I'm tring to convert this date string "2021-12-10T00:00:00" into a Date but when i deserialize it i got this.
Thu Dec 09 19:00:00 COT 2021.
it seems I'm losing one day.
Can anyone help me?
"startDate": "2021-12-10T00:00:00", and the result is this
2021-12-09T19:00:00.000-0500
tl;dr
java.util.Date.from(
LocalDateTime
.parse( "2021-12-10T00:00:00" )
.atZone(
ZoneId.of( "America/Bogota" )
)
.toInstant()
)
Details
I am guessing that you are using the terrible legacy date-time classes such as Date and Calendar. Don’t. Use only java.time class.
Your input string complies with the ISO 8601 standard for date-time formats. The java.time classes use these standard formats by default when parsing/generating strings. So no need to specify a formatting pattern.
LocalDateTime ldt = LocalDateTime.parse( "2021-12-10T00:00:00" ) ;
You said:
I'm tring to convert this date string "2021-12-10T00:00:00" into a Date
That does not make sense.
I assume by “Date”, you meant a java.until.Date. That legacy class represents a moment, a point on the timeline as seen in UTC, that is, with an offset from UTC of zero hours-minutes-seconds.
But your input lacks an indicator of time zone or offset. For example, if that string was meant to represent a moment as seen in UTC, it should have had a Z appended.
I am guessing that you assume the input was meant to represent a moment as seen in Colombia.
ZoneId z = ZoneId.of( "America/Bogota" ) ;
ZonedDateTime zdt = ldt.atZone( z ) ;
Now we have determined a moment as seen through the wall-clock time used by the people of Colombia.
Generally best to avoid java.util.Date class. But if you must, to interoperate with legacy code not yet updated to java.time, you can convert.
java.util.Date d = Date.from( zdt.toInstant() ) ;
Your start date is 2021-12-10 00:00:00 GMT+0 and your result is 2021-12-09 19:00:00 GMT-5. These times are the same. You can pass a Locale to your SimpleDataFormat constructor to be able to configure the used time zone.
Related
I am having a string value in format "Tue Apr 30 00:00:00 UTC 1996";
. I want this value to be converted into a timestamp field in "30-APR-96 05:30:00.000000000 AM"
What i tried here is
DateFormat formatter = new SimpleDateFormat("E MMM dd HH:mm:ss Z yyyy");
Date date = formatter.parse(str);
Timestamp ts = new Timestamp(date getTime());
SimpleDateFormat fo = new SimpleDateFormat("dd-MMM-yy hh:mm:ss.SSSSSSSSS a");
fo.format(ts);
//When i try here Timestamp.valueOf(fo.format(ts));
I am getting an exception Timestamp format must be yyyy-mm-dd hh:mm:ss[.ffffff]
In DB when i see i have the type as Timestamp and values are stored in "30-APR-96 05:30:00.000000000 AM"
tl;dr
myPreparedStatement.setObject(
… ,
ZonedDateTime
.parse(
"Tue Apr 30 00:00:00 UTC 1996" ,
DateTimeFormatter
.ofPattern( "E MMM dd HH:mm:ss zzz uuuu" )
.withLocale( Locale.US )
)
.toOffsetDateTime()
);
Avoid legacy date-time classes.
You are using terribly flawed date-time classes that were years ago supplanted by the modern java.time classes defined in JSR 310. Never use Date, Calendar, SimpleDateFormat, etc.
In particular, your input data uses a resolution of nanoseconds, while thé java.util.Date class is limited to milliseconds.
ISO 8601
Let me mention that data exchange should be using standard ISO 8601 formats for date-time values transmitted as text. The standard formats are concise, unambiguous, and easily read by both humans and machines.
Use custom or localized formats only for presentation to user, not for storage and data exchange.
So, "Tue Apr 30 00:00:00 UTC 1996" would be 1996-04-30T00:00:00Z where Z is short for +00:00, an offset from UTC of zero hours-minutes-seconds.
java.time
The java.time classes do support the nanoseconds resolution needed for your data inputs.
Define a formatting pattern to match the input. Specify a Locale to determine the human language and cultural norms used in translation.
Locale locale = new Locale( "en" , "IN" ) ;
DateTimeFormatter f = DateTimeFormatter.ofPattern( "E MMM dd HH:mm:ss zzz uuuu" ) ;
Parse your input.
ZonedDateTime zdt = ZonedDateTime.parse( "Tue Apr 30 00:00:00 UTC 1996" , f ) ;
See this code run live at IdeOne.com.
zdt.toString(): 1996-04-30T00:00Z[UTC]
Apparently you want to see this moment as it appears in the India 🇮🇳 time zone. Specify the desired time zone as a ZoneId object.
ZoneId z = ZoneId.of( "Asia/Kolkata" ) ;
Apply the zone to get another ZonedDateTime object.
ZonedDateTime zdtKolkata = zdt.withZoneSameInstant( z ) ;
See this code run live at IdeOne.com.
zdtKolkata.toString(): 1996-04-30T05:30+05:30[Asia/Kolkata]
You asked for a java.sql.Timestamp object. That class is one of the terrible legacy classes to avoid. And it is unnecessary. JDBC 4.2 and later requires that a JDBC driver support java.time.
To write a moment to a database, we need to use OffsetDateTime rather than ZonedDateTime. The SQL standard does not specify time zones, only offsets.
And, there is no need for the India-specific value. Most databases saving into a column of a type akin to the SQL standard type TIMESTAMP WITH TIME ZONE will automatically adjust inputs into UTC (an offset of zero).
OffsetDateTime odt = zdt.toOffsetDateTime() ;
myPreparedStatement.setObject( … , odt ) ;
Retrieval.
OffsetDateTime odt = myResultSet.getObject( … , OffsetDateTime.class ) ;
Beware: Verify the data type of your database column. If you are using a column of a type akin to the SQL standard type TIMESTAMP WITHOUT TIME ZONE, you are using the wrong type. That type cannot represent a moment, a specific point on the timeline. Such a type has only a date with time of day, but lacks the context of an offset.
Hi I want to convert String value 2020-12-16T19:20:30+01:00 UTC to either LocalDateTime or ZonedDateTime in java
I tried solution:
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("YYYY-MM-DDThh:mm:ssTZD", Locale.ENGLISH);
final String responseTimeStamp = "2020-12-16T19:20:30+01:00 UTC";
ZonedDateTime zdt = ZonedDateTime.parse(responseTimeStamp, dtf);
Which gives me the error
Exception in thread "main" java.lang.IllegalArgumentException: Unknown pattern letter: T at java.base/java.time.format.DateTimeFormatterBuilder.parsePattern(DateTimeFormatterBuilder.java:1815) at java.base/java.time.format.DateTimeFormatterBuilder.appendPattern(DateTimeFormatterBuilder.java:1712) at java.base/java.time.format.DateTimeFormatter.ofPattern(DateTimeFormatter.java:588) at learning/learning.SpringDemo.main(SpringDemo.java:21)
tl;dr
OffsetDateTime
.parse(
"2020-12-16T19:20:30+01:00 UTC"
.replace( " UTC" , "" )
)
.withZoneSameInstant(
ZoneId.of( "America/Edmonton" )
)
ISO 8601
Your input string:
2020-12-16T19:20:30+01:00 UTC
… nearly complies with the ISO 8601 standard for data-exchange date-time formats. To fully comply, delete the SPACE and UTC from the end. The +01:00 at the end means “one hour ahead of UTC", so the UTC at the end is redundant.
String input = "2020-12-16T19:20:30+01:00 UTC".replace( " UTC" , "" ) ;
Offset versus time zone
Parse as an OffsetDateTime because your input indicates small offset from UTC, not a time zone.
An offset is merely a number of hours-minutes-seconds ahead/behind the prime meridian of UTC. A time zone is much more. A time zone is a history of the past, present, and future changes to the offset used by the people of a particular region as decided by their politicians. A time zone has a name in format of Continent/Region, such as Europe/Paris and Africa/Tunis.
OffsetDateTime
So the other Answer’s suggestion to use ZonedDateTime for parsing is misguided as no time zone is indicated. Your input has only an offset, therefore use OffsetDateTime.
No need to specify a formatting pattern. Our modified input complies with ISO 8601, and the java.time classes use those standard formats by default when parsing/generating strings.
OffsetDateTime odt = OffsetDateTime.parse( input ) ;
LocalDateTime
You asked how to get a LocalDateTime. That class lacks any concept of offset or time zone. So beware, if you convert from OffsetDateTime, you are discarding valuable information.
So while I don’t recommend doing this, here is the code.
LocalDateTime ldt = odt.toLocalDateTime() ;
ZonedDateTime
You asked how to adjust into a time zone.
To adjust from our offset to a time zone, merely specify the desired time zone.
ZoneId z = ZoneId.of( "Asia/Tokyo" ) ;
ZonedDateTime zdt = odt.withZoneSameInstant( z ) ;
There are a few things wrong with your code. I suggest you to take a look at the DateTimeFormatter documentation.
YYYY -> This means week-based-year, you can have a look here to see the difference between year-of-era. So you should be using yyyy.
DD -> This means day-of-year, so December 16 is equal to 350. In your case you want to use dd, day-of-month.
T -> There isn't a pattern for T, so you can put it like a text to formmat you date 'T'
TZD -> I don't know what you are trying to use here and I couldn't find the patter +03:00 UTC, you can try to use O
So your final pattern should be "yyyy-MM-dd'T'HH:mm:ssO". It doens't work for UTC and I couldn't find it on ZoneId list, maybe because UTC is +00:00 already, so UTC+01:00 is equal to +01:00.
After a lot of working understanding the pattern, I found out that you are looking for ISO_ZONED_DATE_TIME, so you could just change your code like below:
DateTimeFormatter dtf = DateTimeFormatter.ISO_ZONED_DATE_TIME;
final String responseTimeStamp = "2020-12-16T19:20:30+01:00";
ZonedDateTime zdt = ZonedDateTime.parse(responseTimeStamp, dtf);
I am using ZonedDateTime to convert GMT timestamp to America/Phoenix timestamp,
Here is my implementation
public static ZonedDateTime convertGMTTimestampToLocalTime(Timestamp gmtTime, String timeZone) throws Exception
{
ZonedDateTime atZone =Instant
.ofEpochMilli( // Parse a count of milliseconds since 1970-01-01T00:00Z.
gmtTime.getTime()
) // Returns a `Instant` object.
.atZone(
ZoneId.of( timeZone )
); // Returns a `ZonedDateTime` object.
return atZone;
}
This gives proper result when I test in local but when I test it remotely (server with docker container) it gives wrong result.
If I do a transaction at 6-Jan-2021 8:00PM (America/Phoenix) it should give 6-Jan-2021 instead it display 7-Jan-2021. My server is in MST
What am I missing, isn't the server supposed to print the date according to the specified time zone. Any help would be appreciated. Thanks.
Avoid legacy date-time classes
Never use the terrible legacy classes Timestamp, Date, Calendar, etc. These were years ago supplanted by the modern java.time classes defined in JSR 310.
Use java.time
If handed an object of that class, immediately convert to Instant. The Instant class represents a moment as seen in in UTC, with an offset of zero hours-minutes-seconds.
Instant instant = myTimestamp.toInstant() ;
Adjust to your desired time zone.
ZoneId z = ZoneId.of( "America/Phoenix" ) ;
ZonedDateTime zdt = instant.atZone( z ) ;
Extract the date portion.
LocalDate ld = zdt.toLocalDate() ;
Generate text representing the value of that LocalDate object.
String iso8601 = ld.toString() ;
Or automatically localize.
Locale locale = Locale.US ;
DateTimeFormatter f = DateTimeFormatter.ofLocalizedDate( FormatStyle.SHORT ).
String localized = ld.format( f ) ;
You said:
My server is in MST
First, servers should generally be kept to a default time zone of UTC, that is no zone, just an offset of zero hours-minutes-seconds.
Secondly, as a Java programmer, write your code without depending on the default time zone. Specify explicitly the desired time zone by passing the otherwise optional time zone argument to the various date-time methods.
Thirdly, MST is not a real time zone.
I'm getting windows time zone as input, which i want to convert it to UTC time in Java. some windows time zone are not same as Java's.
For example:
Windows time zone = MPST(Malay Peninsula Standard Time)
equivalent Java time zone = SGT (Singapore Standard Time)
My input be like - 13/01/2020 10:46:10 MPST. so, when i'm trying to convert this date format to UTC, i'm getting java.text.ParseException: Unparseable date: "13/01/2020 10:46:10 MPST"
Please, help.
Thanks in advance
Avoid pseudo-codes for time zones
The 2-4 letter pseudo-codes often seen in the media are not actual time zones. Values such as IST, PST, CST, and your MPST are not standardized, and are not even unique!
Use only proper time zone names in the format of Continent/Region. See this possibly-outdated list at Wikipedia.
ZoneId z = ZoneId.of( "Asia/Kuala_Lumpur" ) ;
ZonedDateTime now = ZonedDateTime.now( z ) ;
020-01-15T08:02:26.612494+08:00[Asia/Kuala_Lumpur]
See that code run live at IdeOne.com.
The DateTimeFormatter class will try to guess the real time zone intended by the use of a 2-4 letter pseudo-zone. For example:
String input = "13/01/2020 10:46:10 PST" ;
DateTimeFormatter f = DateTimeFormatter.ofPattern( "dd/MM/uuuu HH:mm:ss zz") ;
ZonedDateTime zdt = ZonedDateTime.parse( input , f ) ;
System.out.println( "zdt.toString(): " + zdt ) ;
zdt.toString(): 2020-01-13T10:46:10-08:00[America/Los_Angeles]
But guessing MPST fails with a runtime error.
ISO 8601
In any such case as either PST or MPST, you really should go back to the source of the data. Educate those people about the ISO 8601 standard designed for the purpose of exchanging date-time values as text.
By the way, the toString method of the ZonedDateTime class seen above extends the ISO 8601 standard format by wisely appending the name of the time zone in square brackets.
This may be an extremely simple typo that I have in my code, but I just can't make it work no matter what I do.
I have the following code:
String date="2014-05-22";
String time="09:09:04.145"
String dateAndTime=date.concat(" "+ time);
DateFormat convertDate=new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss:SSSZ");
Date dateOfMeasurement=convertDate.parse(dateAndTime);
I have tried using yyyy-MM-dd'T'HH:mm:ss:SSSZ and yyyy-MM-dd HH:mm:ss:SSS for the formatting, but nothing works.
What am I doing wrong?
Thank you very much.
java.time
You are using troublesome old legacy date-time classes now supplanted by the java.time classes.
ISO 8601
Your inputs happen to comply with ISO 8601 standard. The java.time classes use ISO 8601 formats by default when parsing/generating Strings that represent date-time values. So no need to specify a formatting pattern.
LocalDate ld = LocalDate.parse( "2014-05-22" );
LocalTime lt = LocalTime.parse( "09:09:04.145" );
LocalDateTime ldt = LocalDateTime.of( ld , lt );
Time zones
A LocalDateTime has no concept of time zone or offset-from-UTC. So it does not represent a moment on the timeline.
For an actual moment, assign a time zone. Perhaps you intended the inputs to represent a moment in UTC.
OffsetDateTime odt = ldt.atOffset( ZoneOffset.UTC );
Or perhaps you know from the context that another particular time zone was intended.
ZoneId z = ZoneId.of( "America/Montreal" );
ZonedDateTime zdt = ldt.atZone( z );
Strings
The format you were attempting to assemble is also defined by the ISO 8601 standard. Simply call toString to generate such a value.
An Instant is a basic building-block class in java.time, representing a moment on the timeline in UTC with a resolution up to nanoseconds.
String output = zdt.toInstant().toString(); // 2016-09-08T02:46:15Z
The ZonedDateTime extends standard format by wisely appending the name of the time zone in square brackets.
String output = zdt.toString(); // 2016-09-07T23:46:15-03:00[America/Montreal]
DateFormat convertDate=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
Date dateOfMeasurement=convertDate.parse(dateAndTime);