parrotjack
parrotjack

Reputation: 512

Java8 Date and Time with Instant API

I get dynamic date from my request,

Instant duration = request.getStartDate();   // my input is 2020-03-01T00:00:01Z
for (int i = 0; i < 12; i++) {
  duration  = duration.with(TemporalAdjusters.firstDayOfNextMonth ());
}

Basically i wanted to get first day of every month for 12 months, i tried with above code but getting exception,

java.time.temporal.UnsupportedTemporalTypeException: Unsupported field: DayOfMonth

My output could be,

2020-04-01T00:00:01Z
2020-05-01T00:00:01Z
2020-06-01T00:00:01Z
:
:
2021-03-01T00:00:01Z

anything am missing here? tried with using plus()

duration.plus(30, ChronoUnit.DAYS);

I tried to convert instant to locateDate, then it prints fine, but for my required format i need to convert to Instant from localdate. I'm not seeing 1st day of next month.


2019-03-31T22:00:00Z
2019-04-30T22:00:00Z
2019-05-31T22:00:00Z
2019-06-30T22:00:00Z
2019-07-31T22:00:00Z
2019-08-31T22:00:00Z
2019-09-30T22:00:00Z
2019-10-31T23:00:00Z
2019-11-30T23:00:00Z
2019-12-31T23:00:00Z

any suggestion are appreciated. Thanks!

Upvotes: 0

Views: 696

Answers (2)

Michael
Michael

Reputation: 44150

Much less fiddly than my namesake's answer: provided you convert to an OffsetDateTime up-front, there is no problem using the nice human-readable adjuster that you were trying to use initially.

OffsetDateTime duration = Instant.now().atOffset(ZoneOffset.UTC);
for (int i = 0; i < 12; i++) {
    duration = duration.with(TemporalAdjusters.firstDayOfNextMonth());
}

The issue is that an Instant is an unambiguous point in time, irrespective of any specific timezone or geographic location. There is no specific date associated with an instant; what is Monday the 1st in one location may be Sunday the 31st in another, but it's still the same instant. That is why when trying to set a first day of the month, you get an exception.

If you convert to an OffsetDateTime, you are applying an offset (in this case UTC, so an offset of zero). This converts your data to a format in which a date is unambiguous.

Upvotes: 3

MikeFHay
MikeFHay

Reputation: 9013

Instant startInstant = request.getStartDate();
LocalDate start = startInstant.atZone(ZoneOffset.UTC).toLocalDate().withDayOfMonth(1);
for (int i = 0; i < 12; i++) {
    System.out.println(start.plusMonths(i).atStartOfDay().toInstant(ZoneOffset.UTC));
}

Upvotes: 1

Related Questions