簡體   English   中英

Java 從字符串到 ZonedDateTime 的時間轉換

[英]Java Time conversion from string to ZonedDateTime

您好,我正在嘗試將日期和時間從以 UTC 時間存儲的 SQL 數據庫轉換為我的系統本地時區,該時區將顯示在 JAVAFX 應用程序的表格中。

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);

這是我寫的。 該表正在以 UTC 時間填充,並且未進行轉換。 我沒有收到任何錯誤,但是這個邏輯錯了嗎? 如果是這樣,我該怎么做?

歡迎來到堆棧溢出!

您的代碼有幾個問題:

  • 查看第 3 行和第 4 行並編寫代碼。您實際上並沒有解析為 UTC。
  • 由於您的appointmentStart字符串不包含時區,因此您需要在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());

tl;博士

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 2023 年 1 月 23 日 07:30:55 太平洋北美洲正常時間

細節

CryptoFool答案和 Oliver的答案都朝着正確的方向前進。 但我不喜歡他們在單獨解析日期時間之前直接注入一個偏移量。 我也不喜歡他們在OffsetDateTime更合適的地方使用ZonedDateTime

顯然,您有一個包含日期和時間的輸入字符串,但缺少時區上下文或與 UTC 的偏移量。 例如: "2023-01-23 15:30:55"

String input = "2023-01-23 15:30:55" ; 

該輸入幾乎符合日期時間值的ISO 8601標准格式。 要完全遵守,請將中間的 SPACE 換成T

String modified = input.replace( " " , "T" ) ;

java.time類在解析/生成文本時默認使用 ISO 8601 格式。 因此無需指定格式化模式。

解析為時間日期 object, LocalDateTime object。

LocalDateTime ldt = LocalDateTime.parse( modified );

你說你想假設日期和時間是用來表示一個時刻,與 UTC 的偏移量為零小時-分鍾-秒。 Java 為該偏移量提供了一個常量ZoneOffset.UTC 應用該ZoneOffset以生成OffsetDateTime object。

OffsetDateTime odt = ldt.atOffset( ZoneOffset.UTC );

接下來,您要求從零偏移量進行調整,以查看 JVM 當前默認時區中的同一時刻。 同一時刻,時間軸上的同一點,但掛鍾時間不同。

獲取該默認區域。

ZoneId z = ZoneId.systemDefault() ;

將該ZoneId應用於OffsetDateTime以獲得ZonedDateTime

ZonedDateTime zdt = odt.atZoneSameInstant( z ) ;

以本地化格式生成文本。 指定Locale以用於本地化人類語言和文化規范。

Locale locale = Locale.US;
DateTimeFormatter f = DateTimeFormatter.ofLocalizedDateTime( FormatStyle.FULL ).withLocale( locale );
String output = zdt.format( f );

將所有代碼放在一起。

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 );

轉儲到控制台。

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

可能有一種更巧妙的方法可以做到這一點,但我會這樣做:

// 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);

結果:

2022-12-24 03:00:00

我在太平洋時區,與 UTC 相差 -8 小時,我們看到生成的字符串對於我的本地時區是正確的。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM