This question already has answers here:
How to Parse Date from GMT TimeZone to IST TimeZone and Vice Versa in android
(4 answers)
SimpleDateFormat returns wrong time zone during parse
(2 answers)
DateFormat parse - not return date in UTC
(1 answer)
Closed 3 years ago.
I searched for solutions but still not working ,I'm trying to convert the date object's local timezone to UTC +0 , but when i format the date object to UTC it's working . but when I want to convert the converted string to date again, the format changes and UTC goes back to GMT+8 before i store it in the fire store. what is the problem in the code?
this is the current date object that i get
Calendar time = Calendar.getInstance();
time.setTimeZone(TimeZone.getTimeZone("UTC"));
Date current_time = time.getTime();
if printed
Thu Aug 22 10:09:55 GMT+08:00 2019
then i convert it to UTC
String dismissal_time_firestore;
Log.i(TAG, "Current time when swiped from phone time.getTime() "+current_time);
SimpleDateFormat dateFormat = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss Z");
dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
dismissal_time_firestore = dateFormat.format(current_time);
got this
Thu, 22 Aug 2019 02:09:55 +0000
but then when i convert this string to a date object
try {
current_time = dateFormat.parse(dismissal_time_firestore);
} catch (ParseException e) {
e.printStackTrace();
}
i got this
Thu Aug 22 10:09:55 GMT+08:00 2019
You are using terrible date-time classes that were supplanted years ago by the modern java.time classes defined in JSR 310.
Your main problem is not understanding that the Date::toString method lies to you. It dynamically applies the JVM’s current time zone to the moment in UTC while generating the text. One of many reasons to never use this class.
Get current moment in UTC.
Instant instant = Instant.now() ;
View that moment as seen in the wall-clock time used by the people of a particular region (a time zone).
ZoneId z = ZoneId.of( "America/Montreal" ) ;
ZonedDateTime zdt = instant.atZone( z ) ;
Generate text for display to user.
DateTimeFormatter f = DateTimeFormatter.ofLocalizedDateTime( FormatStyle.FULL ).withLocale( Locale.CANADA_FRENCH ) ;
String output = zdt.format( f ) ;
You talk about parsing formatted strings. Bad idea. Think of textual representations of date-time values only as outputs, not inputs. Collecting date-time inputs should be done by using date-time widgets, not typed text.
When storing or exchanging date-time values as text, always use ISO 8601 standard formats. The java.time classes use ISO 8601 formats by default when parsing/generating strings. So no need to specify any formatting pattern. Just call parse/toString. Example: Instant.now().toString() and Instant.parse( "2020-01-23T12:34:56.123456Z" ).
I cannot help further as you did not really say what you were trying to accomplish.
All of this has been covered many many times on Stack Overflow. So search to learn more. And search before posting.
Related
I've made a simple method which is used to convert a timestamp retrieved from a database into a LocalDate. However for some reason I keep getting the wrong day in the conversion. I've shared the code below.
private LocalDate getLocalDateFromTimeStamp(Row row, String key){
return LocalDate.parse(row.getTimestamp(key).toInstant().atZone(ZoneOffset.UTC).toLocalDate().format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
}
So the date I'm expecting is 2022-12-21 but what I get is 2022-12-22.
When I debug and check what
row.getTimestamp(key)
gets me a Date object of Wed Dec 21 20:47:46 CST 2022 which is what I expect.
When I check what
row.getTimestamp(key).toInstant()
does, I get "2022-12-22T02:47:46.299Z". And I think this is where the problem is popping up and I'm not sure why it's happening. The LocalDate that's returned by the method is "2022-12-22".
If anyone could shine a light on this I'd really appreciate it as I'm lost as to why this is happening.
Try it like this. Check out DateTimeFormatter for details on the following arguments.
String date = "Wed Dec 21 20:47:46 CST 2022";
EEE three letter day of week
MMM three letter month
dd integer day
HH:mm:ss time using 24 hour clock
z time zone name (CST)
yyyy year
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("EEE MMM dd HH:mm:ss z yyyy");
LocalDate dt = LocalDateTime.parse(date, dtf).toLocalDate();
System.out.println(dt);
prints
2022-12-21
Updated
If you actually have an instance of Date you might try the following:
LocalDate ldt = LocalDate.ofInstant(date.toInstant(),
ZoneId.systemDefault());
tl;dr
Avoid unnecessary string manipulation. Use date-time types for date-time values.
myResultSet
.getObject( … , OffsetDateTime.class ) // For any database column of a data type akin to the SQL standard type of `TIMESTAMP WITH TIME ZONE`.
.toLocalDate() // Extract the date portion from the returned `OffsetDateTime` object.
.toString() // Generate text in standard ISO 8601 format.
Details
The Timestamp class is part of the terrible date-time classes that are now legacy. Use only their replacements, the modern java.time classes defined in JSR 310.
Instead of Timestamp, use OffsetDateTime with JDBC 4.2 and later. Do this for any database column of a data type akin to the SQL standard type of TIMESTAMP WITH TIME ZONE.
OffsetDateTime odt = myResultSet.getObject( … , OffsetDateTime.class ) ;
Your Question is not clear, but you seem to want the date portion of that moment as seen with an offset from UTC of zero hours-minutes-seconds.
The retrieved OffsetDateTime is likely already in UTC. But let’s be sure:
OffsetDateTime odtUtc = odt.withOffsetSameInstant( ZoneOffset.UTC ) ;
Extract the date portion.
LocalDate localDate = odtUtc.toLocalDate() ;
To generate text in standard ISO 8601 format, call toString.
String output = localDate.toString() ;
We are using Java8 in our project.I have startDate in String format "2021-12-31" which I am receiving from from an 3RD party.
I have to pass it to our consumer via our model.Model accepts java.util.Date and the format should be yyyy-MM-dd.
I wrote the below code:
String strDate="2021-12-31";
DateFormat df=new SimpleDateFormat("yyyy-MM-dd");
java.util.Date parsedDate=(Date)df.parse(strDate);
Expected output : parsedDate = 2021-12-31
Actual Output: parsedDate= Tue Dec 07 00:00:00 GMT +5.30 2021.
Please help.
No, Tue Dec 07 00:00:00 GMT +5.30 2021 could not be the result of your code. Even accounting for time zone issues, the result could not be different by weeks. Please take more care when posting here, to not waste people's time.
The actual results of your code will be something more like the following. See for yourself.
Fri Dec 31 00:00:00 GMT 2021
Or, setting the JVM’s current default time zone to Asia/Kolkata:
Fri Dec 31 00:00:00 IST 2021
Notice that those two results are different moments, several hours apart. The day starts earlier in India than at UTC/GMT prime meridian. So the results of this code vary by the current default time zone — not good!
java.time
You are using terrible date-time classes that were years ago supplanted by the modern java.time classed defined in JSR 310.
Your input string complies with the ISO 8601 standard used by default in the java.time classes when parsing/generating text. So no need to specify a formatting pattern.
For a date-only value, without time of day, and without time zone or offset-from-UTC, use LocalDate.
LocalDate ld = LocalDate.parse( "2021-12-31" ) ;
You said:
Model accepts java.util.Date and the format should be yyyy-MM-dd
Well, (a) that is unfortunate, (b) a Date object does not have a "format", it has a date-time value rather than text, and (c) a java.util.Date represents a moment, a specific point on the timeline rather than a date-only. A Date object represents a date with time-of-day as seen in UTC (an offset from UTC of zero hours-minutes-seconds).
The best solution is to fix your design to use proper types.
If you cannot fix the faulty design and must employ a hack, then perhaps you could use the first moment of the day on that date as seen in UTC.
ZonedDateTime zdt = ld.atStartOfDay( ZoneOffset.UTC ) ;
Instant instant = zdt.toInstant() ;
Convert from modern class to legacy class by calling new conversion methods added to the old classes.
java.util.Date d = Date.from( instant ) ;
Dump to console.
System.out.println( "ld.toString(): " + ld ) ;
System.out.println( "zdt.toString(): " + zdt ) ;
System.out.println( "instant.toString(): " + instant ) ;
System.out.println( "d.toString(): " + d ) ;
See this code run live at IdeOne.com.
ld.toString(): 2021-12-31
zdt.toString(): 2021-12-31T00:00Z
instant.toString(): 2021-12-31T00:00:00Z
d.toString(): Fri Dec 31 00:00:00 GMT 2021
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.
This question already has answers here:
want current date and time in "dd/MM/yyyy HH:mm:ss.SS" format
(11 answers)
display Java.util.Date in a specific format
(11 answers)
Closed 2 years ago.
I get Date as java.util.Date(not String) : (java.util.Date) Mon Jul 13 00:00:00 IST 2020
I want to convert it to : 2020-07-13T00:00 format==>("yyyy-MM-dd'T'HH:mm") but as DATE not String.
I tried following code:
Date scheduleDate=details.getScheduledDate(); // This value is fetched from object passed-- [scheduleDate = (java.util.Date) Mon Jul 13 00:00:00 IST 2020]
SimpleDateFormat sd = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm");
sd.setTimeZone(TimeZone.getTimeZone("Asia/Kolkata"));
String dateFormat=sd.format(scheduleDate); //Here I get [dateFormat = (java.lang.String) "2020-07-13T00:00"]
Date date = sd.parse(dateFormat); //[date = (java.util.Date) Mon Jul 13 00:00:00 IST 2020]
I observed that string format has correct(as expected ) value but the value changes back when I convert it to java.util.date.
Does java.util.Date support yyyy-MM-dd'T'HH:mm format ?
If yes, Can anyone suggest me with any good approach/direction/topics/library to look into.
Thank You..
tl;dr
Convert from legacy class to modern class. Adjust from UTC to a time zone. Generate text in standard ISO 8601. We omit the context of time zone or offset in our output because you so requested, against my recommendation.
myJavaUtilDate
.toInstant()
.atZone( ZoneId.of( "Asia/Kolkata" ) )
.truncatedTo( ChronoUnit.MINUTES )
.format( DateTimeFormatter.ISO_LOCAL_DATE_TIME )
I expect using UTC and including the offset would be wiser.
myJavaUtilDate
.toInstant()
.toString()
Details
Date-time objects do not have a format, only text has a format.
Use java.time classes, never java.util.Date.
Convert your legacy Date object to its modern replacement, java.time.Instant.
Instant instant = myJUDate.toInstant() ;
Adjust from UTC to your desired time zone.
ZoneId z = ZoneId.of( "Asia/Kolkata" ) ;
ZonedDateTime zdt = instant.atZone( z ) ;
Apparently you do not care about the the second of minute. So let’s truncate that to zero seconds.
ZonedDateTime zdt = zdt.truncatedTo( ChronoUnit.MINUTES ) ;
Generate text in your desired format. Java comes bundled with a formatter already defined for your format.
String output = zdt.format( DateTimeFormatter.ISO_LOCAL_DATE_TIME ) ;
I showed that format because asked. But I do not recommend it. That format fails to indicate a time zone or offset-from-UTC. So if it says noon, the reader does not know if that means noon in Tokyo Japan 🇯🇵, noon in Toulouse France 🇫🇷, or noon in Toledo Ohio Us 🇺🇸 — three very different moments, several hours apart.
When communicating a moment, a specific point on the timeline, textually it is usually best to do so in UTC. And use ISO 8601 standard formats. Commonly a Z is placed on the end to indicate UTC, an offset of zero hours-minutes-seconds.
Instant instant = zdt.toInstant() ;
String output = instant.toString() ;
I have the local date in json input in String format dd-MM-yyyy HH:mm:ss format [let it be any format no issue], have a separate field timezone in header [eg : CST , CDT etc]. In java when i try to create a date with this value and timezone it is getting created with my system [jvm running system] timezone.
I need to persist the exact date and time from input with the input timezone.
How can I do it ?
I even tried with putting date object with #DateTimeFormat in dto instead of string but that did not work.
I want a method like this to get the local date from the input date string and timezone.
public Date getLocalDate(String dateString, String localTimeZone) {
SimpleDateFormat formatter = new SimpleDateFormat("dd-MM-yyyy hh:mm:ss a");
formatter.setTimeZone(TimeZone.getTimeZone(localTimeZone));
return formatter.parse(dateString);
}
Input : dateString : "20-04-2019 20:15:00 AM" localTimeZone : "CDT" .
Expected Output : Date object with value 20-04-2019 20:15:00 AM CDT .
Actual Output : same date with IST-CDT hour difference with IST timezone
There is a misunderstanding about what a Date object really is. It is just a number of milliseconds since '01-01-1970 00:00:00 UTC'. Said differently it is always an UTC date/time and it is implicitely converted in your local time zone by the default formatter when you try to print it.
If you want to store both the instant (ie the UTC date/time) and a time zone, you will have to use a Calendar object. But anyway, if you want to store both the time and the zone in Oracle, you should directly store a string, or a date and a string (for the timezone), because AFAIK, Oracle DATE fields have no notion of a time zone.
java.time
You are using terrible date-time classes that were supplanted years ago by the java.time classes defined in JSR 310.
“CST” and such 2-4 character pseudo-zones are not time zones. They are not standardized and are not even unique! Ex: CST is Central time in North America and also China Standard Time.
True time zones are in format Continent/Region. Ex: Europe/Paris or Africa/Tunis. See list in Wikipedia.
To represent a date and time-of-day in the context of a time zone, use ZonedDateTimeclass.
To store a date-time separate from zone, use LocalDateTime and ZoneId classes.
Database
Your comments indicate a desire to store the current moment in database.
Capture the current moment in UTC.
Instant instant = Instant.now() ;
For use with JDBC 4.2, convert to an OffsetDateTime.
OffsetDateTime odt = instant.atOffset( ZoneOffset.UTC ) ;
Pass to a prepared statement.
myPreparedStatement.setObject( … , odt ) ;
Retrieve.
OffsetDateTime odt = myResultSet.getObject( … , OffsetDateTime.class ) ;