1

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

CoderDev
  • 13
  • 4
  • Your date string doesn't have time. Where is the time part in start time and end time coming from? – Arvind Kumar Avinash Jun 06 '20 at 17:47
  • As I've said I want to convert a date as start time of the day (12:00:00AM) and end time of the day (11:59:59PM) – CoderDev Jun 06 '20 at 18:07
  • Your answer link does not work as I had expected. Please delete it. If you wanted to post your own answer (which is a fine thing to do), please do so in the Answer section below. Thank you. – Ole V.V. Apr 19 '23 at 07:34

2 Answers2

4

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

Ole V.V.
  • 81,772
  • 15
  • 137
  • 161
1

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
codeogeek
  • 652
  • 1
  • 8
  • 22
  • Thanks Sunil, Can we have the output in this format: "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'" – CoderDev Jun 07 '20 at 01:09
  • Yeah, actually the last part of the string required in SSS'Z while in your output string start date don't have it(while required 000Z) and end date is having it like 999999999Z(while required 999Z) – CoderDev Jun 07 '20 at 01:45
  • if this has resolved your query, please accept it as an answer – codeogeek Jun 07 '20 at 03:15
  • @sunil, After running the code the output is not what I've expected: I've write down the code like this: http://m.uploadedit.com/bltc/159150652274.TXT – CoderDev Jun 07 '20 at 05:08
  • @CoderDev Hardcoding `Z` as a literal in the string is incorrect. It’s an offset of zero from UTC, so format the offset to get it correct. – Ole V.V. Jun 07 '20 at 06:18
  • But don't we have any other option apart from switching to ThreeTenBP Library? – CoderDev Jun 07 '20 at 06:49
  • @CoderDev I updated my answer. Did u get the correct answer after OleV.V.'s solution? – codeogeek Jun 07 '20 at 10:02