Reputation: 51
Hello I am trying to convert a Date and Time from a SQL data base that is being stored in UTC time to my systems Local Time zone that will be displayed in a table in a JAVAFX application.
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
String appointmentStart = rs.getString("Start");
LocalDateTime ldtStart = LocalDateTime.parse(appointmentStart, formatter);
ZonedDateTime zdtStart = ZonedDateTime.of(ldtStart, ZoneId.systemDefault());
appointmentStart = zdtStart.format(formatter);
String appointmentEnd = rs.getString("End");
LocalDateTime ldtEnd = LocalDateTime.parse(appointmentEnd, formatter);
ZonedDateTime zdtEnd = ZonedDateTime.of(ldtEnd, ZoneId.systemDefault());
appointmentEnd = zdtEnd.format(formatter);
This is what I have written. The table is being populated in UTC time and is not converting. I get no errors but is this logic wrong? If so how can I do this?
Upvotes: 5
Views: 18919
Reputation: 29
String date = "2023-1-1 00:00:00" ZonedDateTime.parse(date, DateTimeFormatter.ISO_DATE_TIME)
ISO_DATE_TIME parses with offset and zone if available like this: 2011-12-03T10:15:30+01:00[Europe/Paris]
Upvotes: 1
Reputation: 340230
DateTimeFormatter // Class for generating text that represents the value of a date-time object.
.ofLocalizedDateTime( FormatStyle.FULL ) // Automatically localize the generated text.
.withLocale( Locale.FRANCE ) // Whatever human language and cultural norms are best for presentation to this particular user. Or call `Locale.getDefault`.
.format( // Generate text.
LocalDateTime // Represent a date with a time-of-day. Does *not* represent a moment as it lacks the context of a time zone or offset from UTC.
.parse( // Interpret text as a date-time value.
"2023-01-23 15:30:55"
.replace( " " , "T" ) // Comply with ISO 8601 format. Then we can proceed with parsing without bothering to specify a formatting pattern.
) // Returns a `LocalDateTime` object.
.atOffset( ZoneOffset.UTC ) // Returns a `OffsetDateTime` object.
.atZoneSameInstant(
ZoneId.systemDefault()
) // Returns a `ZonedDateTime` object.
) // Return a `String` object.
lundi 23 janvier 2023 à 07:30:55 heure normale du Pacifique nord-américain
The Answer by CryptoFool and the Answer by Oliver are headed in the right direction. But I do not like that they directly inject an offset before parsing the date-time alone. I also do not like that they use ZonedDateTime
where OffsetDateTime
is more appropriate.
Apparently you have an input string with a date and a time-of-day but lacking the context of a time zone or offset from UTC. For example: "2023-01-23 15:30:55"
.
String input = "2023-01-23 15:30:55" ;
That input nearly complies with the ISO 8601 standard format for date-time values. To fully comply, swap that SPACE in the middle with a T
.
String modified = input.replace( " " , "T" ) ;
The java.time classes use ISO 8601 formats by default when parsing/generating text. So no need to specify a formatting pattern.
Parse as a date-with-time object, an LocalDateTime
object.
LocalDateTime ldt = LocalDateTime.parse( modified );
You said you want to assume that date and time is intended to represent a moment as seen with an offset from UTC of zero hours-minutes-seconds. Java offers a constant for that offset, ZoneOffset.UTC
. Apply that ZoneOffset
to produce an OffsetDateTime
object.
OffsetDateTime odt = ldt.atOffset( ZoneOffset.UTC );
Next you asked to adjust from that offset of zero to view the same moment in the JVM’s current default time zone. Same moment, same point on the timeline, but different wall-clock time.
Get that default zone.
ZoneId z = ZoneId.systemDefault() ;
Apply that ZoneId
to the OffsetDateTime
to get a ZonedDateTime
.
ZonedDateTime zdt = odt.atZoneSameInstant( z ) ;
Generate text in localized format. Specify the Locale
to use in localizing for human language and cultural norms.
Locale locale = Locale.US;
DateTimeFormatter f = DateTimeFormatter.ofLocalizedDateTime( FormatStyle.FULL ).withLocale( locale );
String output = zdt.format( f );
Pull all that code together.
String input = "2023-01-23 15:30:55";
String modified = input.replace( " " , "T" );
LocalDateTime ldt = LocalDateTime.parse( modified );
OffsetDateTime odt = ldt.atOffset( ZoneOffset.UTC );
ZoneId z = ZoneId.systemDefault();
ZonedDateTime zdt = odt.atZoneSameInstant( z );
Locale locale = Locale.US;
DateTimeFormatter f = DateTimeFormatter.ofLocalizedDateTime( FormatStyle.FULL ).withLocale( locale );
String output = zdt.format( f );
Dump to console.
input = 2023-01-23 15:30:55
modified = 2023-01-23T15:30:55
ldt = 2023-01-23T15:30:55
odt.toString() = 2023-01-23T15:30:55Z
z.toString() = America/Los_Angeles
zdt.toString() = 2023-01-23T07:30:55-08:00[America/Los_Angeles]
output = Monday, January 23, 2023 at 7:30:55 AM Pacific Standard Time
Upvotes: 7
Reputation: 1655
Welcome to Stack Overflow!
There are a couple issues with your code:
appointmentStart
string doesn't include the timezone, you need to specify that in your DateTimeFormatter
.DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")
.withZone(ZoneOffset.UTC);
String appointmentStart = rs.getString("Start");
// UTC
ZonedDateTime ldtStart = ZonedDateTime.parse(appointmentStart, formatter);
// Local.
ZonedDateTime start = ldtStart.withZoneSameInstant(ZoneId.systemDefault());
Upvotes: 1
Reputation: 23139
There may be a slicker way to do this, but here's how I would do this:
// We have an unzoned datetime String that we assume is in UTC
String appointmentStart = "2022-12-24 11:00:00";
// Add a UTC time (+0) offset to the end of our String, and parse it to get a UTC-zoned ZonedDateTime
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ssZ");
ZonedDateTime utcStart = ZonedDateTime.parse(appointmentStart + "+0000", formatter);
// Convert to the local timezone
ZonedDateTime localZonedStart = utcStart.withZoneSameInstant(ZoneId.systemDefault());
// Define a formatter that doesn't include the time zone
DateTimeFormatter formatter2 = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
// Convert the local time to a String
String localZonedStartString = localZonedStart.format(formatter2);
// Print the resulting String
System.out.println(localZonedStartString);
Result:
2022-12-24 03:00:00
I'm in Pacific time zone, which is offset by -8 hours from UTC, and we see that the resulting string is correct for my local time zone.
Upvotes: 0