深入了解Java 8日期和时间API

在这篇文章中,我们将更深入地了解通过Java 8获得的新的Date / Time API(
JSR 310 )。 请注意,本文主要由显示新API功能的代码示例驱动。 我认为这些示例是不言自明的,因此我没有花太多时间在它们周围写文本:-)

让我们开始吧!

处理日期和时间对象

Java 8 Date / Time API的所有类都位于java.time包内。 我们要看的第一类是java.time.LocalDate。 LocalDate表示没有时间的年月日日期。 我们从创建新的LocalDate实例开始:

// the current date
LocalDate currentDate = LocalDate.now();// 2014-02-10
LocalDate tenthFeb2014 = LocalDate.of(2014, Month.FEBRUARY, 10);// months values start at 1 (2014-08-01)
LocalDate firstAug2014 = LocalDate.of(2014, 8, 1);// the 65th day of 2010 (2010-03-06)
LocalDate sixtyFifthDayOf2010 = LocalDate.ofYearDay(2010, 65);

LocalTime和LocalDateTime是我们要研究的下一个类。 两者的工作方式都与LocalDate类似。 LocalTime可用于时间(无日期),而LocalDateTime可将日期和时间组合在一个类中:

LocalTime currentTime = LocalTime.now(); // current time
LocalTime midday = LocalTime.of(12, 0); // 12:00
LocalTime afterMidday = LocalTime.of(13, 30, 15); // 13:30:15// 12345th second of day (03:25:45)
LocalTime fromSecondsOfDay = LocalTime.ofSecondOfDay(12345);// dates with times, e.g. 2014-02-18 19:08:37.950
LocalDateTime currentDateTime = LocalDateTime.now();// 2014-10-02 12:30
LocalDateTime secondAug2014 = LocalDateTime.of(2014, 10, 2, 12, 30);// 2014-12-24 12:00
LocalDateTime christmas2014 = LocalDateTime.of(2014, Month.DECEMBER, 24, 12, 0);

默认情况下,LocalDate / Time类将使用默认时区中的系统时钟。 我们可以通过提供时区或其他Clock实现来更改此设置:

// current (local) time in Los Angeles
LocalTime currentTimeInLosAngeles = LocalTime.now(ZoneId.of("America/Los_Angeles"));// current time in UTC time zone
LocalTime nowInUtc = LocalTime.now(Clock.systemUTC());

从LocalDate / Time对象,我们可以获得我们可能需要的各种有用信息。 一些例子:

LocalDate date = LocalDate.of(2014, 2, 15); // 2014-02-15boolean isBefore = LocalDate.now().isBefore(date); // false// information about the month
Month february = date.getMonth(); // FEBRUARY
int februaryIntValue = february.getValue(); // 2
int minLength = february.minLength(); // 28
int maxLength = february.maxLength(); // 29
Month firstMonthOfQuarter = february.firstMonthOfQuarter(); // JANUARY// information about the year
int year = date.getYear(); // 2014
int dayOfYear = date.getDayOfYear(); // 46
int lengthOfYear = date.lengthOfYear(); // 365
boolean isLeapYear = date.isLeapYear(); // falseDayOfWeek dayOfWeek = date.getDayOfWeek();
int dayOfWeekIntValue = dayOfWeek.getValue(); // 6
String dayOfWeekName = dayOfWeek.name(); // SATURDAYint dayOfMonth = date.getDayOfMonth(); // 15
LocalDateTime startOfDay = date.atStartOfDay(); // 2014-02-15 00:00// time information
LocalTime time = LocalTime.of(15, 30); // 15:30:00
int hour = time.getHour(); // 15
int second = time.getSecond(); // 0
int minute = time.getMinute(); // 30
int secondOfDay = time.toSecondOfDay(); // 55800

无需提供特定日期即可获得某些信息。 例如,如果我们需要有关特定年份的信息,则可以使用Year类:

Year currentYear = Year.now();
Year twoThousand = Year.of(2000);
boolean isLeap = currentYear.isLeap(); // false
int length = currentYear.length(); // 365// sixtyFourth day of 2014 (2014-03-05)
LocalDate date = Year.of(2014).atDay(64);

我们可以使用加号和减号方法来添加或减去特定的时间量。 请注意,这些方法总是返回一个新实例(Java 8日期/时间类是不可变的)。

LocalDate tomorrow = LocalDate.now().plusDays(1);// before 5 houres and 30 minutes
LocalDateTime dateTime = LocalDateTime.now().minusHours(5).minusMinutes(30);

TemporalAdjusters是日期处理的另一种不错的方法。 TemporalAdjuster是一个单一方法接口,用于将调整过程与实际日期/时间对象分开。 可以使用TemporalAdjusters类的静态方法访问一组常见的TemporalAdjusters 。

LocalDate date = LocalDate.of(2014, Month.FEBRUARY, 25); // 2014-02-25// first day of february 2014 (2014-02-01)
LocalDate firstDayOfMonth = date.with(TemporalAdjusters.firstDayOfMonth());// last day of february 2014 (2014-02-28)
LocalDate lastDayOfMonth = date.with(TemporalAdjusters.lastDayOfMonth());

静态导入使它更通俗易懂:

import static java.time.temporal.TemporalAdjusters.*;...// last day of 2014 (2014-12-31)
LocalDate lastDayOfYear = date.with(lastDayOfYear());// first day of next month (2014-03-01)
LocalDate firstDayOfNextMonth = date.with(firstDayOfNextMonth());// next sunday (2014-03-02)
LocalDate nextSunday = date.with(next(DayOfWeek.SUNDAY));

时区

使用时区是新API简化的另一个重要主题。 到目前为止,我们已经看到的LocalDate / Time类不包含有关时区的信息。 如果我们要使用某个时区中的日期/时间,可以使用ZonedDateTime或OffsetDateTime :

ZoneId losAngeles = ZoneId.of("America/Los_Angeles");
ZoneId berlin = ZoneId.of("Europe/Berlin");// 2014-02-20 12:00
LocalDateTime dateTime = LocalDateTime.of(2014, 02, 20, 12, 0);// 2014-02-20 12:00, Europe/Berlin (+01:00)
ZonedDateTime berlinDateTime = ZonedDateTime.of(dateTime, berlin);// 2014-02-20 03:00, America/Los_Angeles (-08:00)
ZonedDateTime losAngelesDateTime = berlinDateTime.withZoneSameInstant(losAngeles);int offsetInSeconds = losAngelesDateTime.getOffset().getTotalSeconds(); // -28800// a collection of all available zones
Set<String> allZoneIds = ZoneId.getAvailableZoneIds();// using offsets
LocalDateTime date = LocalDateTime.of(2013, Month.JULY, 20, 3, 30);
ZoneOffset offset = ZoneOffset.of("+05:00");// 2013-07-20 03:30 +05:00
OffsetDateTime plusFive = OffsetDateTime.of(date, offset);// 2013-07-19 20:30 -02:00
OffsetDateTime minusTwo = plusFive.withOffsetSameInstant(ZoneOffset.ofHours(-2));

时间戳记

诸如LocalDate和ZonedDateTime之类的类提供了对时间的直观了解。 但是,通常我们需要从机器角度来看待时间。 为此,我们可以使用表示时间戳的Instant类。 即时计数是从1970年1月1日(1970-01-01 00:00:00)的第一秒开始的时间,也称为EPOCH 。 如果即时值出现在纪元之前,则它们可以为负。 它们遵循ISO 8601表示日期和时间的标准。

// current time
Instant now = Instant.now();// from unix timestamp, 2010-01-01 12:00:00
Instant fromUnixTimestamp = Instant.ofEpochSecond(1262347200);// same time in millis
Instant fromEpochMilli = Instant.ofEpochMilli(1262347200000l);// parsing from ISO 8601
Instant fromIso8601 = Instant.parse("2010-01-01T12:00:00Z");// toString() returns ISO 8601 format, e.g. 2014-02-15T01:02:03Z
String toIso8601 = now.toString();// as unix timestamp
long toUnixTimestamp = now.getEpochSecond();// in millis
long toEpochMillis = now.toEpochMilli();// plus/minus methods are available too
Instant nowPlusTenSeconds = now.plusSeconds(10);

期限和期限

期间和持续时间是另外两个重要的类别。 就像名称所暗示的那样,它们代表时间或数量。 期间使用基于日期的值(年,月,日),而期间使用秒或纳秒来定义时间量。 持续时间最适合使用Instants和机器时间。 如果终点发生在起点之前,则“期间”和“持续时间”可以包含负值。

// periodsLocalDate firstDate = LocalDate.of(2010, 5, 17); // 2010-05-17
LocalDate secondDate = LocalDate.of(2015, 3, 7); // 2015-03-07
Period period = Period.between(firstDate, secondDate);int days = period.getDays(); // 18
int months = period.getMonths(); // 9
int years = period.getYears(); // 4
boolean isNegative = period.isNegative(); // falsePeriod twoMonthsAndFiveDays = Period.ofMonths(2).plusDays(5);
LocalDate sixthOfJanuary = LocalDate.of(2014, 1, 6);// add two months and five days to 2014-01-06, result is 2014-03-11
LocalDate eleventhOfMarch = sixthOfJanuary.plus(twoMonthsAndFiveDays);// durationsInstant firstInstant= Instant.ofEpochSecond( 1294881180 ); // 2011-01-13 01:13
Instant secondInstant = Instant.ofEpochSecond(1294708260); // 2011-01-11 01:11Duration between = Duration.between(firstInstant, secondInstant);// negative because firstInstant is after secondInstant (-172920)
long seconds = between.getSeconds();// get absolute result in minutes (2882)
long absoluteResult = between.abs().toMinutes();// two hours in seconds (7200)
long twoHoursInSeconds = Duration.ofHours(2).getSeconds();

格式化和解析

格式化和解析是处理日期和时间时的另一个大话题。 在Java 8中,这可以通过使用format()和parse()方法来实现:

// 2014-04-01 10:45
LocalDateTime dateTime = LocalDateTime.of(2014, Month.APRIL, 1, 10, 45);// format as basic ISO date format (20140220)
String asBasicIsoDate = dateTime.format(DateTimeFormatter.BASIC_ISO_DATE);// format as ISO week date (2014-W08-4)
String asIsoWeekDate = dateTime.format(DateTimeFormatter.ISO_WEEK_DATE);// format ISO date time (2014-02-20T20:04:05.867)
String asIsoDateTime = dateTime.format(DateTimeFormatter.ISO_DATE_TIME);// using a custom pattern (01/04/2014)
String asCustomPattern = dateTime.format(DateTimeFormatter.ofPattern("dd/MM/yyyy"));// french date formatting (1. avril 2014)
String frenchDate = dateTime.format(DateTimeFormatter.ofPattern("d. MMMM yyyy", new Locale("fr")));// using short german date/time formatting (01.04.14 10:45)
DateTimeFormatter formatter = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.SHORT).withLocale(new Locale("de"));
String germanDateTime = dateTime.format(formatter);// parsing date strings
LocalDate fromIsoDate = LocalDate.parse("2014-01-20");
LocalDate fromIsoWeekDate = LocalDate.parse("2014-W14-2", DateTimeFormatter.ISO_WEEK_DATE);
LocalDate fromCustomPattern = LocalDate.parse("20.01.2014", DateTimeFormatter.ofPattern("dd.MM.yyyy"));

转换次数

当然,我们并不总是拥有所需类型的对象。 因此,我们需要一个选项来在彼此之间转换不同的日期/时间相关对象。 以下示例显示了一些可能的转换选项:

// LocalDate/LocalTime <-> LocalDateTime
LocalDate date = LocalDate.now();
LocalTime time = LocalTime.now();
LocalDateTime dateTimeFromDateAndTime = LocalDateTime.of(date, time);
LocalDate dateFromDateTime = LocalDateTime.now().toLocalDate();
LocalTime timeFromDateTime = LocalDateTime.now().toLocalTime();// Instant <-> LocalDateTime
Instant instant = Instant.now();
LocalDateTime dateTimeFromInstant = LocalDateTime.ofInstant(instant, ZoneId.of("America/Los_Angeles"));
Instant instantFromDateTime = LocalDateTime.now().toInstant(ZoneOffset.ofHours(-2));// convert old date/calendar/timezone classes
Instant instantFromDate = new Date().toInstant();
Instant instantFromCalendar = Calendar.getInstance().toInstant();
ZoneId zoneId = TimeZone.getDefault().toZoneId();
ZonedDateTime zonedDateTimeFromGregorianCalendar = new GregorianCalendar().toZonedDateTime();// convert to old classes
Date dateFromInstant = Date.from(Instant.now());
TimeZone timeZone = TimeZone.getTimeZone(ZoneId.of("America/Los_Angeles"));
GregorianCalendar gregorianCalendar = GregorianCalendar.from(ZonedDateTime.now());

结论

使用Java 8,我们可以在java.time包中获得一个非常丰富的API,用于处理日期和时间。 该API可以用更新,更灵活的类完全替换旧的类,如java.util.Date或java.util.Calendar。 由于大多数类都是不可变的,因此新的API有助于构建线程安全的系统。

  • 示例的源代码可以在GitHub上找到 。

参考:在mscharhag,Programming and Stuff博客上,我们的JCG合作伙伴 Michael Scharhag 对Java 8 Date and Time API进行了更深入的研究 。

翻译自: https://www.javacodegeeks.com/2014/03/a-deeper-look-into-the-java-8-date-and-time-api.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/364721.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

P4047 部落划分

这题太水了吧&#xff0c;不知道怎么蓝的&#xff0c;蒟蒻只写了十五分钟就一次AC了…… 但是挺有意思&#xff0c;就发篇题解吧qwq emmm……最小生成树&#xff08;贪心&#xff09;&#xff0c;就没别的了…… 要明确&#xff1a; 一开始可以把每个点都看成一个部落&#xff…

如何用纯 CSS 创作一个文本淡入淡出的 loader 动画

效果预览 在线演示 按下右侧的“点击预览”按钮可以在当前页面预览&#xff0c;点击链接可以全屏预览。https://codepen.io/comehope/pen/ERwpeG可交互视频此视频是可以交互的&#xff0c;你可以随时暂停视频&#xff0c;编辑视频中的代码。请用 chrome, safari, edge 打开观…

java csf_WebService CSF使用详解 | 学步园

一建立service:1)CxfService&#xff1a;WebServicepublicinterfaceCxfService {WebMethodpublicWebResultList getTasksByActor(WebParam(name"actor") String actor);WebMethodpublicvoidcreateAndStartProcessInstance(WebParam(name"processName") Str…

软件工程和项目管理的区别

软件工程的定义&#xff1a; 软件工程是研究和应用如何以系统性的、规范化的、可定量的过程化方法去开发和维护软件&#xff0c;以及如何把经过时间考验而证明正确的管理技术和当前能够得到的最好的技术方法结合起来。 项目管理的定义&#xff1a; 项目管理是一个管理学分支的学…

如何启动多个WebLogic托管服务器

WebLogic Server文档建议您创建专用的管理服务器&#xff0c;然后分离托管服务器以进行应用程序部署。 在这里&#xff0c;我将向您展示如何在与管理服务器相同的主机中创建一个或多个托管服务器。 我假设您已经安装了WLS&#xff0c;并已创建并正在运行自己的域。 如果您以前…

《机器学习基石》第一周 —— When Can Machine Learn?

&#xff08;注&#xff1a;由于之前进行了吴恩达机器学习课程的学习&#xff0c;其中有部分内容与机器学习基石的内容重叠&#xff0c;所以以下该系列的笔记只记录新的知识&#xff09; 《机器学习基石》课程围绕着下面这四个问题而展开&#xff1a; 主要内容&#xff1a; 一、…

如何用纯 CSS 创作一盘传统蚊香

效果预览 在线演示 按下右侧的“点击预览”按钮可以在当前页面预览&#xff0c;点击链接可以全屏预览。https://codepen.io/comehope/pen/BVpvMz可交互视频教程此视频是可以交互的&#xff0c;你可以随时暂停视频&#xff0c;编辑视频中的代码。请用 chrome, safari, edge 打…

LeetCode 905. 按奇偶排序数组

LeetCode 905. 按奇偶排序数组 转载于:https://www.cnblogs.com/hglibin/p/10794792.html

java父类序列化_父类的序列化与 Transient 关键字

情境&#xff1a;一个子类实现了 Serializable 接口&#xff0c;它的父类都没有实现 Serializable 接口&#xff0c;序列化该子类对象&#xff0c;然后反序列化后输出父类定义的某变量的数值&#xff0c;该变量数值与序列化时的数值不同。解决&#xff1a;要想将父类对象也序列…

Java:在Runnable中处理RuntimeException

去年年底&#xff0c;我正在运行预定的任务来监视Neo4j集群&#xff0c;而我遇到的问题之一是有时监视会退出。 我最终意识到这是因为RuntimeException被抛出到Runnable方法中&#xff0c;而我没有处理它。 以下代码演示了该问题&#xff1a; import java.util.ArrayList; im…

错误代码: 1231 - Variable 'sql_mode' can't be set to the value of 'NULL'

错误代码&#xff1a; 1231 - Variable sql_mode cant be set to the value of NULL 错误代码&#xff1a; 1231 - Variable sql_mode cant be set to the value of NULL 错误代码&#xff1a; 1231 - Variable sql_mode cant be set to the value of NULL mysql中的提示 删除注…

[Unity3D]Unity3D游戏开发之怪物AI

大家好。欢迎大家关注由我为大家带来的Unity3D游戏开发系列文章&#xff0c;我的博客地址为&#xff1a;http://blog.csdn.net/qinyuanpei。在上一篇文章中&#xff0c;我们基本上实现了一个小地图的功能&#xff0c;今天呢&#xff0c;我们来实现怪物AI&#xff0c;所谓怪物AI…

中国第一批写java的人_中国java开源界最可爱的人们

评论# re: 中国java开源界最可爱的人们2007-12-07 15:29sitinspring如果少一些抒情,多一点实质内容,文章更耐看. 回复 更多评论# re: 中国java开源界最可爱的人们[未登录]2007-12-07 15:49dennis竟然没有满江红&#xff0c;opendoc的意义不用多说了吧 回复 更多评论# re: 中…

如何把握好 transition 和 animation 的时序,创作描边按钮特效

效果预览 在线演示 按下右侧的“点击预览”按钮可以在当前页面预览&#xff0c;点击链接可以全屏预览。https://codepen.io/comehope/pen/mKdzZM可交互视频教程此视频是可以交互的&#xff0c;你可以随时暂停视频&#xff0c;编辑视频中的代码。请用 chrome, safari, edge 打…

使用PHREAK算法实现Drools 6性能

Drools 6引入了新的惰性匹配算法。 该算法的详细信息已在之前的两个博客中介绍&#xff1a; RIP RETE时间获得PHREAKY 基于PHREAK堆栈的评估和向后链接 第一篇文章讨论了性能以及为什么算法的批处理和惰性方面难以比较。 “性能的最后一点。 通常&#xff0c;使用PHREAK的单…

02Data

1.数据从何而来 2.数据对象和属性类型 数据集合的类型 结构数据的重要特征 数据对象 属性 属性类型 数据属性的类型 离散 vs.连续属性 3.数据的&#xff08;基本&#xff09;统计描述 分布度量 代数度量 整体度量 度量数据的中心趋势 对称/偏斜数据 4.数据可视化 5.数据的相似…

PAT 1131 Subway Map

题目链接&#xff1a; https://pintia.cn/problem-sets/994805342720868352/problems/994805347523346432 思路&#xff1a; 说多了都是泪&#xff0c; Dijstra超时&#xff0c;采用dfs 利用map<pair<int,int>,int>&#xff0c;表示两个点和他们中间的地铁线号 每次…

专访Vue作者尤雨溪:Vue CLI 3.0重构的原因

1、为什么要对 Vue CLI 进行大规模修改&#xff1f; 尤雨溪认为旧版本的 Vue CLI 本质上只是从 GitHub 拉取模版&#xff0c;这种拉模版的方式有几个问题&#xff1a; &#xff08;1&#xff09; 在单个模版里面同时支持太多选项会导致模版本身变得极其复杂和难以维护&#x…

java秒杀时间与服务器时间_Javascript实现秒杀倒计时(时间与服务器时间同步)...

现在有很多网站都在做秒杀商品&#xff0c;而这其中有一个很重要的环节就是倒计时。关于倒计时&#xff0c;有下面几点需要注意&#xff1a;1.应该使用服务器时间而不是本地时间(本地时间存在时区不同、用户自行设置等问题)。2.要考虑网络传输的耗时。3.获取时间时可直接从AJAX…

Java 8 Friday Goodies:本地交易范围

在Data Geekery &#xff0c;我们喜欢Java。 而且&#xff0c;由于我们真的很喜欢jOOQ的流畅的API和查询DSL &#xff0c;我们对Java 8将为我们的生态系统带来什么感到非常兴奋。 我们已经写了一些关于Java 8好东西的博客 &#xff0c;现在我们觉得是时候开始一个新的博客系列了…