我正在尝试借助 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"的输出。和时间2是当地的输出(即"亚洲/加尔各答")。
我只想要给定时区的当前时间格式为UTC秒(即1970年1月1日以来的秒数)。
为什么SimpleDateFormat.format()和SimpleDateFormat.parse()通过只设置一个时区给出不同的时间?
请帮帮我。
答案 0 :(得分:4)
使用 Parse ,您可以命令编译器以特定格式了解给定日期。它理解并保持其自己的格式,并准备提供您想要的任何格式!
您正在获取输出,这是您输入日期已成功解析的信号。你无法控制变量存储日期的格式。
使用格式,您可以将日期转换为任何所需的格式。
简单地 解析 - >阅读(我可以用任何方式阅读它并以我想要的任何方式存储) 格式 - >写(我会以你想要的格式给你)
答案 1 :(得分:2)
dateFormat.format()将为您提供给定格式的输出,并将时区更改为格式化程序中设置的时区。 (例如dateFormat.setTimeZone(TimeZone.getTimeZone(“ America / Los_Angeles”))))
dateFormat.parse()假定日期已经在提到的时区中,它将日期转换为您的本地时区。
答案 2 :(得分:0)
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
答案 3 :(得分:0)
使用第一行,您将本地日期格式化为特定时区。它将返回一个字符串,表示在特定时区传递的参数日期。但是解析函数不同。它将返回一个日期对象表示的数字自1970年1月1日上午12:00,UTC以来的毫秒数。它不包含任何时区信息。
答案 4 :(得分:0)
可怕的旧日期时间类非常令人困惑,尤其是在处理隐式默认时区时。但是,您的谜尚无足轻重,因为这些可怕的旧类早在几年前就被现代的 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
问题已经解决,因为 java.time 取代了可怕的旧日期时间类,例如SimpleDateFormat
。
java.util.Date
类被java.time.Instant
取代。两者都代表UTC时刻,始终代表UTC。 (尽管Date::toString
在应用JVM当前的默认时区时对您说谎)。
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偏移量的指示。这样的值是 not 片刻,是 not 在时间线上的一点。例如,印度的晚上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中时间轴上的时刻,分辨率为nanoseconds(十进制小数的九(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及更高版本中。这些类取代了麻烦的旧legacy日期时间类,例如java.util.Date
,Calendar
和SimpleDateFormat
。
目前位于Joda-Time的maintenance mode项目建议迁移到java.time类。
要了解更多信息,请参见Oracle Tutorial。并在Stack Overflow中搜索许多示例和说明。规格为JSR 310。
您可以直接与数据库交换 java.time 对象。使用符合JDBC driver或更高版本的JDBC 4.2。不需要字符串,不需要java.sql.*
类。
在哪里获取java.time类?
ThreeTen-Extra项目使用其他类扩展了java.time。该项目为将来可能在java.time中添加内容提供了一个试验场。您可能会在这里找到一些有用的类,例如Interval
,YearWeek
,YearQuarter
和more。