tl; dr
Instant.ofEpochMilli( 1_317_816_735_000L )
.atZone( ZoneId.of( "Pacific/Auckland" ) )
.format( DateTimeFormatter.ofLocalizedDateTime( FormatStyle.MEDIUM ).withLocale( new Locale( "en" , "NZ" ) ) )
…也…
LocalDateTime.parse( "2011-10-06 03:35:05".replace( " " , "T" ) )
.atZone( ZoneId.of( "Pacific/Auckland" ) )
java.time
“问题”和“大多数答案”使用Java最早版本中的过时的旧式日期时间类。这些老类被证明是麻烦和令人困惑的。避免他们。而是使用java.time类。
ISO 8601
您的输入字符串几乎是标准的ISO 8601格式。只需将中间的SPACE替换为即可T
。
String input = "2011-10-06 03:35:05".replace( " " , "T" );
LocalDateTime
现在将其解析为a,LocalDateTime
因为输入内容缺少有关UTC偏移量或时区的任何信息。一个LocalDateTime
没有偏移,也没有时区的概念,所以它并不能代表时间轴上的实际的时刻。
LocalDateTime ldt = LocalDateTime.parse( input );
ZoneOffset
您似乎在说,从业务环境来看,您知道此字符串的意图是表示比UTC早13小时的时刻。因此,我们实例化了一个ZoneOffset
。
ZoneOffset offset = ZoneOffset.ofHours( 13 );
OffsetDateTime
应用它得到一个OffsetDateTime
对象。这成为时间表上的实际时刻。
OffsetDateTime odt = ldt.atOffset( offset);
ZoneId
但随后您提到了新西兰。因此,您要考虑一个特定的时区。时区是从UTC偏移的时间,再加上一组用于处理异常的规则,例如夏令时(DST)。因此,我们可以将a指定ZoneId
为一个ZonedDateTime
而不是一个单纯的偏移量。
指定正确的时区名称。切勿使用3-4字母的缩写,例如EST
或,IST
因为它们不是真实的时区,不是标准化的,甚至不是唯一的(!)。例如,Pacific/Auckland
。
ZoneId z = ZoneId.of( "Pacific/Auckland" );
ZonedDateTime
应用ZoneId
。
ZonedDateTime zdt = ldt.atZone( z );
您可以在时间轴上的同一时刻轻松调整到另一个区域。
ZoneId zParis = ZoneId.of( "Europe/Paris" );
ZonedDateTime zdtParis = zdt.withZoneSameInstant( zParis );
从时代开始计数
我强烈建议您不要将日期时间值视为一个新纪元,例如从1970 UTC开始的毫秒数。但是,如果必须,请Instant
从这样的数字创建一个。
Instant instant = Instant.ofEpochMilli( 1_317_816_735_000L );
然后,根据需要分配一个如上所述的时区,以使其远离UTC。
ZoneId z = ZoneId.of( "Pacific/Auckland" );
ZonedDateTime zdt = instant.atZone( z );
您的值为1_317_816_735_000L
:
2011-10-05T12:12:15Z
(2011年10月5日,星期三,格林尼治标准时间)
2011-10-06T01:12:15+13:00[Pacific/Auckland]
(2011年10月6日,星期四,01:12:15在新西兰奥克兰)。
产生字串
要生成标准ISO 8601格式的字符串,只需调用toString
。请注意,ZonedDateTime
通过在方括号中附加时区的名称来明智地扩展标准格式。
String output = zdt.toString();
对于其他格式,请在堆栈溢出中搜索DateTimeFormatter
类。已经覆盖了很多次。
指定FormatStyle
和Locale
。
Locale l = new Locale( "en" , "NZ" );
DateTimeFormatter f = DateTimeFormatter.ofLocalizedDateTime( FormatStyle.MEDIUM ).withLocale( l );
String output = zdt.format( f );
请注意,时区与语言环境无关。您可以Europe/Paris
用日语和文化规范Asia/Kolkata
显示日期时间,也可以用葡萄牙语和巴西文化规范显示日期时间。
关于java.time
该java.time框架是建立在Java 8和更高版本。这些类取代的麻烦旧日期,时间类,如java.util.Date
,.Calendar
,和java.text.SimpleDateFormat
。
现在处于维护模式的Joda-Time项目建议迁移到java.time。
要了解更多信息,请参见Oracle教程。并在Stack Overflow中搜索许多示例和说明。
大部分的java.time功能后移植到Java 6和7 ThreeTen,反向移植,并进一步用于安卓在ThreeTenABP(见如何使用......)。
该ThreeTen-额外项目与其他类扩展java.time。该项目为将来可能在java.time中添加内容打下了基础。你可能在这里找到一些有用的类,如Interval
,YearWeek
,YearQuarter
,等。