日期类操作

Posted by Pismery Liu on Wednesday, November 14, 2018

TOC

Java 8 新增日期类基本使用介绍

Java 8 – Date and Time Operation

介绍

Java 8 新增许多日期操作类来替换原来的Date,Calendar,timestamp,SimpleDateFormat(线程不安全)。

新增类大致如下:

  1. 日期类
    • Instant: 瞬时实例;
    • LocalDate: 本地日期,不包含具体时间 例如:2014-01-14 可以用来记录生日、纪念日、加盟日等;
    • LocalTime: 本地时间,不包含日期;
    • LocalDateTime: 组合了日期和时间,但不包含时差和时区信息;
    • ZonedDateTime: 最完整的日期时间,包含时区和相对UTC或格林威治的时差;
  2. 持续时间类
    • Duration: 表示两个Instant间的一段时间;具有:纳秒值(小于一秒的部分),秒钟值(一共有几秒)
    • Period: 表示两个LocalDate间的一段时间;内部使用三个int值分表表示年、月、
  3. 格式化和解析类
    • DateTimeFormatter

日期类

LocalDate

public static void init() {
    log.debug("LocalDate.MAX: "+LocalDate.MAX); //LocalDate.MAX: +999999999-12-31
    log.debug("LocalDate.MIN: "+LocalDate.MIN); //LocalDate.MIN: -999999999-01-01
    log.debug("LocalDate.of(2015, Month.SEPTEMBER,12): "+LocalDate.of(2015, Month.SEPTEMBER,12)); //LocalDate.of(2015, Month.SEPTEMBER,12): 2015-09-12
    log.debug("LocalDate.now(): "+LocalDate.now()); //LocalDate.now(): 2018-09-09
}

public static void apiBaseUse() {
    LocalDate localDate = LocalDate.of(2015,11,12);

    log.debug("toString: "+localDate.toString()); //toString: 2015-11-12
    log.debug("getYear: "+localDate.getYear()); //getYear: 2015

    log.debug("getMonth: "+localDate.getMonth()); //getMonth: NOVEMBER
    log.debug("getMonthValue: "+localDate.getMonthValue()); //getMonthValue: 11

    log.debug("getDayOfWeek: "+localDate.getDayOfWeek()); //getDayOfWeek: THURSDAY
    log.debug("getDayOfMonth: "+localDate.getDayOfMonth()); //getDayOfMonth: 12
    log.debug("getDayOfYear: "+localDate.getDayOfYear()); //getDayOfYear: 316

    log.debug("isLeapYear: "+localDate.isLeapYear()); //isLeapYear: false
    log.debug("lengthOfMonth: "+localDate.lengthOfMonth()); //lengthOfMonth: 30
    log.debug("lengthOfYear: "+localDate.lengthOfYear()); //lengthOfYear: 365
}

## 求两个日期的天数
public static long getBetweenDays(LocalDate d1,LocalDate d2) {
    return Math.abs(d1.toEpochDay() - d2.toEpochDay());
}
方法 描述
now,of 根据当前时间或指定年月日来创建LocalDate对象
plusDays,plusWeeks,plusMonths,plusYears 向当前对象添加天、周、月、年
minusDays,minusWeeks,minusMonths,plusYears 向当前对象减去天、周、月、年
plus,minus 添加或减少一个Duration或者Perid
WithDayOfMonth,WithDayOfYear,withMonth,withYear 将月份天数、年份天数、年份修改为指定的值,并返回一个新的LocalDate对象
getDayOfMonth 获得月份天数(1~31)
getDayOfYear 获得年份天数(1~366)
getDayOfWeek 获得星期几
getMonth,getMonthValue 获得月份,或者Month枚举值,或者1-12数字
getYear 获得年份
isBefore,isAfter 比较日期
isleapYear 是否为闰年

LocalTime

public static void init() {
    log.debug("LocalTime.MAX: "+ LocalTime.MAX); //LocalTime.MAX: 23:59:59.999999999
    log.debug("LocalTime.MIDNIGHT: "+ LocalTime.MIDNIGHT); //LocalTime.MIDNIGHT: 00:00
    log.debug("LocalTime.MIN: "+ LocalTime.MIN); //LocalTime.MIN: 00:00
    log.debug("LocalTime.NOON: "+ LocalTime.NOON); //LocalTime.NOON: 12:00
}

public static void apiBasicUse() {
    LocalTime time = LocalTime.of(7,20,10,110000000);

    log.debug("time.getHour(): "+time.getHour()); //time.getHour(): 7
    log.debug("time.getMinute(): "+time.getMinute()); //time.getMinute(): 20
    log.debug("time.getSecond(): "+time.getSecond()); //time.getSecond(): 10
    log.debug("time.getLong(ChronoField.MICRO_OF_DAY): "+ time.getLong(ChronoField.MICRO_OF_DAY)); //time.getLong(ChronoField.MICRO_OF_DAY): 26410110000
    log.debug("time.getNano(): "+time.getNano()); //time.getNano(): 110000000

    log.debug("time.plusHours(17): "+ time.plusHours(17)); //time.plusHours(17): 00:20:10.110
    log.debug("time.plus(Duration.ofHours(17)): "+time.plus(Duration.ofHours(17))); //time.plus(Duration.ofHours(17)): 00:20:10.110

}
方法 描述
now,of 根据当前时间或指定年月日来创建LocalTime对象
plusHours,plusMinutes,plusSeconds,plusNanos 向当前对象添加时、分秒、微秒
minusHours,minusMinutes,minusSeconds,minusNanos 向当前对象减去时、分秒、微秒
plus,minus 添加或减少一个Duration
WithHour,WithMinute,withSecond,withNano 将时、分、秒、微秒修改为指定的值,并返回一个新的LocalTime对象
getHour,getMinute,getSecond,getNano 获取事件对象的时、分、秒、微秒
isBefore,isAfter 比较时间

持续时间类

Duration

Duration表示秒、纳秒,分钟,小时和天数的持续时间

public static long getLivedDays() {
    LocalDateTime birthday = LocalDateTime.of(
            LocalDate.of(1990, Month.JANUARY, 1),
            LocalTime.of(10, 10));
    LocalDateTime deathDay = LocalDateTime.of(
            LocalDate.of(2090, Month.JANUARY, 1),
            LocalTime.of(10, 10));

    return Duration.between(birthday, deathDay).toDays(); //36525
}

Period

Period表示年,月,日的时间差值。

public static Period getLivedDays() {
    LocalDate birthday = LocalDate.of(1990, Month.JANUARY, 1);
    LocalDate deathDay = LocalDate.of(2090, Month.JANUARY, 1);

    return Period.between(birthday,deathDay); //36525
}

## 测试
@Test
public void getLivedDays() {
    assertThat(PeriodDemo.getLivedDays().getYears()).isEqualTo(100);
    assertThat(PeriodDemo.getLivedDays().getMonths()).isEqualTo(0);
    assertThat(PeriodDemo.getLivedDays().getDays()).isEqualTo(0);
}

基本操作

Convert between LocalDate and LocalDateTime to java.util.Date

public static Date asDate(LocalDate localDate) {
    return Date.from(localDate.atStartOfDay().atZone(ZoneId.systemDefault()).toInstant());
}

public static Date asDate(LocalDateTime localDateTime) {
    return Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant());
}

public static LocalDate asLocalDate(Date date) {
    return Instant.ofEpochMilli(date.getTime()).atZone(ZoneId.systemDefault()).toLocalDate();
}

public static LocalDateTime asLocalDateTime(Date date) {
    return Instant.ofEpochMilli(date.getTime()).atZone(ZoneId.systemDefault()).toLocalDateTime();
}

Convert between LocalDate to java.sql.Date

public static java.sql.Date asDate(LocalDate localDate) {
    return java.sql.Date.valueOf( localDate );
}

public static LocalDate asLocalDate(java.sql.Date date) {
    return date.toLocalDate();
}

Convert between String to LocalDate

DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("dd/MM/yyyy");
String dateString = "14/07/2018";
 
LocalDate localDateObj = LocalDate.parse(dateString, dateTimeFormatter);    //String to LocalDate
 
String dateStr = localDateObj.format(dateTimeFormatter);        //LocalDate to String

LocalDate localDate = LocalDate.parse( dateString ); ##defaul pattern yyyy-MM-dd

Java Convert Date or Timestamp Between Timezones

Convert ZonedDateTime between timezones

import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
 
public class Main {
    private static final String DATE_FORMAT = "dd-M-yyyy hh:mm:ss a z";
    private static final DateTimeFormatter formatter = DateTimeFormatter.ofPattern(DATE_FORMAT);
     
    public static void main(String[] args) {
        ZoneId fromTimeZone = ZoneId.of("Asia/Kolkata");    //Source timezone
        ZoneId toTimeZone = ZoneId.of("America/New_York");  //Target timezone
         
        LocalDateTime today = LocalDateTime.now();          //Current time
        ZonedDateTime currentISTime = today.atZone(fromTimeZone);  //Zoned date time at source timezone    
        ZonedDateTime currentETime = currentISTime.withZoneSameInstant(toTimeZone);//Zoned date time at target timezone
         
        //Format date time - optional
        System.out.println(formatter.format(currentISTime));
        System.out.println(formatter.format(currentETime));
    }
}
 
//Output:
 
14-7-2018 11:57:46 PM IST
14-7-2018 02:27:46 PM EDT

Convert Date between timezones

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.TimeZone;
 
public class Main {
    static SimpleDateFormat FORMATTER = new SimpleDateFormat("MM/dd/yyyy 'at' hh:mma z");
     
    public static void main(String[] args) {
        TimeZone etTimeZone = TimeZone.getTimeZone("America/New_York"); //Target timezone
        Date currentDate = new Date();
         
        System.out.println(FORMATTER.format(currentDate));  //Date in current timezone
         
        FORMATTER.setTimeZone(etTimeZone);
         
        System.out.println(FORMATTER.format(currentDate));  //Date in target timezone
    }
}
 
//Output:
 
07/15/2018 at 12:13AM IST
07/14/2018 at 02:43PM EDT

Convert Calendar between timezones

import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.TimeZone;
 
public class Main {
    static SimpleDateFormat FORMATTER = new SimpleDateFormat("MM/dd/yyyy 'at' hh:mma z");
     
    public static void main(String[] args) {
        TimeZone istTimeZone = TimeZone.getTimeZone("Asia/Kolkata");    //Source timezone
        TimeZone etTimeZone = TimeZone.getTimeZone("America/New_York"); //Target timezone
         
        Calendar today = Calendar.getInstance(istTimeZone);
         
        System.out.println(FORMATTER.format(today.getTime()));  //07/15/2018 at 12:35AM IST
         
        //Change timezone in formatter
        FORMATTER.setTimeZone(etTimeZone);         
         
        System.out.println(FORMATTER.format(today.getTime()));  //07/14/2018 at 03:05PM EDT
         
        //OR calendar static methods
         
        System.out.println(today.get(Calendar.HOUR));       //0
        System.out.println(today.get(Calendar.MINUTE));     //37
        System.out.println(today.get(Calendar.SECOND));     //9
         
        //Change calendar timezone
        today.setTimeZone(etTimeZone);
         
        System.out.println(today.get(Calendar.HOUR));       //3
        System.out.println(today.get(Calendar.MINUTE));     //7
        System.out.println(today.get(Calendar.SECOND));     //9
    }
}

Data Compare

Class: - java.time.LocalDate - java.time.LocalTime - java.time.LocalDateTime.

Method: - date1.isAfter( date2 ) – It returns true is date1 comes after date2; else false. - date1.isBefore( date2 ) – It returns true is date1 comes before date2; else false. - date1.compareTo( date2 ) – It returns ‘positive number’ is date1 comes after date2; else ‘negative number’. A value ‘0’ means both dates are equal.

public static void compareLocalDates() {
    LocalDate todayLocalDate = LocalDate.now();
    LocalDate pastLocalDate = LocalDate.of(2018, 10, 01);
    DateTimeFormatter sdf = DateTimeFormatter.ofPattern("yyyy-MM-dd");
    String date1 = sdf.format(todayLocalDate);
    String date2 = sdf.format(pastLocalDate);
    
    //isAfter() Method
    System.out.println(date1 + " is after " + date2 + " :: " + todayLocalDate.isAfter(pastLocalDate));    //true
    //isBefore() Method
    System.out.println(date2 + " is before " + date2 + " :: " + pastLocalDate.isBefore(todayLocalDate));  //true
    //compareTo()
    int dateDifference = todayLocalDate.compareTo(pastLocalDate);
    System.out.println("Date diff : " + dateDifference);

    if (dateDifference > 0)
        System.out.println(date1 + " > " + date2);           //prints
    else if (dateDifference < 0)
        System.out.println(date1 + " < " + date2);       //does not print
    else
        System.out.println(date1 + " = " + date2);          //does not print
}

## 结果
2018-10-18 is after 2018-10-01 :: true
2018-10-01 is before 2018-10-01 :: true
Date diff : 17
2018-10-18 > 2018-10-01

Writing custom TemporalAdjuster

public static void nextWorkDate() {
    LocalDate today = LocalDate.now();
    TemporalAdjuster nextWorkingDayAdjuster = TemporalAdjusters.ofDateAdjuster(localDate -> {
        DayOfWeek dayOfWeek = localDate.getDayOfWeek();
        if (dayOfWeek == DayOfWeek.FRIDAY) {
            return localDate.plusDays(3);
        } else if (dayOfWeek == DayOfWeek.SATURDAY) {
            return localDate.plusDays(2);
        }
        return localDate.plusDays(1);
    });
    System.out.println(today.with(nextWorkingDayAdjuster));
}