Java基础:日期与时间

文章目录

  • 日期与时间
  • 新纪元时间(Epoch Time)
  • Java时间API
    • 老版本API
    • Java8中的新版本API
      • 时刻(Instant)
      • 创建一个时间对象
      • Duration和Period
      • 新版时间格式化(DateTimeFormatter)
      • 带时区的时间
      • 在数据库中存储日期和时间
  • ISO 8601
  • API文档

日期与时间

  • 日期
    如2020-06-17
  • 时间(可包含日期)
    如 12:10:10或2020-06-17 12:10:10

新纪元时间(Epoch Time)

epoch time 表示一个特定时间:1970-01-01 00:00:00 UTC,从这一时刻开始计算所经过的秒数称为UNIX时间戳(Unix timestamp)。在Java中可使用System.currentTimeMillis()获取时间戳。

Java时间API

老版本API

老版本时间API位于java.util包中。

  • Date 表示一个日期和时间对象。可以获取当前时间及对应的年月日时分秒等。
  • Calendar 可获取和设置年月日时分秒,比Date多了时间运算。
  • TimeZone 提供时区转换功能
    更多信息参考:廖雪峰-Date和Calendar

时间格式化

Date date = new Date();
var sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
System.out.println(sdf.format(date));

更多格式化格式见:JDK文档: Class SimpleDateFormat

Java8中的新版本API

新的时间API位于java.time包中,主要API包含:

类别 API
本地日期时间 LocalDateTime ,LocalDate,LocalTime
时刻 Instant
时间间隔 Duration
包含时区的时间 ZonedDateTime
时区 ZoneId,ZoneOffset

时刻(Instant)

获取某一时刻时间戳

// 秒
instant.getEpochSecond()
// 毫秒
instant.toEpochMilli()

将时间戳转为特定时区时间

Instant ins = Instant.ofEpochSecond(1592385860);
System.out.println(ins);    // UTC 时间
ZonedDateTime zonedDateTime = ins.atZone(ZoneId.systemDefault());
ZonedDateTime zonedDateTime2 = ins.atZone(ZoneId.of("America/New_York"));

创建一个时间对象

LocalDateTime ldt = LocalDateTime.now();
LocalDateTime ldt2 = LocalDateTime.of(2020, 6, 17, 12, 12, 12);

上述两个时间对象都将输出标准的ISO 8601的格式

Duration和Period

Duration表示两个时刻之间的时间间隔,Period表示两个日期之间的天数

LocalDateTime ldt = LocalDateTime.now();
LocalDateTime ldt2 = LocalDateTime.of(2020, 6, 17, 12, 12, 12);
Duration duration = Duration.between(ldt2, ldt);
System.out.println(duration);
Period period = Period.between(LocalDate.now().minusDays(1), LocalDate.now());
System.out.println(period);

输出内容类似:PT4H34M1.412SP1D
输出格式:以P...T...的形式表示,P...T之间表示日期间隔,T后面表示时间间隔。
所以上述输出分别表示时间间隔为4小时34分钟1.412秒以及日期间隔为1天。

新版时间格式化(DateTimeFormatter)

DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
System.out.println(dtf.format(LocalDateTime.now()));

新版API还提供了更强大的日期计算方法,参见廖雪峰-LocalDateTime

带时区的时间

ZonedDateTime beijingTime = ZonedDateTime.now(); // 默认时区
ZonedDateTime newYorkTime = ZonedDateTime.now(ZoneId.of("America/New_York")); // 指定时区
// or create by asZone
ZonedDateTime beijingTime2 = ldt.atZone(ZoneId.systemDefault());
ZonedDateTime newYorkTime2 = ldt.atZone(ZoneId.of("America/New_York"));

输出如下

2020-06-17T16:55:47.874+08:00[Asia/Shanghai]
2020-06-17T04:55:47.876-04:00[America/New_York]

也可使用withZoneSameInstant()将时区转换为纽约时间:

ZonedDateTime newYorkTime3 = beijingTime.withZoneSameInstant(ZoneId.of("America/New_York"));

在数据库中存储日期和时间

我们可以在数据库中保存unix时间戳,然后根据用户选择的时区显示本地时间。

public static void main(String[] args) {
    long unixTimestamp = 1592386268000L;
    String bj = timestampToString(unixTimestamp, Locale.CHINA, "Asia/Shanghai");
    String ny = timestampToString(unixTimestamp, Locale.US, "America/New_York");
    System.out.println(bj);
    System.out.println(ny);
}
static String timestampToString(long epochMilli, Locale locale, String zoneId) {
    Instant ins = Instant.ofEpochMilli(epochMilli);
	// DateTimeFormatter dtf = DateTimeFormatter.ISO_DATE_TIME;
    DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
    return dtf.withLocale(locale).format(ZonedDateTime.ofInstant(ins, ZoneId.of(zoneId)));
}

输出如下

2020-06-17 17:31:08
2020-06-17 05:31:08

ISO 8601

ISO 8601规定的日期和时间分隔符是T

  • 日期:yyyy-MM-dd
  • 时间:HH:mm:ss
  • 带毫秒的时间:HH:mm:ss.SSS
  • 日期和时间:yyyy-MM-dd’T’HH:mm:ss
  • 带毫秒的日期和时间:yyyy-MM-dd’T’HH:mm:ss.SSS

API文档

中文
English

你可能感兴趣的:(Java,java,时间,日期)