I’m trying to obtain the start and end times of a specific month in a particular timezone, specifically "Asia/Kolkata" (UTC+05:30).
For instance, below are start and end times for September 2023.
Start Time: 2023-09-01 00:00:00
End Time: 2023-09-30 23:59:59
I’ve implemented the following functions in Java:
public static Long getStartTimeStampOfMonth(Month month, Year year) {
LocalDate startDate = LocalDate.of(year.getValue(), month, 1);
LocalDateTime startDateTime = LocalDateTime.of(startDate, LocalTime.MIN);
ZonedDateTime istDateTime = startDateTime.atZone(ZoneId.of("Asia/Kolkata"));
return Timestamp.valueOf(istDateTime.toLocalDateTime()).getTime();
}
public static Long getEndTimeStampOfMonth(Month month, Year year) {
LocalDate startDate = LocalDate.of(year.getValue(), month, 1);
LocalDate endDate = startDate.withDayOfMonth(startDate.lengthOfMonth());
LocalDateTime endDateTime = LocalDateTime.of(endDate, LocalTime.MAX);
ZonedDateTime istDateTime = endDateTime.atZone(ZoneId.of("Asia/Kolkata"));
return Timestamp.valueOf(istDateTime.toLocalDateTime()).getTime();
}
However, I’ve noticed that the above code returns the start and end times based on the timezone configured on the machine. Even though I’ve explicitly specified ZoneId.of("Asia/Kolkata"), it doesn’t produce the desired results.
When I tested the code for SEPTEMBER 2023 on a machine set to the UTC timezone, I got the following output:
Start Time: 1693526400000
End Time: 1696118399999
However, I want the output to be consistent, regardless of the machine’s timezone:
Start Time: 1693506600000
End Time: 1696098599999
Please help me identify what I might be missing or suggest an alternative approach.
>Solution :
The local time zone is being introduced when you convert from ZonedDateTime
to a Timestamp
:
return Timestamp.valueOf(istDateTime.toLocalDateTime()).getTime();
Since you’re going through a LocalDateTime
, the Timestamp.valueOf
method will presume the local time zone.
From the docs:
public static Timestamp valueOf(LocalDateTime dateTime)
Obtains an
instance ofTimestamp
from aLocalDateTime
object, with the same year, month, day of month, hours, minutes, seconds and nanos date-time value as the providedLocalDateTime
.The provided
LocalDateTime
is interpreted as the local date-time in the local time zone.
Instead, you can create the Timestamp
from an Instant
:
return Timestamp.from(istDateTime.toInstant()).getTime();
Though, since you appear to be after a long
in terms of milliseconds, you could just skip the Timestamp
type entirely:
return istDateTime.toInstant().toEpochMilli();