![](/img/trans.png)
[英]SimpleDateFormat.parse and SimpleDateFormat.format not producing identical values
[英]Why SimpleDateFormat.format() and SimpleDateFormat.parse() are giving different time though setting only one TimeZone?
我正在尝试通过SimpleDateFormat将时区设置为其他国家的时区。 SimpleDateFormat.format()返回给定时区的正确当前时间,但是SimpleDateFormat.parse()返回本地当前时间,我不知道为什么会这样。 这是我的代码-
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:MM:ss");
dateFormat.setTimeZone(TimeZone.getTimeZone("America/Los_Angeles"));
System.out.println("Time1 : " + dateFormat.format(new Date()));
System.out.println("Time2 : " + dateFormat.parse(dateFormat.format(new Date())));
输出是-
Time1 : 2013-01-17 21:01:55
Time2 : Fri Jan 18 10:30:55 IST 2013
Time1是“ America / Los_Angeles”的输出,而Time2是local(即“ Asia / Calcutta”)的输出 。
我只想要UTC秒格式的给定时区的当前时间(即,自1970年1月1日以来的秒)。
为什么虽然只设置一个时区,但SimpleDateFormat.format()和SimpleDateFormat.parse()却给出了不同的时间?
请帮我。
使用Parse ,您可以命令编译器理解特定格式的给定日期。 它了解并保持其自己的格式,并准备提供您想要的任何格式!
您将得到一个输出,这表示您输入日期已成功解析。 您无法控制变量存储的date的格式。
使用格式,您可以将日期转换为任何所需的格式。
只需解析->阅读(我可以以任何方式阅读并以我想要的任何方式存储)格式->写(我会以您想要的格式给您)
dateFormat.format()将为您提供给定格式的输出,并将时区更改为格式化程序中设置的时区。 (例如dateFormat.setTimeZone(TimeZone.getTimeZone(“ America / Los_Angeles”)));)
而dateFormat.parse()假定日期已在提到的时区中,它将日期转换为您的本地时区。
第二个println中的dateFormat.parse()
System.out.println("Time2 : " + dateFormat.parse(dateFormat.format(new Date())));
返回Date和Date.toString()以EEE MMM dd HH:mm:ss zzz yyyy
格式返回日期的字符串表示形式。 参见Date.toString()API
在第一行中,您正在将本地日期格式化为特定时区,它将返回一个字符串,该字符串表示在特定时区中传递的参数日期,但是解析函数有所不同。它将返回一个日期对象,该对象表示自一月份以来的毫秒数1970年1月1日,UTC。 它不包含任何时区信息。
糟糕的旧日期时间类非常令人困惑,尤其是在处理隐式默认时区时。 但是,您的谜尚无足轻重 ,因为这些可怕的旧类早在几年前就被现代的java.time类所取代。
Instant.now() // Capture current moment in UTC. This class replaces `java.util.Date`.
.atZone( // Adjust from UTC to the wall-clock time used by the people of a particular region, a time zone.
ZoneId.of( "America/Montreal" )
) // Returns a `ZonedDateTime`
.format(
DateTimeFormatter.ISO_LOCAL_DATE_TIME
) // Returns a String like: `2013-01-17T21:01:55`.
.replace( "T" , " " ) // Replace the `T` in the middle (from the standard ISO 8601 format) with a SPACE.
2013-01-17 21:01:55
由于可怕的旧日期时间类(例如SimpleDateFormat
已被java.time取代,因此该问题不存在 。
java.util.Date
类由java.time.Instant
替换。 两者都代表UTC时刻,始终代表UTC。 (尽管在应用JVM的当前默认时区时对您说谎,尽管Date::toString
。)
Instant instant = Instant.now() ; // Capture current moment in UTC.
调整到一个时区。
ZoneId z = ZoneId.of( "America/Los_Angeles" ) ;
ZonedDateTime zdt = instant.atZone( z ) ;
调整到另一个时区。
ZoneId zKolkata = ZoneId.of( "Asia/Kolkata" ) ; // Contemporary time in India.
ZonedDateTime zdtKolkata = instant.atZone( zKolkata ) ;
这三个对象( instant
, zdt
和zdtKolkata
)都表示同一时刻 ,时间轴上的同一点。 只有挂钟时间不同。
当生成表示日期时间值的字符串时,除非上下文绝对清晰,否则我建议始终包括偏移量/区域信息。 在时间范围不明确的报告中,我在商业世界中看到了很多困惑。
但是,如果您坚持要用DateTimeFormatter
类定义自己的格式化模式,或者使用给定的格式化程序ISO_LOCAL_DATE_TIME
并将中间的T
替换为SPACE。
DateTimeFormatter f = DateTimeFormatter.ISO_LOCAL_DATE_TIME ;
String output = zdt.format( f ) ;
2013-01-17 21:01:55
问题的一部分是您的字符串的歧义2013-01-17 21:01:55
。 该字符串缺少任何时区或UTC偏移量的指示。 这样的值不是时刻, 也不是时间轴上的一点。 例如,印度的晚上9点比魁北克的晚上9点早几个小时。 没有区域或偏移量,该字符串仅代表沿全球时区范围约26-27小时的潜在时刻。
传统类没有此类代表这种价值的类。 在现代类中,我们为此设置了LocalDateTime
,这是一个无时区,日期和时间的无区域/偏移量。
解析/生成字符串时, java.time类默认使用ISO 8601标准格式。 您的输入几乎符合要求。 我们只需要在中间用T
替换SPACE即可。
LocalDateTime ldt = LocalDateTime.parse( "2013-01-17 21:01:55".replace( "" , "T" ) ) ;
如果您知道该字符串后面的意图是表示特定时区中的某个时刻,请应用ZoneId
来获取ZonedDateTime
。 例如,如果您确定它代表了北美大部分西海岸的一刻,请使用America/Los_Angeles
。
ZoneId z = ZoneId.of( "America/Los_Angeles" ) ;
ZonedDateTime zdt = ldt.atZone( z ) ;
要从该区域调整为UTC,请提取一个Instant
对象。 Instant
类以UTC表示时间轴上的时刻,分辨率为纳秒 (最多十进制的九(9)位数字)。
Instant instant = zdt.toInstant() ; // Adjust from some zone to UTC. Same moment, same point on the timeline, different wall-clock time.
java.time框架内置于Java 8及更高版本中。 这些类取代了麻烦的旧的旧式日期时间类,例如java.util.Date
, Calendar
和SimpleDateFormat
。
现在处于维护模式的Joda-Time项目建议迁移到java.time类。
要了解更多信息,请参见Oracle教程 。 并在Stack Overflow中搜索许多示例和说明。 规格为JSR 310 。
您可以直接与数据库交换java.time对象。 使用与JDBC 4.2或更高版本兼容的JDBC驱动程序 。 不需要字符串,不需要java.sql.*
类。
在哪里获取java.time类?
ThreeTen-Extra项目使用其他类扩展了java.time。 该项目为将来可能在java.time中添加内容提供了一个试验场。 您可以在这里找到一些有用的类,比如Interval
, YearWeek
, YearQuarter
,和更多 。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.