Java8:新的时间和日期类库

Java8的日期和时间类包含LocalDate、LocalTime、Instant、Duration、Period,这些类都包含在java.time包中。

关于Java8日期的应用,有篇好blog:Java 函数式编程(五):Java 8 的日期和时间 API

一、 日期操作与格式化

1. LocalDate和LocalTime

LocalDate 表示一个具体的日期,格式为:2020-04-24。

LocalDate localDate = LocalDate.of(2020, 4, 24);     // 初始化一个日期:2020-04-24
int year = localDate.getYear();                     // 年份:2020
Month month = localDate.getMonth();                 // 月份:APRIL
int dayOfMonth = localDate.getDayOfMonth();         // 月份中的第几天:24
DayOfWeek dayOfWeek = localDate.getDayOfWeek();     // 一周的第几天:FRIDAY
int length = localDate.lengthOfMonth();             // 月份的天数:30
boolean leapYear = localDate.isLeapYear();          // 是否为闰年:false

LocalDate today = LocalDate.now();          //从系统时钟获取当前日期
LocalDate date = LocalDate.parse("2020-04-24");

LocalTime 表示具体的时间(24小时制),格式为:11:12:38.267039

LocalTime localTime = LocalTime.of(11, 12, 38);     // 初始化一个时间:11:12:38
int hour = localTime.getHour();                     // 时:11
int minute = localTime.getMinute();                 // 分:12
int second = localTime.getSecond();                 // 秒:38
LocalTime time = LocalTime.parse("11:12:38");

LocalDateTime 为LocalDate和LocalTime的结合体,格式为:2020-04-24T11:25:51

LocalDateTime ldt1 = LocalDateTime.of(2020, 4, 24, 11, 25, 51);

LocalDate localDate = LocalDate.of(2020, 4, 24);
LocalTime localTime = LocalTime.of(11, 25, 51);
LocalDateTime ldt2 = localDate.atTime(localTime);

LocalDate date = ldt1.toLocalDate();
LocalTime time = ldt1.toLocalTime();

2. Instant

Instant表示一个时间戳,可以精确到纳秒,seconds表示从1970-01-01 00:00:00开始到现在的秒数,nanos表示纳秒部分(nanos的值不会超过999,999,999),1秒=100万纳秒。

Instant instant = Instant.ofEpochSecond(220, 100000);
Instant nowInstant = Instant.now();

3. Duration

Duration的内部实现与Instant类似,也是包含两部分:seconds表示秒,nanos表示纳秒。两者的区别是Instant用于表示一个时间戳(或者说是一个时间点),而Duration表示一个时间段,所以Duration类中不包含now()静态方法。可以通过Duration.between()方法创建Duration对象:

LocalDateTime from = LocalDateTime.of(2020, 2, 1, 0, 0, 0);    // 2020-02-01 00:00:00
LocalDateTime to = LocalDateTime.of(2020, 5, 1, 0, 0, 0);     // 2020-05-01 00:00:00

//必须以两个时间点之间,用LocalDate会抛异常
Duration duration = Duration.between(from, to);     // 表示从 2020-02-01 00:00:00 到 2020-05-01 00:00:00 这段时间
long days = duration.toDays();              // 这段时间的总天数
long hours = duration.toHours();            // 这段时间的小时数
long minutes = duration.toMinutes();        // 这段时间的分钟数
long seconds = duration.getSeconds();       // 这段时间的秒数
long milliSeconds = duration.toMillis();    // 这段时间的毫秒数
long nanoSeconds = duration.toNanos();      // 这段时间的纳秒

//Duration对象还可以通过of()方法创建,该方法接受一个时间段长度,和一个时间单位作为参数:
Duration duration1 = Duration.of(5, ChronoUnit.DAYS);       // 5天
Duration duration2 = Duration.of(1000, ChronoUnit.MILLIS);  // 1000毫秒
Duration的通用方法.png

4. Period

Period与Duration类似,不过Period是以年月日来衡量的时间段,比如10年3个月6天。

Period period = new Period(10, 3, 6);

Period periodBetween = Period.between(LocalDate.of(2020, 2, 1), LocalDate.of(2020, 5, 1));

5. LocalDate、LocalTime、LocalDateTime、Instant的通用方法:[图片上传中...(3.png-284944-1587715244373-0)]

表示时间点的通用方法.png

二、日期操作与格式化

1. 增加和减少日期

为保证线程安全,Java8中的日期/时间类都是不可变的。新的日期/时间类也提供了方法用于创建对象的可变版本,如增加一天或者减少一天。

简单操作:

LocalDate date = LocalDate.of(2020, 4, 24);          // 2020-04-24
LocalDate date1 = date.withYear(2019);              // 修改为 2019-04-24
LocalDate date2 = date.withMonth(2);                // 修改为 2020-02-24
LocalDate date3 = date.withDayOfMonth(1);           // 修改为 2020-04-01
LocalDate date4 = date.plusYears(1);                // 增加一年 2021-04-24
LocalDate date5 = date.minusMonths(2);              // 减少两个月 2020-02-24
LocalDate date6 = date.plus(5, ChronoUnit.DAYS);    // 增加5天 2020-02-29

复杂操作:

//静态导入TemporalAdjusters对象:
import static java.time.temporal.TemporalAdjusters.*;

LocalDate date1 = date.with(nextOrSame(DayOfWeek.SUNDAY));      // 返回下一个距离当前时间最近的星期日
LocalDate date2 = date.with(lastInMonth(DayOfWeek.SATURDAY));   // 返回本月最后一个星期六
TemporalAdjuster类中的工厂方法.png

TemporalAdjuster是一个函数式接口,可以使用Lambda表达式自定义处理流程。

@FunctionalInterface
public interface TemporalAdjuster {
    Temporal adjustInto(Temporal temporal);
}

2. 格式化日期

Java8的日期类有一个format()方法,用于将日期格式转化为字符串。该方法接受一个DateTimeFormatter类型参数:

LocalDateTime dateTime = LocalDateTime.now();
String strDate1 = dateTime.format(DateTimeFormatter.BASIC_ISO_DATE);    // 20200424
String strDate2 = dateTime.format(DateTimeFormatter.ISO_LOCAL_DATE);    // 2020-04-24
String strDate3 = dateTime.format(DateTimeFormatter.ISO_LOCAL_TIME);    // 15:22:14.101066
String strDate4 = dateTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));   // 2020-04-24
String strDate5 = dateTime.format(DateTimeFormatter.ofPattern("今天是:YYYY年 MMMM DD日 E", Locale.CHINESE)); // 今天是:2020年 四月 115日 周五

日期类也支持将字符串解析为一个日期对象,例如:

String strDate1 = "2020-04-24";
String strDate2 = "2017-04-24 15:25:05";
LocalDate date = LocalDate.parse(strDate1, DateTimeFormatter.ofPattern("yyyy-MM-dd"));
LocalDateTime dateTime = LocalDateTime.parse(strDate2, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));

3. 时区

Java8新时区类java.time.ZoneId。ZoneId对象可以通过ZoneId.of()方法创建,也可以通过ZoneId.systemDefault()获取系统默认时区。

ZoneId shanghaiZoneId = ZoneId.of("Asia/Shanghai");
ZoneId systemZoneId = ZoneId.systemDefault();

of()方法接收一个“区域/城市”的字符串作为参数,你可以通过getAvailableZoneIds()方法获取所有合法的“区域/城市”字符串:

Set<String> zoneIds = ZoneId.getAvailableZoneIds();

有了ZoneId,我们就可以将一个LocalDate、LocalTime或LocalDateTime对象转化为ZonedDateTime对象:

LocalDateTime localDateTime = LocalDateTime.now();
ZonedDateTime zonedDateTime = ZonedDateTime.of(localDateTime, shanghaiZoneId);

打印zonedDateTime为(注意没有“Asia/Beijing”):

2020-04-24T15:46:30.947148+08:00[Asia/Shanghai]

ZonedDateTime对象由两部分构成,LocalDateTime和ZoneId,其中2020-04-24T15:46:30.947148部分为LocalDateTime,+08:00[Asia/Shanghai]部分为ZoneId。

另一种表示时区的方式是使用ZoneOffset,它是以当前时间和世界标准时间(UTC)/格林威治时间(GMT)的偏差来计算,例如:

ZoneOffset zoneOffset = ZoneOffset.of("+09:00");
LocalDateTime localDateTime = LocalDateTime.now();
OffsetDateTime offsetDateTime = OffsetDateTime.of(localDateTime, zoneOffset);
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,125评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,293评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,054评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,077评论 1 291
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,096评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,062评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,988评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,817评论 0 273
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,266评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,486评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,646评论 1 347
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,375评论 5 342
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,974评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,621评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,796评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,642评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,538评论 2 352

推荐阅读更多精彩内容