且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

将日期从一个时区转换为java中的其他时区

更新时间:2023-11-29 12:49:40

tl ; dr



使用现代 java.time 类,特别是 ZonedDateTime ZoneId 。请参阅 Oracle教程

ZonedDateTime                         // Represent a date and time-of-day in a specific time zone.
.now(                                 // Capture the current moment as seen in the wall-clock time used by the people of a particular region (a time zone). 
    ZoneId.of( "Pacific/Auckland" )   // Specify time zone using proper name in `Continent/Region` format. Never use 3-4 letter pseudo-zone such as IST or PST or EST.
)                                     // Returns a `ZonedDateTime` object.
.withZoneSameInstant(                 // Adjust from one time zone to another. Same point on the timeline, same moment, but different wall-clock time.
    ZoneId.of( "Africa/Tunis" )       
)                                     // Returns a new fresh `ZonedDateTime` object rather than altering/"mutating" the original, per immutable objects pattern.
.toString()                           // Generate text in standard ISO 8601 format, extended to append name of zone in square brackets.




2018-09-18T21:47:32.035960 + 01:00 [非洲/突尼斯]

2018-09-18T21:47:32.035960+01:00[Africa/Tunis]

对于UTC,请致电 ZonedDateTime :: toInstant

For UTC, call ZonedDateTime::toInstant.

避免使用这三个字母的时区代码。它们既不标准也不独特。例如,您使用IST可能意味着印度标准时间,爱尔兰标准时间以及其他人。

Avoid those three-letter time zone codes. They are neither standardized nor unique. For example, your use of "IST" may mean India Standard Time, Irish Standard Time, and maybe others.

使用正确的时区名称。时区及其名称的定义经常更改,因此请保持您的来源最新。例如,旧的亚洲/加尔各答现在是亚洲/加尔各答。而不只是名字;***因改变时区的规则/行为而臭名昭着,偶尔会在最后一刻。

Use proper time zone names. The definition of time zones and their names change frequently, so keep your source up-to-date. For example the old "Asia/Calcutta" is now "Asia/Kolkata". And not just names; governments are notorious for changing the rules/behavior of a time zone, occasionally at the last minute.

避免使用捆绑的java.util.Date和Calendar类。它们是出了名的麻烦,并将在Java 8中被新的 java.time。*包(灵感来自 Joda-Time )。

Avoid using the bundled java.util.Date and Calendar classes. They are notoriously troublesome and will be supplanted in Java 8 by the new java.time.* package (which was inspired by Joda-Time).

学会以UTC而不是自己的教区时区思考和工作。记录,数据交换和数据存储通常应以UTC格式完成。

Learn to think and work in UTC rather than your own parochial time zone. Logging, data-exchange, and data-storage should usually be done in UTC.

Instant instant = Instant.now() ;  // Capture the current moment in UTC.




instant.toString():2018-09-18T20:48: 43.354953Z

instant.toString(): 2018-09-18T20:48:43.354953Z



ZonedDateTime



调整为时区。同一时刻,时间轴上的同一点,不同的挂钟时间。应用 ZoneId (时区)获取 ZonedDateTime object。

ZonedDateTime

Adjust into a time zone. Same moment, same point on the timeline, different wall-clock time. Apply a ZoneId (time zone) to get a ZonedDateTime object.

ZoneId zMontreal = ZoneId.of( "America/Montreal" ) ;  
ZonedDateTime zdtMontreal = instant.atZone( zMontreal ) ;  // Same moment, different wall-clock time.

我们可以使用 Instant 再次调整>或 ZonedDateTime

ZoneId zKolkata = ZoneId.of( "Asia/Kolkata" ) ;
ZonedDateTime zdtKolkata = zdtMontreal.withZoneSameInstant​( zKolkata ) ;



ISO 8601



致电 toString 都会生成标准 ISO 8601 一个>班级。 ZonedDateTime 类通过在方括号中附加时区名称来明智地扩展标准。

ISO 8601

Calling toString on any of these classes produce text in standard ISO 8601 class. The ZonedDateTime class extends the standard wisely by appending the name of the time zone in square brackets.

交换日期时-time值作为文本,始终使用ISO 8601格式。不要使用问题中所示的自定义格式或本地化格式。

When exchanging date-time values as text, always use ISO 8601 formats. Do not use custom formats or localized formats as seen in your Question.

java.time 类默认使用标准格式来解析和生成字符串。

The java.time classes use the standard formats by default for both parsing and generating strings.

Instant instant = Instant.parse( "2018-01-23T01:23:45.123456Z" ) ;

使用标准格式可以避免在问题中看到的所有混乱的字符串操作。

Using standard formats avoids all that messy string manipulation seen in the Question.

你总是可以拿一个 ZonedDateTime 通过提取 Instant 返回UTC。

You can always take a ZonedDateTime back to UTC by extracting a Instant.

Instant instant = zdtKolkata.toInstant() ;



DateTimeFormatter



要以其他格式表示您的日期时间值,搜索 DateTimeFormatter 类的Stack Overflow。你会发现很多例子和讨论。

DateTimeFormatter

To represent your date-time value in other formats, search Stack Overflow for DateTimeFormatter class. You will find many examples and discussions.

更新: Joda-Time 项目现在在维护模式下,建议迁移到 java.time 类。我将此部分保留为历史记录。

UPDATE: The Joda-Time project is now in maintenance-mode, and advises migration to the java.time classes. I am leaving this section intact as history.

谨防java.util.Date对象看起来他们有一个时区,但实际上并没有。在Joda-Time, DateTime 确实知道它指定的时区。通常应指定所需的时区。否则,将分配JVM的默认时区。

Beware of java.util.Date objects that seem like they have a time zone but in fact do not. In Joda-Time, a DateTime does indeed know its assigned time zone. Generally should specify a desired time zone. Otherwise, the JVM's default time zone will be assigned.

Joda-Time主要使用不可变对象。不是修改实例,而是创建新的新实例。当调用 toDateTime ,返回一个新的DateTime实例,原始对象保持不变。

Joda-Time uses mainly immutable objects. Rather than modify an instance, a new fresh instance is created. When calling methods such as toDateTime, a new fresh DateTime instance is returned leaving the original object intact and unchanged.

//DateTime now = new DateTime(); // Default time zone automatically assigned.

// Convert a java.util.Date to Joda-Time.
java.util.Date date = new java.util.Date();
DateTime now = new DateTime( date );  // Default time zone automatically assigned.

DateTimeZone timeZone = DateTimeZone.forID( "Asia/Kolkata" );
DateTime nowIndia = now.toDateTime( timeZone );

// For UTC/GMT, use built-in constant.
DateTime nowUtcGmt = nowIndia.toDateTime( DateTimeZone.UTC );

// Convert from Joda-Time to java.util.Date.
java.util.Date date2 = nowIndia.toDate();

转储到控制台......

Dump to console…

System.out.println( "date: " + date );
System.out.println( "now: " + now );
System.out.println( "nowIndia: " + nowIndia );
System.out.println( "nowUtcGmt: " + nowUtcGmt );
System.out.println( "date2: " + date2 );

运行时...

date: Sat Jan 25 16:52:28 PST 2014
now: 2014-01-25T16:52:28.003-08:00
nowIndia: 2014-01-26T06:22:28.003+05:30
nowUtcGmt: 2014-01-26T00:52:28.003Z
date2: Sat Jan 25 16:52:28 PST 2014






关于 java.time



java.time 框架内置于Java 8及更高版本中。这些类取代了麻烦的旧遗留日期时间类,例如 java.util.Date 日历 ,& SimpleDateFormat


About java.time

The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.

Joda-Time 项目,现已进入维护模式 ,建议迁移到 java.time classes。

The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.

要了解更多信息,请参阅 Oracle Tutorial 。并搜索Stack Overflow以获取许多示例和解释。规范是 JSR 310

To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.

您可以直接与数据库交换 java.time 对象。使用符合 JDBC驱动程序 / jeps / 170rel =nofollow noreferrer> JDBC 4.2 或更高版本。不需要字符串,不需要 java.sql。* 类。

You may exchange java.time objects directly with your database. Use a JDBC driver compliant with JDBC 4.2 or later. No need for strings, no need for java.sql.* classes.

从哪里获取java.time班?

Where to obtain the java.time classes?


  • Java SE 8 Java SE 9 Java SE 10 Java SE 11 及更高版本 - 部分带有捆绑实现的标准Java API。


    • Java 9增加了一些小功能和修复。

    • Java SE 8, Java SE 9, Java SE 10, Java SE 11, and later - Part of the standard Java API with a bundled implementation.
      • Java 9 adds some minor features and fixes.
      • Most of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
      • Later versions of Android bundle implementations of the java.time classes.
      • For earlier Android (<26), the ThreeTenABP project adapts ThreeTen-Backport (mentioned above). See How to use ThreeTenABP….

      ThreeTen-Extra 项目使用其他类扩展java.time。该项目是未来可能添加到java.time的试验场。您可以在这里找到一些有用的课程,例如 Interval YearWeek YearQuarter 更多