最近拜读了一篇不错的文章原文:http://lrwinx.github.io/2017/03/04/%E7%BB%86%E6%80%9D%E6%9E%81%E6%81%90-%E4%BD%A0%E7%9C%9F%E7%9A%84%E4%BC%9A%E5%86%99java%E5%90%97/
其中提到了一个日期应用场景:
项目开发阶段,有一个关于下单发货的需求:如果今天下午3点前进行下单,那么发货时间是明天,如果今天下午3点后进行下单,那么发货时间是后天,如果被确定的时间是周日,那么在此时间上再加1天为发货时间。
作者建议:“对于时间的计算我们要考虑joda-time这种类似的成熟时间计算框架来写代码,它会让代码更加简洁和易读。”
作者的代码:
public class DateQuestion2 {
private static final DateTime DISTRIBUTION_TIME_SPLIT_TIME = new DateTime().withTime(15, 0, 0, 0);
public static Date calculateDistributionTimeByOrderCreateTime(Date orderCreateTime) {
DateTime orderCreateDateTime = new DateTime(orderCreateTime);
Date tomorrow = orderCreateDateTime.plusDays(1).toDate();
Date theDayAfterTomorrow = orderCreateDateTime.plusDays(2).toDate();
return orderCreateDateTime.isAfter(DISTRIBUTION_TIME_SPLIT_TIME) ? wrapDistributionTime(theDayAfterTomorrow) : wrapDistributionTime(tomorrow);
}
private static Date wrapDistributionTime(Date distributionTime) {
DateTime currentDistributionDateTime = new DateTime(distributionTime);
DateTime plusOneDay = currentDistributionDateTime.plusDays(1);
boolean isSunday = (DateTimeConstants.SUNDAY == currentDistributionDateTime.getDayOfWeek());
return isSunday ? plusOneDay.toDate() : currentDistributionDateTime.toDate();
}
}
本人用java8的日期类实现了类似功能:
public class DateQuestion {
private static final LocalDate TODAY = LocalDate.now(ZoneId.systemDefault());
private static final LocalDateTime DEFAULT_TIME_SPLIT = LocalDateTime.of(TODAY, LocalTime.of(17, 0, 0));
public static Date calculateDistributionTimeByOrderCreateTime(Date orderCreateTime) {
LocalDateTime orderCreateLocalTime = Instant.ofEpochMilli(orderCreateTime.getTime()).atZone(ZoneId.systemDefault()).toLocalDateTime();
LocalDateTime result;
if (orderCreateLocalTime.isBefore(DEFAULT_TIME_SPLIT)) {
result = orderCreateLocalTime.plusDays(1);
} else {
result = orderCreateLocalTime.plusDays(2);
}
if (result.getDayOfWeek() == DayOfWeek.SUNDAY) {
result = result.plusDays(1);
}
return Date.from(result.toInstant(OffsetDateTime.now().getOffset()));
}
}
编写的单元测试类:
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import java.time.LocalDateTime;
import java.time.OffsetDateTime;
import java.util.Calendar;
import java.util.Date;
class DateQuestionTest {
@Test
@DisplayName("joda和java8日期")
void jodaAndJava8DateTest() {
LocalDateTime localDateTime = LocalDateTime.of(2018, Calendar.DECEMBER, 22, 10, 30);
Date date = Date.from(localDateTime.toInstant(OffsetDateTime.now().getOffset()));
// java8方式
Date dateGet = DateQuestion.calculateDistributionTimeByOrderCreateTime(date);
// joda方式
Date dateGet2 = DateQuestion2.calculateDistributionTimeByOrderCreateTime(date);
Assertions.assertEquals(dateGet, dateGet2);
}
}
最终运行通过。
总结
结合之前未采用java8时封装日期的痛苦经历,最近接触java8日期时间类之后,下决心以后采用java8或者增强的日期时间库来实现日期相关功能。
joda-time 对日期类之间的转换支持更好一些,提供了更丰富的日期处理函数,未来有复杂的日期需求会考虑使用。
另外附IBM网站关于joda-time的一篇很不错的文章:https://www.ibm.com/developerworks/cn/java/j-jodatime.html