5

I wish to get the exact date of first day of last month at 00:00:00Z.
So, here is my current solution:

public static String getStartingDateAndTimeOfLastMonth() {
    int dayOfCurrentMonth = ZonedDateTime.now().getDayOfMonth();
    return ZonedDateTime.now()
                        .minusDays(dayOfCurrentMonth - 1)
                        .minusMonths(1)
                        .format(DateTimeFormatter.ISO_INSTANT);
}

When i call the moethod:

String startDate = CustomUtilsFunctions.getStartingDateAndTimeOfLastMonth();
System.out.println("startDate: " + startDate);

The output of current solution is:

startDate: 2021-05-01T07:22:10.389Z

As you can see, the time of the output is 07:22:10.389Z but, I don't know the easiest way to turn it to 00:00:00:000Z

So the desired output for is:

startDate: 2021-05-01T00:00:00.000Z

Point: I know, i can extract the hour, minutes and seconds and millis and then use the minus(), but I believe there must be an easier solution.

1
  • You could try truncatedTo(ChronoUnit.DAYS) and maybe prepend withZoneSameInstant(ZoneId.of("UTC")).
    – Thomas
    Commented Jun 10, 2021 at 7:38

2 Answers 2

5

Instead of using today as base, you could use a java.time.YearMonth (like this month) and subtract one month to get the last one. Then take the start of its first day. Do all that in UTC and then format as desired:

public static String getStartingDateAndTimeOfLastMonth() {
    // get the current month and subtract one to get the last
    YearMonth lastMonth = YearMonth.now().minusMonths(1);
    // then return its first day
    return lastMonth.atDay(1)                
                    // at the beginning of the day in UTC
                    .atStartOfDay(ZoneOffset.UTC)
                    // formatted as desired
                    .format(
                        DateTimeFormatter.ofPattern(
                            "uuuu-MM-dd'T'HH:mm:ss.SSSX",
                            Locale.ENGLISH
                        )
                    );
}

This outputs today (10th of June, 2021):

2021-05-01T00:00:00.000Z

Note: The default format of ZonedDateTime omits seconds and fraction-of-second if they are zero.
If you are fine with 2021-05-01T00:00Z, you can replace

    .format(
        DateTimeFormatter.ofPattern(
            "uuuu-MM-dd'T'HH:mm:ss.SSSX",
            Locale.ENGLISH
        )
    );

with simply .toString();.

1
  • 1
    @ArvindKumarAvinash Thanks for your edit, I just realigned the indentation for better visibility. I missed the correct format ;-), good to have more eyes watching answers here!
    – deHaar
    Commented Jun 10, 2021 at 8:51
5

You could first create the desired day and then use it together with a set time to compose DateTime. Depending on your use case, you could use LocalDateTime or ZonedDateTime.

LocalDate day = LocalDate.now()
        .minusMonths(1)
        .withDayOfMonth(1);

ZonedDateTime target = ZonedDateTime.of(day, LocalTime.MIDNIGHT, ZoneId.systemDefault());

System.out.println(target);

Another option would be to use turncatedTo (as @Thomas mentioned in comment)

ZonedDateTime target = ZonedDateTime.now()
        .minusMonths(1)
        .withDayOfMonth(1)
        .truncatedTo(ChronoUnit.DAYS)
        .withZoneSameLocal(ZoneId.of("UTC")); // optional depending on your case

Not the answer you're looking for? Browse other questions tagged or ask your own question.