以 ISO 8601 格式生成昨天的日期时间字符串

Shu*_*Tee 0 java android calendar date simpledateformat

在Android中,我用来java.util.Calendar获取格式为昨天的日期yyyy-MM-dd'T'hh:mm:ss'Z'。例如,如果今天是31 May 2017,我想将昨天的日期设为2017-05-30T00:00:00Z

Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.HOUR_OF_DAY, 0);
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.SECOND, 0);
calendar.set(Calendar.MILLISECOND, 0);

// Date End = yesterday
calendar.add(Calendar.DATE, -1);
Date dateEnd = calendar.getTime();

SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd'T'hh:mm:ss'Z'");
this.dateEndStr = formatter.format(dateEnd);
Run Code Online (Sandbox Code Playgroud)

我期望输出为2017-05-30T00:00:00Z. 但它给了我2017-05-30T12:00:00Z

这里有什么问题吗?与时区有关吗?我的时区是GMT/UTC + 08:00 hour.

Ole*_*.V. 5

我回答的可能比你问的还要多,但现在你问了,为什么不全部拿走呢?我发现您的代码有两三个问题。鲍莫尔在另一个答案中已经谈到了这三个问题,但我认为其中一些还可以说得更清楚:

\n\n
    \n
  1. 是的,第一个也是最严重的是时区相关。您需要决定,并且应该在代码中明确说明您使用的时区。将 Z 作为位于时区偏移 +08:00 的时间的时区是不正确的。Z 代表祖鲁时间,UTC 的另一个名称。
  2. \n
  3. 在您的格式模式中,您应该使用大写字母HH来表示一天中的小时。
  4. \n
  5. 原则上,您应该更喜欢现代日期和时间类,但至少对于这样的情况是这样。有了这些,您将\xe2\x80\x99 不会犯与老式SimpleDateFormat.
  6. \n
\n\n

时区

\n\n

时区对于您的任务至关重要。您需要决定昨天\xe2\x80\x99s 的日期是否采用UTC 格式(如您请求的输出所示),或者GMT/UTC + 08:00例如采用JVM\xe2\x80\x99s 当前时区(可以随时更改)你的程序正在运行)。此片段使用 UTC:

\n\n
this.yesterdayAtStartOfDay = LocalDate.now(ZoneOffset.UTC)\n    .minusDays(1)\n    .atStartOfDay(ZoneOffset.UTC)\n    .format(DateTimeFormatter.ISO_INSTANT);\n
Run Code Online (Sandbox Code Playgroud)\n\n

刚才运行一下,结果是

\n\n
2017-05-30T00:00:00Z\n
Run Code Online (Sandbox Code Playgroud)\n\n

您可以使用更简单的代码,而不是代码片段的最后一行:

\n\n
    .toString();\n
Run Code Online (Sandbox Code Playgroud)\n\n

这给出了相同的结果,因为给出了带有时区 Z 的atStartOfDay()a ,并且其方法给出了您请求的 ISO 8601 字符串。ZonedDateTimetoString()

\n\n

如果您希望在另一个时区中昨天\xe2\x80\x99s 日期,请在代码片段的第一行(并且仅第一行)中使用例如ZoneOffset.ofHours(8),ZoneId.of("Asia/Hong_Kong")ZoneId.systemDefault()作为时区。

\n\n

如果您使用 Java 6 或 7,要使用现代日期和时间类,您需要获取ThreeTen -Backport。尽管在引入外部依赖项之前我总是三思而后行,但我强烈推荐这个来完成您的任务。

\n\n

在ThreeTenABP项目中,该向后移植进一步针对 Android 进行了调整。

\n