简体   繁体   English

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

[英]Generate string of yesterday’s date-time in ISO 8601 format

In Android, I am using java.util.Calendar to get yesterday date in format yyyy-MM-dd'T'hh:mm:ss'Z' . 在Android中,我正在使用java.util.Calendaryyyy-MM-dd'T'hh:mm:ss'Z'格式获取昨天的日期。 For example if today is 31 May 2017 , I want to get yesterday date as 2017-05-30T00:00:00Z . 例如,如果今天是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);

I am expecting output to be 2017-05-30T00:00:00Z . 我期望输出为2017-05-30T00:00:00Z But it gives me 2017-05-30T12:00:00Z . 但这给了我2017-05-30T12:00:00Z

What is wrong here? 怎么了 Is it TimeZone related? 与TimeZone相关吗? My timezone is GMT/UTC + 08:00 hour . 我的时区是GMT/UTC + 08:00 hour

I am probably answering more than you asked about, but now you have asked, why not take all of it? 我的回答可能比您要的要多,但是现在您已经问了,为什么不全部使用呢? I see two or three things wrong with your code. 我发现您的代码有两三件事是错的。 bowmore in another answer has touched on all three already, but I think a couple of them can be made a little clearer still: 另一个答案中, bowmore已经涉及到所有三个,但是我认为其中的两个可以更清晰一些:

  1. Yes, the first and most serious is time zone related. 是的,最严重的是时区相关的。 You need to decide, and you should make explicit in your code, which time zone you use. 您需要确定,并且应该在代码中明确说明所使用的时区。 And it is incorrect to give Z as time zone on a time at zone offset +08:00. 在区域偏移量+08:00的时间上给Z作为时区是不正确的。 Z is for Zulu time, another name for UTC. Z是祖鲁语时间,UTC的另一个名称。
  2. In your format pattern, you should use capital HH for hour of day. 在格式格式中,您应该在一天中的小时内使用大写HH
  3. You should prefer the modern date and time classes, in principle always, but at least for a case like this. 从原则上讲,您应该始终偏爱现代日期和时间类,但至少在这种情况下更是如此。 With these you won't be able to make the errors you did with the oldfashioned SimpleDateFormat . 有了这些,您将无法做出与老式SimpleDateFormat的错误。

Time zone 时区

Time zone is crucial to your task. 时区对于您的任务至关重要。 You need to decide whether yesterday's date in UTC (as your requested output says), in GMT/UTC + 08:00 or, say, in the the JVM's current time zone (which can be changed at any time while your program is running). 您需要确定昨天的日期是UTC(如请求的输出所示), GMT/UTC + 08:00还是JVM的当前时区(可以在程序运行时随时更改)。 。 This snippet uses UTC: 此代码段使用UTC:

this.yesterdayAtStartOfDay = LocalDate.now(ZoneOffset.UTC)
    .minusDays(1)
    .atStartOfDay(ZoneOffset.UTC)
    .format(DateTimeFormatter.ISO_INSTANT);

Running it just now, the result is 现在运行它,结果是

2017-05-30T00:00:00Z

Instead of the last line of the snippet, you may use the even simpler: 除了使用代码段的最后一行,您还可以使用更简单的代码:

    .toString();

This gives the same result because atStartOfDay() gives a ZonedDateTime with time zone Z, and its toString() method gives the ISO 8601 string you requested. 这给出了相同的结果,因为atStartOfDay()给出了时区为Z的ZonedDateTime ,而其toString()方法给出了您请求的ISO 8601字符串。

If you want yesterday's date in another time zone, in the first line of the snippet (and only the first line) use for example ZoneOffset.ofHours(8) , ZoneId.of("Asia/Hong_Kong") or ZoneId.systemDefault() as time zone. 如果要在另一个时区使用昨天的日期,请在代码段的第一行(仅第一行)中使用ZoneOffset.ofHours(8)ZoneId.of("Asia/Hong_Kong")ZoneId.systemDefault()作为时区。

In case you are using Java 6 or 7, to use the modern date and time classes you need to get the ThreeTen-Backport library . 如果您使用Java 6或7,要使用现代的日期和时间类,则需要获取ThreeTen-Backport Even though I always think twice before introducing an external dependency, I recommend this one warmly for your task. 即使在引入外部依赖项之前我总是三思而后行,但我还是为您的任务推荐了这个。

That back-port is further adapted for Android in the ThreeTenABP project. 该后端口在ThreeTenABP项目中进一步适用于Android。

This is simply a mistake in your SimpleDateFormat . 这只是您SimpleDateFormat一个错误。

You use hh for the hours, but that shows the one based hour of AM/PM. 您将hh用作小时,但这显示了AM / PM的一个小时。

These are the relevant symbols (from SimpleDateFormat ) 这些是相关的符号(来自SimpleDateFormat

  • H Hour in day (0-23) H小时(0-23)
  • k Hour in day (1-24) k一天中的小时(1-24)
  • K Hour in am/pm (0-11) K小时,上午/下午(0-11)
  • h Hour in am/pm (1-12) h上午/下午(1-12)

You want this : "yyyy-MM-dd'T'HH:mm:ss'Z'" 您想要这样: "yyyy-MM-dd'T'HH:mm:ss'Z'"

Remark 备注

You say your timezone is +08:00 hours, and you calculate the date using that timezone, however you format it as if it's in the Zulu timezone (which has an offset of +00:00) 您说您的时区为+08:00小时,并使用该时区计算日期,但是您将其格式化为好像在Zulu时区中(偏移量为+00:00)

BONUS 奖金

In Java 8 all this Calendar manipulating goes away : 在Java 8中,所有这些Calendar操作都消失了:

ZonedDateTime yesterday = ZonedDateTime.now().with(ChronoField.NANO_OF_DAY, 0).minusDays(1);
DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss'Z'");
dateEndStr = formatter.format(dateEnd);

To subtract days, you should use: 要减去天数,应使用:

Calendar calendar = Calendar.getInstance();
calendar.add(Calendar.DAY_OF_MONTH, -5);
cal.add(Calendar.DAY_OF_YEAR, -1);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM