UTC时间不匹配 - 的Java VS一刻起节点JS

问题描述:

Node JS服务器上使用moment.js库:UTC时间不匹配 - 的Java VS一刻起节点JS

moment().utc().format("YYYY-MM-DD HH:mm:ss.SSS") 

我有当前时间字符串:

2017年8月2日11: 57:52.616Z

在Android上,我使用了下面的代码。

Date myDate = new Date(); 
Calendar calendar = Calendar.getInstance(); 
calendar.setTimeZone(TimeZone.getTimeZone("UTC")); 
calendar.setTime(myDate); 
Date time = calendar.getTime(); 
SimpleDateFormat outputFmt = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"); 
String dateAsString = outputFmt.format(time); 

输出功率为:

2017年8月2日22:58:46.163Z

我该如何解决这个问题?差异似乎在11个小时左右。

+0

你恰巧在UTC时间11小时的时区吗? –

+0

印度。这是+5:30 – Abhilash

+1

我不能真正帮助你,因为我不熟悉'Calendar'和'Date'的错综复杂。我能告诉你的是,我不熟悉他们的_reason_是他们是糟糕的API。如果你有能力,我强烈推荐使用Joda Time(http://www.joda.org/joda-time/),JSR-310(http://www.threeten.org/)或Java 8的java .time'包(https://docs.oracle.com/javase/8/docs/api/java/time/package-summary.html) –

如果你想在UTC的当前日期,必须设置在SimpleDateFormat的时区,而不是在Calendar。而你并不需要创建一个Calendar,你可以使用一个Date直接:

SimpleDateFormat outputFmt = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSX"); 
outputFmt.setTimeZone(TimeZone.getTimeZone("UTC")); 
String dateAsString = outputFmt.format(new Date()); // current date/time 

以上是在JDK 7中引入的,因此,如果您使用的是JDK < = 6 X模式,你必须把文字Z

SimpleDateFormat outputFmt = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"); 
outputFmt.setTimeZone(TimeZone.getTimeZone("UTC")); 
String dateAsString = outputFmt.format(new Date()); 

X先尝试,因为它是preferrable输出正确的时区,而不是硬编码的Z(因为如果更改时区到另一个时,Z将是错误的,因为它用于only when the date/time is in UTC)。


老班(DateCalendarSimpleDateFormat)有lots of problemsdesign issues,他们正在被新的API取代。

对于Android,您可以使用ThreeTen Backport,它是Java 8新日期/时间类的一个很好的后端。您还需要ThreeTenABP才能使其工作(更多关于如何使用它here)。

如果你想在UTC当前日期,你可以使用org.threeten.bp.Instant类(代表UTC瞬间):

String dateAsString = Instant.now().toString(); 

dateAsString变量将有一个像2017-08-02T19:21:22.271Z值。


如果您正在使用UTC值,那么Instant类就足够了。但是如果你想与其他时区工作,你必须使用一个org.threeten.bp.ZonedDateTime

// current time in UTC 
dateAsString = ZonedDateTime.now(ZoneOffset.UTC).toString(); 

// current time in another timezone 
dateAsString = ZonedDateTime.now(ZoneId.of("Asia/Kolkata")).toString(); 

,因为它使用时区,这不是UTC第二种情况会产生不同的输出(如2017-08-03T01:05:06.631+05:30[Asia/Kolkata])。你可以改变它,但是,通过使用org.threeten.bp.format.DateTimeFormatter

DateTimeFormatter fmt = DateTimeFormatter.ISO_OFFSET_DATE_TIME; 
dateAsString = ZonedDateTime.now(ZoneId.of("Asia/Kolkata")).format(fmt); 

这将导致2017-08-03T01:06:19.131+05:30。您也可以使用DateTimeFormatter.ofPattern("pattern")创建另一种格式,用相应的模式字母(check the javadoc替代pattern获取更多详细信息)。

请注意,他API使用IANA timezones names(始终格式为Region/City,如Asia/KolkataEurope/Berlin)。 避免使用3字母缩写(如CSTIST),因为它们是ambiguous and not standard

通过调用ZoneId.getAvailableZoneIds(),您可以获得可用时区列表(并选择最适合您系统的时区)。

您也可以使用系统的默认时区ZoneId.systemDefault(),但即使在运行时也可以在不通知的情况下对其进行更改,因此最好使用特定的时区。