I am converting my time calculations from self implemented code to Java 8 Time API.
I need to have the start and end time in milliseconds from a java.time.Year
or java.time.Month
class, which I plan to use later in another layer for JFreeChart.
I need functions like getFirstMillisecond()
& getLastMilliSecond()
from org.jfree.data.time.RegularTimePeriod
class of JFreeChart.
I have already implemented code something like-
public static long getStartTimeInMillis(java.time.Year year, java.time.Month month) {
if (year != null && month != null) {
return LocalDate.of(year.getValue(), month, 1).with(TemporalAdjusters.firstDayOfMonth()).
atStartOfDay().atZone(TimeZone.getDefault().toZoneId()).toInstant().toEpochMilli();
} else if (year != null) {
return LocalDate.of(year.getValue(), java.time.Month.JANUARY, 1).with(TemporalAdjusters.firstDayOfMonth()).
atStartOfDay().atZone(TimeZone.getDefault().toZoneId()).toInstant().toEpochMilli();
}
return 0;
}
public static long getEndTimeInMillis(java.time.Year year, java.time.Month month) {
if (year != null && month != null) {
return LocalDate.of(year.getValue(), month, 1).with(TemporalAdjusters.lastDayOfMonth()).
atTime(OffsetTime.MAX).toLocalDateTime().atZone(TimeZone.getDefault().toZoneId()).toInstant().toEpochMilli();
} else if (year != null) {
return LocalDate.of(year.getValue(), java.time.Month.DECEMBER, 1).with(TemporalAdjusters.lastDayOfMonth()).
atTime(OffsetTime.MAX).toLocalDateTime().atZone(TimeZone.getDefault().toZoneId()).toInstant().toEpochMilli();
}
return 0;
}
But it looks really complicated to me. Is there any better/shorter way to get these values?
YearMonth
Yes, there is a slightly better way. Use the YearMonth
class included with java.time.
Also, break up that call-chain into separate statements to make it more readable and easier to trace/debug. Trust the JVM to optimize on your behalf; only use call-chaining where it makes your code more readable and easier to understand.
Going through TimeZone
to get the JVM’s current default time zone is unnecessary. Instead, call ZoneId.systemDefault()
.
Set up some input values.
// Inputs
Year year = Year.of ( 2015 );
Month month = Month.DECEMBER;
The core part of your method.
// Code for your method.
YearMonth yearMonth = year.atMonth ( month ); // Instantiate a YearMonth from a Year and a Month.
LocalDate localDate = yearMonth.atDay ( 1 ); // First day of month.
ZoneId zoneId = ZoneId.systemDefault (); // Or… ZoneId.of("America/Montreal");
ZonedDateTime zdt = localDate.atStartOfDay ( zoneId );
long millis = zdt.toInstant ().toEpochMilli ();
Dump to console.
System.out.println ( "year: " + year + " | month: " + month + " | yearMonth: " + yearMonth + " | zoneId:" + zoneId + " | zdt: " + zdt + " | millis: " + millis );
year: 2015 | month: DECEMBER | yearMonth: 2015-12 | zoneId:America/Los_Angeles | zdt: 2015-12-01T00:00-08:00[America/Los_Angeles] | millis: 1448956800000
Even better, pass the YearMonth
instance to your method rather than the pair of Year
and Month
objects. If your other business logic is using the Year
+ Month
pair, use YearMonth
instead – that’s what it’s for.