日期与时间


#Java 笔记


时间戳

long currentTimeMillis = System.currentTimeMillis();  // 毫秒级时间戳
long currentTimestamp = System.currentTimeMillis()/1000;  // 秒级时间戳

从 Java 8 开始加入的 Instant 类也可以获取秒级时间戳:

import java.time.Instant;

public class Main {

    public static void main(String[] args) {
        long currentTimestamp1 = System.currentTimeMillis()/1000;  // 秒级时间戳
        long currentTimestamp2 = Instant.now().getEpochSecond();   // 这个也是秒级时间戳

        System.out.println("当前秒级时间戳:" + currentTimestamp1);
        System.out.println("当前秒级时间戳:" + currentTimestamp2);
    }
}

java.time.LocalDateTime

LocalDatetime 类从 Java 8 开始引入。

该类的一个显著特点是,月从1开始,而不是从0开始,年也不用像 java.util.Date 那样加一个 1900。

获取当前日期和时间

import java.time.LocalDateTime;

public class Main {

    public static void main(String[] args) {
        LocalDateTime localDateTime = LocalDateTime.now();
        System.out.println(localDateTime);
    }
}

运行结果示例:

2019-06-22T21:50:20.760

分表获取当前年月日时分秒

import java.time.LocalDateTime;

public class Main {

    public static void main(String[] args) {
        LocalDateTime localDateTime = LocalDateTime.now();
        System.out.printf("%s-%s-%s %s:%s:%s\n",
                localDateTime.getYear(), localDateTime.getMonth().getValue(), localDateTime.getDayOfMonth(),
                localDateTime.getHour(), localDateTime.getMinute(), localDateTime.getSecond());
    }
    
}

运行结果示例:

2019-6-22 21:51:46

将秒级时间戳转换为 LocalDateTime

import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;

public class Main {

    public static void main(String[] args) {
        LocalDateTime localDateTime = LocalDateTime.ofInstant(Instant.ofEpochSecond(1561211629L), ZoneId.systemDefault());
        System.out.printf("%s-%s-%s %s:%s:%s\n",
                localDateTime.getYear(), localDateTime.getMonth().getValue(), localDateTime.getDayOfMonth(),
                localDateTime.getHour(), localDateTime.getMinute(), localDateTime.getSecond());
    }

}

将 LocalDateTime 转换成时间戳

import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;

public class Main {

    public static void main(String[] args) {
        LocalDateTime localDateTime = LocalDateTime.of(2019, 6, 23, 9, 0);
        System.out.println(localDateTime);
        Instant instant = localDateTime.atZone(ZoneId.systemDefault()).toInstant();
        System.out.println(instant.getEpochSecond());  // 秒级时间戳
        System.out.println(instant.toEpochMilli());    // 毫秒级时间戳
    }

}

运行结果示例:

2019-06-23T09:00
1561251600
1561251600000

也可以像下面这样获取秒级时间戳:

import java.time.LocalDateTime;
import java.time.ZoneId;

public class Main {

    public static void main(String[] args) {
        LocalDateTime localDateTime = LocalDateTime.of(2019, 6, 23, 9, 0);
        System.out.println( localDateTime.atZone(ZoneId.systemDefault()).toEpochSecond() );;
    }

}

格式化 LocalDateTime

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.FormatStyle;

public class Main {

    public static void main(String[] args) {
        LocalDateTime localDateTime = LocalDateTime.now();
        System.out.println( localDateTime.format(DateTimeFormatter.ISO_DATE) );
        System.out.println( localDateTime.format(DateTimeFormatter.ofLocalizedDate(FormatStyle.FULL)) );
        System.out.println( localDateTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")) );
    }

}

运行结果示例:

2019-06-22
2019年6月22日 星期六
2019-06-22 22:02:38

字符串转换为 LocalDateTime

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

public class Main {

    public static void main(String[] args) {
        DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        LocalDateTime localDateTime = LocalDateTime.parse("2019-06-18 12:00:00", df);
        System.out.println( localDateTime );
    }

}

模式可以在 DateTimeFormatter 的源码注释中找到:

 *  Symbol  Meaning                     Presentation      Examples
 *  ------  -------                     ------------      -------
 *   G       era                         text              AD; Anno Domini; A
 *   u       year                        year              2004; 04
 *   y       year-of-era                 year              2004; 04
 *   D       day-of-year                 number            189
 *   M/L     month-of-year               number/text       7; 07; Jul; July; J
 *   d       day-of-month                number            10
 *
 *   Q/q     quarter-of-year             number/text       3; 03; Q3; 3rd quarter
 *   Y       week-based-year             year              1996; 96
 *   w       week-of-week-based-year     number            27
 *   W       week-of-month               number            4
 *   E       day-of-week                 text              Tue; Tuesday; T
 *   e/c     localized day-of-week       number/text       2; 02; Tue; Tuesday; T
 *   F       week-of-month               number            3
 *
 *   a       am-pm-of-day                text              PM
 *   h       clock-hour-of-am-pm (1-12)  number            12
 *   K       hour-of-am-pm (0-11)        number            0
 *   k       clock-hour-of-am-pm (1-24)  number            0
 *
 *   H       hour-of-day (0-23)          number            0
 *   m       minute-of-hour              number            30
 *   s       second-of-minute            number            55
 *   S       fraction-of-second          fraction          978
 *   A       milli-of-day                number            1234
 *   n       nano-of-second              number            987654321
 *   N       nano-of-day                 number            1234000000
 *
 *   V       time-zone ID                zone-id           America/Los_Angeles; Z; -08:30
 *   z       time-zone name              zone-name         Pacific Standard Time; PST
 *   O       localized zone-offset       offset-O          GMT+8; GMT+08:00; UTC-08:00;
 *   X       zone-offset 'Z' for zero    offset-X          Z; -08; -0830; -08:30; -083015; -08:30:15;
 *   x       zone-offset                 offset-x          +0000; -08; -0830; -08:30; -083015; -08:30:15;
 *   Z       zone-offset                 offset-Z          +0000; -0800; -08:00;
 *
 *   p       pad next                    pad modifier      1
 *
 *   '       escape for text             delimiter
 *   ''      single quote                literal           '
 *   [       optional section start
 *   ]       optional section end
 *   #       reserved for future use
 *   {       reserved for future use
 *   }       reserved for future use

获取某个时间对应的月份有多少天

import java.time.LocalDateTime;

public class Main {

    public static void main(String[] args) {
        LocalDateTime localDateTime = LocalDateTime.now();
        System.out.println(localDateTime.toLocalDate().lengthOfMonth()); 
    }

}

toLocalDate 用于获取 LocalDate 对象。

lengthOfMonth 方法返回的是 int 类型。

运行结果示例:

30

获取一段时间前的时间

import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;

public class Main {

    public static void main(String[] args) {
        LocalDateTime localDateTime1 = LocalDateTime.now();
        System.out.println(localDateTime1);
        LocalDateTime localDateTime2 = localDateTime1.minus(32, ChronoUnit.DAYS); // 32天前的时间
        System.out.println(localDateTime1); // localDateTime1 保持不变
        System.out.println(localDateTime2);
    }

}

运行结果示例:

2019-06-22T22:11:59.322
2019-06-22T22:11:59.322
2019-05-21T22:11:59.322

获取一段时间后的时间

import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;

public class Main {

    public static void main(String[] args) {
        LocalDateTime localDateTime1 = LocalDateTime.now();
        System.out.println("localDateTime1: " + localDateTime1);
        LocalDateTime localDateTime2 = localDateTime1.plus(32, ChronoUnit.HOURS); // 32小时后的时间
        System.out.println("localDateTime1: " + localDateTime1); // localDateTime1 保持不变
        System.out.println("localDateTime2: " + localDateTime2);
    }

}

运行结果示例:

localDateTime1: 2019-06-23T08:48:14.321
localDateTime1: 2019-06-23T08:48:14.321
localDateTime2: 2019-06-24T16:48:14.321

指定时间

import java.time.LocalDateTime;

public class Main {

    public static void main(String[] args) {
        LocalDateTime localDateTime1 = LocalDateTime.of(2019, 6, 23, 9, 0);
        System.out.println("localDateTime1: " + localDateTime1);
        LocalDateTime localDateTime2 = localDateTime1.withHour(20); // 将 hour 改成 20
        System.out.println("localDateTime1: " + localDateTime1);    // localDateTime1 保持不变
        System.out.println("localDateTime2: " + localDateTime2);
    }

}

运行结果示例:

localDateTime1: 2019-06-23T09:00
localDateTime1: 2019-06-23T09:00
localDateTime2: 2019-06-23T20:00

获取当天最早的时间、最晚的时间

import java.time.LocalDateTime;
import java.time.LocalTime;

public class Main {

    public static void main(String[] args) {
        LocalDateTime localDateTime = LocalDateTime.of(2019, 6, 23, 9, 0);
        System.out.println(LocalDateTime.of(localDateTime.toLocalDate(), LocalTime.MIN)); // 当前最早的时间
        System.out.println(LocalDateTime.of(localDateTime.toLocalDate(), LocalTime.MAX)); // 当天最晚的时间
    }

}

运行结果示例:

2019-06-23T00:00
2019-06-23T23:59:59.999999999

LocalDateTime 转换为 Date

import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.Date;

public class Main {

    public static void main(String[] args) {
        LocalDateTime localDateTime = LocalDateTime.of(2019, 6, 23, 9, 0);
        Date date = Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant());
        System.out.println(date);
        System.out.println(date.getTime());  // 毫秒级时间戳
    }

}

运行结果示例:

Sun Jun 23 09:00:00 CST 2019
1561251600000

判断两个 LocalDateTime 的时间先后关系

import java.time.LocalDateTime;

public class Main {

    public static void main(String[] args) {

        LocalDateTime localDateTime01 = LocalDateTime.of(2019, 6, 18, 12, 0);
        LocalDateTime localDateTime02 = LocalDateTime.of(2019, 6, 1, 12, 0);

        System.out.println( localDateTime01.isAfter(localDateTime02) );   // 类似的,还有 isBefore 等方法

    }

}

运行结果:

true

获取两个 LocalDateTime 之间的间隔

import java.time.Duration;
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;

public class Main {

    public static void main(String[] args) {

        LocalDateTime localDateTime01 = LocalDateTime.of(2019, 6, 18, 12, 0);
        LocalDateTime localDateTime02 = LocalDateTime.of(2019, 6, 18, 13, 0);

        Duration duration = Duration.between(localDateTime01, localDateTime02);

        System.out.println( duration.get(ChronoUnit.SECONDS) );
        System.out.println( duration.getSeconds() );

    }

}

运行结果:

3600
3600

java.time.LocalDate

LocalDate 类从 Java 8 开始引入。相对于 LocalDateTime,LocalDate 仅处理年月日这三个维度。

获取当前年月日对应的 LocalDate

import java.time.LocalDate;

public class Main {

    public static void main(String[] args) {

        LocalDate localDate = LocalDate.now();
        
        System.out.println(localDate);
        System.out.printf("%s-%s-%s\n", localDate.getYear(), localDate.getMonthValue(), localDate.getDayOfMonth());
    }

}

运行结果示例:

2019-06-24
2019-6-24

生成指定时间的 LocalDate

import java.time.LocalDate;

public class Main {

    public static void main(String[] args) {

        LocalDate localDate = LocalDate.of(2019, 6, 18);

        System.out.println(localDate);
        System.out.printf("%s-%s-%s\n", localDate.getYear(), localDate.getMonthValue(), localDate.getDayOfMonth());
    }

}

运行结果:

2019-06-18
2019-6-18

获取指定时间是当年的第几天

import java.time.LocalDate;

public class Main {

    public static void main(String[] args) {
        LocalDate localDate = LocalDate.of(2019, 6, 18);
        System.out.println(localDate.getDayOfYear());
    }

}

运行结果:

169

将当年的第几天转换为 LocalDate

import java.time.LocalDate;

public class Main {

    public static void main(String[] args) {
        LocalDate localDate = LocalDate.ofYearDay(2019, 169);
        System.out.println(localDate);
    }

}

运行结果:

2019-06-18

计算两个 LocalDate 之间间隔的时间

import java.time.LocalDate;
import java.time.Period;
import java.time.temporal.ChronoUnit;

public class Main {

    public static void main(String[] args) {

        LocalDate localDate01 = LocalDate.of(2019, 6, 18);
        LocalDate localDate02 = LocalDate.of(2019, 6, 12);

        Period period = Period.between(localDate01, localDate02);

        System.out.println( period.get(ChronoUnit.DAYS) );

    }

}

运行结果:

-6

java.time.LocalTime

LocalTime 类从 Java 8 开始引入。相对于 LocalDateTime,LocalDate 仅处理时分秒这三个维度。秒,可以精确到纳秒。1秒等于10^9(10的9次方)纳秒。

获取当前时间对应的 LocalTime

import java.time.LocalTime;

public class Main {

    public static void main(String[] args) {
        LocalTime localTime = LocalTime.now();
        System.out.println( localTime );
        System.out.printf("%s:%s:%s %s\n", localTime.getHour(), localTime.getMinute(), localTime.getSecond(), localTime.getNano());
    }

}

运行结果示例:

23:42:15.555
23:42:15 555000000

生成指定时间的 LocalTime

import java.time.LocalTime;

public class Main {

    public static void main(String[] args) {
        LocalTime localTime = LocalTime.of(10, 25, 59);
        System.out.println( localTime );
    }

}

运行结果:

10:25:59

获取当前时间是当日的第几秒

import java.time.LocalTime;

public class Main {

    public static void main(String[] args) {
        LocalTime localTime = LocalTime.of(10, 25, 59);
        System.out.println(localTime.toSecondOfDay());
    }

}

运行结果:

37559

将当日的第几秒转换为 LocalTime

import java.time.LocalTime;

public class Main {

    public static void main(String[] args) {
        LocalTime localTime = LocalTime.ofSecondOfDay(37559);
        System.out.println(localTime);
    }

}

运行结果:

10:25:59

java.util.Date

获取当前时间

import java.util.Date;

public class Main {

    public static void main(String[] args) {
        Date date = new Date();     // 当前时间
        System.out.println("年: " + (1900+date.getYear()));  // 要加上 1900
        System.out.println("月: " + (1+date.getMonth()));    // 要加上 1
        System.out.println("日: " + date.getDate());
        System.out.println("时: " + date.getHours());
        System.out.println("分: " + date.getMinutes());
        System.out.println("秒: " + date.getSeconds());
    }

}

注意,上面用到的 get 开头的方法,已经被废弃了。

运行结果示例:

年: 2019
月: 6
日: 23
时: 10
分: 10
秒: 46

时间戳转换为 Date

import java.time.Instant;
import java.util.Date;

public class Main {

    public static void main(String[] args) {
        // 方法1
        Date date1 = new Date(1561256015L*1000); // 要使用毫秒级
        System.out.println(date1);

        // 方法2
        Date date2 = Date.from(Instant.ofEpochSecond(1561256015L));
        System.out.println(date2);
    }

}

运行结果示例:

Sun Jun 23 10:13:35 CST 2019
Sun Jun 23 10:13:35 CST 2019

Date 转换为时间戳

import java.util.Date;

public class Main {

    public static void main(String[] args) {
        Date date = new Date();
        System.out.println(date.toInstant().getEpochSecond());  // 返回 long 类型 
    }

}

运行结果示例:

1561256111

格式化 Date

import java.text.SimpleDateFormat;
import java.util.Date;

public class Main {

    public static void main(String[] args) {

        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");

        Date date = new Date();

        System.out.println( df.format(date) );

    }

}

运行结果示例:

2019-06-24 06:53:56

注意,SimpleDateFormat 是线程不安全的,也就是不要在多线程中共享一个 SimpleDateFormat 实例。

字符串转换为 Date

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

public class Main {

    public static void main(String[] args) throws ParseException {

        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

        Date date = df.parse("2019-06-18 12:00:00");

        System.out.println( date );
    }

}

运行结果:

Tue Jun 18 00:00:00 CST 2019

java.sql.Date

java.sql.Date 继承自 java.util.Date。不同的是,只支持年月日,不支持时分秒。

不支持时分秒

import java.sql.Date;

public class Main {

    public static void main(String[] args) {

        Date date = new Date(2019-1900, 6,18);
        System.out.println(date);
        System.out.println(date.getMinutes());  // 抛出异常

    }

}

运行时会抛出异常:

2019-07-18
Exception in thread "main" java.lang.IllegalArgumentException
	at java.sql.Date.getMinutes(Date.java:200)
	at Main.main(Main.java:9)

java.sql.Date 与时间戳互相转换

import java.sql.Date;

public class Main {

    public static void main(String[] args) {

        // 时间戳到 Date
        Date date = new Date(1561256015L*1000); // 毫秒级时间戳
        System.out.println(date);

        // Date 到时间戳
        System.out.println(date.getTime());

    }

}

运行结果:

2019-06-23
1561256015000

java.sql.Date 转换为 Instant、LocalDate

import java.sql.Date;
import java.time.Instant;
import java.time.LocalDate;

public class Main {

    public static void main(String[] args) {

        Date date = new Date(2019-1900, 6,18);
        Instant instant = date.toInstant();         // 转换为 Instant
        LocalDate localDate = date.toLocalDate();   // 转换为 LocalDate

    }

}

从字符串解析时间

import java.sql.Date;

public class Main {

    public static void main(String[] args) {

        Date date = Date.valueOf("2019-06-18");
        Date date2 = Date.valueOf("2019-6-18");
        System.out.println(date);
        System.out.println(date2);

    }

}

执行结果:

2019-06-18
2019-06-18

java.util.Calendar

查看 Calender 实例内容

import java.util.Calendar;

public class Main {

    public static void main(String[] args) {

        Calendar calendar = Calendar.getInstance();
        System.out.println(calendar);

    }

}

运行结果示例:

java.util.GregorianCalendar[time=1561343283169,areFieldsSet=true,areAllFieldsSet=true,lenient=true,zone=sun.util.calendar.ZoneInfo[id="Asia/Shanghai",offset=28800000,dstSavings=0,useDaylight=false,transitions=19,lastRule=null],firstDayOfWeek=1,minimalDaysInFirstWeek=1,ERA=1,YEAR=2019,MONTH=5,WEEK_OF_YEAR=26,WEEK_OF_MONTH=5,DAY_OF_MONTH=24,DAY_OF_YEAR=175,DAY_OF_WEEK=2,DAY_OF_WEEK_IN_MONTH=4,AM_PM=0,HOUR=10,HOUR_OF_DAY=10,MINUTE=28,SECOND=3,MILLISECOND=169,ZONE_OFFSET=28800000,DST_OFFSET=0]

MONTH 是从 0 开始算的,所以实际使用中要加1。周日是一周的第一天。

从 Calendar 中获取年月日时分秒

import java.util.Calendar;

public class Main {

    public static void main(String[] args) {

        Calendar calendar = Calendar.getInstance();

        System.out.printf("%s-%s-%s %s:%s:%s \n",
                calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH) + 1, calendar.get(Calendar.DAY_OF_MONTH),
                calendar.get(Calendar.HOUR_OF_DAY), calendar.get(Calendar.MINUTE), calendar.get(Calendar.SECOND)
        );

    }

}

运行结果示例:

2019-6-24 10:34:31 

Calendar 转换为时间戳

import java.util.Calendar;

public class Main {

    public static void main(String[] args) {

        Calendar calendar = Calendar.getInstance();
        calendar.set(2019, 6, 18, 18, 0, 0);

        // 转换为秒级时间戳
        System.out.println( calendar.toInstant().getEpochSecond() );

        // 转换为毫秒级时间戳
        System.out.println( calendar.getTimeInMillis() );

    }

}

运行结果:

1563444000
1563444000591

时间戳转换为 Calender

import java.util.Calendar;

public class Main {

    public static void main(String[] args) {

        Calendar calendar = Calendar.getInstance();

        calendar.setTimeInMillis(1563444000L*1000L);

        System.out.printf("%s-%s-%s %s:%s:%s \n",
                calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH) + 1, calendar.get(Calendar.DAY_OF_MONTH),
                calendar.get(Calendar.HOUR_OF_DAY), calendar.get(Calendar.MINUTE), calendar.get(Calendar.SECOND)
        );
        
    }

}

Calender 转换为 Date

import java.util.Calendar;
import java.util.Date;

public class Main {

    public static void main(String[] args) {

        Calendar calendar = Calendar.getInstance();

        Date date = calendar.getTime();

        System.out.println( date );

    }

}

运行结果示例:

Mon Jun 24 18:49:57 CST 2019

Date 转换为 Calender

import java.util.Calendar;
import java.util.Date;

public class Main {

    public static void main(String[] args) {

        Date date = new Date();
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);

        System.out.printf("%s-%s-%s %s:%s:%s \n",
                calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH)+1, calendar.get(Calendar.DAY_OF_MONTH),
                calendar.get(Calendar.HOUR_OF_DAY), calendar.get(Calendar.MINUTE), calendar.get(Calendar.SECOND)
        );

    }

}


( 本文完 )