How to get start time and end time of a day in another timezone in Android

若如初见. 提交于 2020-06-25 07:08:52

问题


I've the date in format: YYYY-MM-DD

Output format required is: "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"

And I want to get the date in ISO format as Start time of the day(starts from 12:00AM) and end time of the day(ends on 11:59PM) in America/Chicago timezone.

For eg. For the date: 2020-06-08 (June 8) the converted final output is like:

Start time of the day as Date: 2020-06-08T05:00:00.000Z

End time of the day as Date: 2020-06-09T04:59:59.999Z

Please help me here if anybody has any clue for the same.

Answer: http://m.uploadedit.com/bltc/1591511729781.txt


回答1:


java.time and ThreeTenABP

I suggest using java.time, the modern Java date and time API, for such date and time math.

    ZoneId zone = ZoneId.of("America/Chicago");

    String dateString = "2020-06-08";
    LocalDate date = LocalDate.parse(dateString);
    Instant startOfDay = date.atStartOfDay(zone).toInstant();
    Instant endOfDay = date.plusDays(1).atStartOfDay(zone).toInstant();

    System.out.println("The day is from " + startOfDay + " (inclusive) to " + endOfDay + " (exclusive)");

Output is:

The day is from 2020-06-08T05:00:00Z (inclusive) to 2020-06-09T05:00:00Z (exclusive)

In order not to exclude the last millisecond of the day we need to count the day as lasting up to the first moment of the next day exclusive. If you do insist on subtracting a millisecond or just a nanosecond, it’s up to you to do so, of course. For example:

    Instant endOfDay = date.plusDays(1).atStartOfDay(zone).minusNanos(1).toInstant();

The day is from 2020-06-08T05:00:00Z (inclusive) to 2020-06-09T04:59:59.999999999Z (inclusive and 1 nano more)

Edit: How to get milliseconds printed in the output? You most probably don’t need that. The format you are asking for is ISO 8601 (see the link at the bottom), the international standard. In ISO 8601 the fraction of second is optional, and leaving it out implies 0. So any API requiring ISO 8601 should accept the above. Only if not, the correct solution is to use a formatter. In this case we need to convert the time to UTC explicitly:

    ZoneId zone = ZoneId.of("America/Chicago");
    DateTimeFormatter formatterWithMillis = DateTimeFormatter.ofPattern("uuuu-MM-dd'T'HH:mm:ss.SSSX");

    String dateString = "2020-06-08";
    LocalDate date = LocalDate.parse(dateString);
    OffsetDateTime startOfDay = date.atStartOfDay(zone)
            .toOffsetDateTime()
            .withOffsetSameInstant(ZoneOffset.UTC);
    OffsetDateTime endOfDay = date.plusDays(1)
            .atStartOfDay(zone)
            .toOffsetDateTime()
            .withOffsetSameInstant(ZoneOffset.UTC);

    String startString = startOfDay.format(formatterWithMillis);
    String endString = endOfDay.format(formatterWithMillis);
    System.out.println("The day is from " + startString + " (inclusive) to " + endString + " (exclusive)");

The day is from 2020-06-08T05:00:00.000Z (inclusive) to 2020-06-09T05:00:00.000Z (exclusive)

Or after subtracting a nanosecond from the end time as before:

    OffsetDateTime endOfDay = date.plusDays(1)
            .atStartOfDay(zone)
            .minusNanos(1)
            .toOffsetDateTime()
            .withOffsetSameInstant(ZoneOffset.UTC);

The day is from 2020-06-08T05:00:00.000Z (inclusive) to 2020-06-09T04:59:59.999Z (inclusive and 1 nano more)

(Since the time is truncated to whole milliseconds the 1 nano more doesn’t really make sense, but I don’t think that’s the point here.)

Question: Doesn’t java.time require Android API level 26?

java.time works nicely on both older and newer Android devices. It just requires at least Java 6.

  • In Java 8 and later and on newer Android devices (from API level 26) the modern API comes built-in.
  • In non-Android Java 6 and 7 get the ThreeTen Backport, the backport of the modern classes (ThreeTen for JSR 310; see the links at the bottom).
  • On (older) Android use the Android edition of ThreeTen Backport. It’s called ThreeTenABP. And make sure you import the date and time classes from org.threeten.bp with subpackages.

But don't we have any other option apart from switching to ThreeTenBP Library?

If you insisted, I suppose that a way through using Calendar, Date and SimpleDateFormat could be found. Those classes are poorly designed and long outdated, so with what I know and don’t know I would prefer ThreeTenABP.

Links

  • Oracle tutorial: Date Time explaining how to use java.time.
  • Java Specification Request (JSR) 310, where java.time was first described.
  • ThreeTen Backport project, the backport of java.time to Java 6 and 7 (ThreeTen for JSR-310).
  • ThreeTenABP, Android edition of ThreeTen Backport
  • Question: How to use ThreeTenABP in Android Project, with a very thorough explanation.
  • Wikipedia article: ISO 8601



回答2:


Updated:

    ZoneId zoneId = ZoneId.of("America/Chicago");
    LocalDate localDate = LocalDate.parse("2020-06-08");
    DateTimeFormatter newPattern = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'").withZone(zoneId);
    Instant startOfDay = localDate.atStartOfDay(zoneId).toInstant();
    Instant endOfDay = LocalDateTime.of(localDate, LocalTime.MAX).atZone(zoneId).toInstant().truncatedTo(ChronoUnit.MILLIS);
    System.out.println(startOfDay);
    System.out.println(endOfDay);

With what I have gone through, the fraction 000 will not come in this but yes one can be sure that if there are no fraction of milliseconds then it is 000. I was not able to figure out how to bring this while formatting. In case you find something then please add else, you can do it this by converting startDate to String and then appending the 000 to it.

Results

    2020-06-08T05:00:00Z
    2020-06-09T04:59:59.999Z


来源:https://stackoverflow.com/questions/62235600/how-to-get-start-time-and-end-time-of-a-day-in-another-timezone-in-android

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!