17.日期时间

日期和时间

Epoch Time是计算从1970年1月1日零点(格林威治时区/GMT+00:00)到现在所经历的秒数,又称为时间戳,在Java程序中,时间戳通常是用long表示的毫秒数
Java标准库有两套处理日期和时间的API:

  • 一套定义在java.util这个包里面,主要包括Date、Calendar和TimeZone这几个类;
  • 一套新的API是在Java 8引入的,定义在java.time这个包里面,主要包括LocalDateTime、ZonedDateTime、ZoneId等。

旧API

Date

java.util.Date是用于表示一个日期和时间的对象,与java.sql.Date不同,后者用在数据库中。
Date的基本用法:

import java.util.*
public class Main {
    public static void main(String[] args) {
        // 获取当前时间:
        Date date = new Date();
        System.out.println(date.getYear() + 1900); // 必须加上1900
        System.out.println(date.getMonth() + 1); // 0~11,必须加上1
        System.out.println(date.getDate()); // 1~31,不能加1
        // 转换为String:
        System.out.println(date.toString());
        // 转换为GMT时区:
        System.out.println(date.toGMTString());
        // 转换为本地时区:
        System.out.println(date.toLocaleString());
    }
}

想要针对用户的偏好精确地控制日期和时间的格式,可以使用SimpleDateFormat对一个Date进行转换。

public class Main {
    public static void main(String[] args) {
        // 获取当前时间:
        Date date = new Date();
        var sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        System.out.println(sdf.format(date));
    }
}

Calendar

Calendar可以用于获取并设置年、月、日、时、分、秒,它和Date比,主要多了一个可以做简单的日期和时间运算的功能
Calendar获取年月日这些信息变成了get(int field),返回的年份不必转换,返回的月份仍然要加1,返回的星期要特别注意,1~7分别表示周日,周一,……,周六。
Calendar只有一种方式获取,即Calendar.getInstance(),而且一获取到就是当前时间。
利用Calendar.getTime()可以将一个Calendar对象转换成Date对象,然后可以用SimpleDateFormat进行格式化
Calendar的运算功能

import java.text.*;
import java.util.*;
public class Main {
    public static void main(String[] args) {
        // 当前时间:
        Calendar c = Calendar.getInstance();
        // 清除所有:
        c.clear();
        // 设置年月日时分秒:
        c.set(2019, 10 /* 11月 */, 20, 8, 15, 0);
        // 加5天并减去2小时:
        c.add(Calendar.DAY_OF_MONTH, 5);
        c.add(Calendar.HOUR_OF_DAY, -2);
        // 显示时间:
        var sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date d = c.getTime();
        System.out.println(sdf.format(d));
        // 2019-11-25 6:15:00
    }
}

新API

LocalDateTime、ZonedDateTime、ZoneId等位于java.time包,主要涉及的类型有:

  • 本地日期和时间:LocalDateTime,LocalDate,LocalTime;
  • 带时区的日期和时间:ZonedDateTime;
  • 时刻:Instant;
  • 时区:ZoneId,ZoneOffset;
  • 时间间隔:Duration。
  • 用于取代SimpleDateFormat的格式化类型DateTimeFormatter

LocalDateTime

LocalDateTime表示一个本地日期和时间

LocalDateTime dt = LocalDateTime.now(); // 当前日期和时间
LocalDate d = dt.toLocalDate(); // 转换到当前日期
LocalTime t = dt.toLocalTime(); // 转换到当前时间

// 指定日期和时间:
LocalDate d2 = LocalDate.of(2019, 11, 30); // 2019-11-30
LocalTime t2 = LocalTime.of(15, 16, 17); // 15:16:17
LocalDateTime dt2 = LocalDateTime.of(2019, 11, 30, 15, 16, 17);
LocalDateTime dt3 = LocalDateTime.of(d2, t2);

//将字符串转换为LocalDateTime就可以传入标准格式:
LocalDateTime dt = LocalDateTime.parse("2019-11-19T15:16:17");
LocalDate d = LocalDate.parse("2019-11-19");
LocalTime t = LocalTime.parse("15:16:17");

LocalDateTime提供了对日期和时间进行加减的非常简单的链式调用
对日期和时间进行直接调整,可使用withXxx()方法,例如:withHour(15)会把10:11:12变为15:11:12,还有一个通用的with()方法允许更复杂的运算
要判断两个LocalDateTime的先后,可以使用isBefore()、isAfter()方法
LocalDateTime无法与时间戳进行转换,因为LocalDateTime没有时区,无法确定某一时刻。要转为ZonedDateTime才可以与long表示的时间戳进行转换

Duration & Period

Duration表示两个时刻之间的时间间隔,Period表示两个日期之间的天数
两个LocalDateTime之间的差值使用Duration表示,类似PT1235H10M30S,表示1235小时10分钟30秒。
两个LocalDate之间的差值用Period表示,类似P1M21D,表示1个月21天
利用ofXxx()或者parse()方法可以直接创建Duration

Duration d1 = Duration.ofHours(10); // 10 hours
Duration d2 = Duration.parse("P1DT2H3M"); // 1 day, 2 hours, 3 minutes

DateTimeFormatter

要自定义输出的格式,或者要把一个非ISO 8601格式的字符串解析成LocalDateTime,可以使用新的DateTimeFormatter

public class Main {
    public static void main(String[] args) {
        // 自定义格式化:
        DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss");
        System.out.println(dtf.format(LocalDateTime.now()));

        // 用自定义格式解析:
        LocalDateTime dt2 = LocalDateTime.parse("2019/11/30 15:16:17", dtf);
        System.out.println(dt2);
    }
}

DateTimeFormatter是不变对象,还是线程安全的

Instant

在java.time中以Instant类型表示时间戳,用Instant.now()获取当前时间戳,可以和ZonedDateTime以及long互相转换

实践

处理日期和时间时,尽量使用新的java.time包;
在数据库中存储时间戳时,尽量使用long型时间戳,它具有省空间,效率高,不依赖数据库的优点。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值