android - UTC 时间不匹配 - Java 与 Node JS 上的 Moment

标签 android simpledateformat datetime-format

在我的 Node JS 服务器上使用 moment.js 库:

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

我得到的当前时间字符串为:

2017-08-02 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-08-02 22:58:46.163Z

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

最佳答案

如果您想要 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

上面的 X 模式是在 JDK 7 中引入的,因此如果您使用的是 JDK <= 6,则必须放置文字 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,因为最好输出正确的时区而不是硬编码的 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();

第二种情况将产生不同的输出(例如 2017-08-03T01:05:06.631+05:30[Asia/Kolkata]),因为它使用的时区不是 UTC。不过,您可以使用 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") 创建另一种格式,将 pattern 替换为相应的模式字母(check the javadoc 了解更多详细信息)。

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

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

您还可以通过 ZoneId.systemDefault() 使用系统的默认时区,但这可以在不通知的情况下更改,即使在运行时也是如此,因此最好明确使用特定的时区。

关于android - UTC 时间不匹配 - Java 与 Node JS 上的 Moment,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45467513/

相关文章:

java - 因此,我尝试在命令行中以字符串形式获取日期并将其转换为毫秒,但它不断增加五个小时。有什么想法吗?

java - 使用 DateTimeFormatter "hh:mm a"解析时间导致异常

java - 使用方法时日历给出错误的年份

java - TextView.setText 由于线程化而无法正常工作?

android - 带有Google Speech to Text的录音机

java - SimpleDateFormat - 无法解析的日期

日期 "Wednesday, January 2, 2013 5:29:26 PM +02:00"的 Java 日期格式字符串

c# - 将日期时间格式 -"yyyyMMddhhmmssfff"的字符串转换为“DD-MM-YYYY HH :MM) before exporting DataTable to excel

android - 如何合并图像并相互叠加

android - OpenGL ES 2.0 中的等 ionic 着色器性能