使用Java 8 time API获取第一次和最后一次时间(以毫秒为单位)



我正在将我的时间计算从自实现代码转换为Java 8 time API。

我需要java.time.Yearjava.time.Month类的开始和结束时间(以毫秒为单位),我计划稍后在JFreeChart的另一层中使用它们。

我需要像getFirstMillisecond()&来自JFreeChart的org.jfree.data.time.RegularTimePeriod类的getLastMilliSecond()

我已经实现了类似的代码

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;
}

但在我看来,这真的很复杂。有什么更好/更短的方法来获得这些值吗?

YearMonth

是的,有一个稍微好一点的方法。使用java.time.中包含的YearMonth

此外,将调用链分解为单独的语句,使其更可读,更易于跟踪/调试。相信JVM会代表您进行优化;只在使代码更可读、更易于理解的地方使用调用链。

通过TimeZone获取JVM的当前默认时区是不必要的。相反,请调用ZoneId.systemDefault()

设置一些输入值。

// Inputs
Year year = Year.of ( 2015 );
Month month = Month.DECEMBER;

你的方法的核心部分。

// 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 ();

转储到控制台。

System.out.println ( "year: " + year + " | month: " + month + " | yearMonth: " + yearMonth + " | zoneId:" + zoneId + " | zdt: " + zdt + " | millis: " + millis );

年份:2015 |月份:12月|年份月份:2015-12 |地区ID:America/Loss_Angeles|zdt:2015-12-01T00:00-08:00[美洲/Loss_Aangeles]|百万:144895680000

更好的是,将YearMonth实例传递给您的方法,而不是一对YearMonth对象。如果您的其他业务逻辑正在使用Year+Month对,请改用YearMonth——这就是它的用途。

除了在给定null年份时返回0并信任系统默认时区的可疑做法外,您还可以按如下方式重写方法:

public static long getStartTimeInMillis(java.time.Year year, java.time.Month month) {
    if (year == null) {
        return 0;
    }
    if (month == null) {
        month = Month.JANUARY;
    }
    return year.atMonth(month)
            .atDay(1)
            .atStartOfDay()
            .atZone(ZoneId.systemDefault())
            .toInstant()
            .toEpochMilli();
}
public static long getEndTimeInMillis(java.time.Year year, java.time.Month month) {
    if (year == null) {
        return 0;
    }
    if (month == null) {
        month = Month.JANUARY;
    }
    return year.atMonth(month)
            .atEndOfMonth()
            .atTime(LocalTime.MAX)
            .atZone(ZoneId.systemDefault())
            .toInstant()
            .toEpochMilli();
};

为了扩展,如果年份是null,那么最好只抛出一个NullPointerException。如果您的年份为空,那么上游代码中可能存在错误。返回一个毫无意义的0只会进一步推动bug,并使其更难追踪。这一原理被称为"快速失效"。

对于严肃的生产代码来说,依赖系统默认时区是个坏主意,因为它往往会导致问题,因为服务器的配置可能不可预测(例如GMT),或者当地理分布的服务器位于不同时区时,可能会出现问题。仔细考虑"我计算这些时间所依据的时区是什么?"

我会像这样重构

public static long getStartTimeInMillis(java.time.Year year, Optional<Month> monthOpt) {
    Month month = monthOpt.orElse(Month.JANUARY);
    if (year != null) {
        return LocalDate.of(year.getValue(), month, 1)
                .with(TemporalAdjusters.firstDayOfMonth())
                .atStartOfDay()
                .atZone(TimeZone.getDefault().toZoneId())
                .toInstant()
                .toEpochMilli();
    }
    return 0;
}

相关内容

  • 没有找到相关文章

最新更新