在这篇文章中,我们将更深入地了解通过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

深入了解Java 8日期和时间API相关推荐

  1. 《Java 8 in Action》Chapter 12:新的日期和时间API

    在Java 1.0中,对日期和时间的支持只能依赖java.util.Date类.同时这个类还有两个很大的缺点:年份的起始选择是1900年,月份的起始从0开始. 在Java 1.1中,Date类中的很多 ...

  2. 【小家java】java8新特性之---全新的日期、时间API(JSR 310规范),附SpringMVC、Mybatis中使用JSR310的正确姿势

    [小家java]java5新特性(简述十大新特性) 重要一跃 [小家java]java6新特性(简述十大新特性) 鸡肋升级 [小家java]java7新特性(简述八大新特性) 不温不火 [小家java ...

  3. Java编程的逻辑 (95) - Java 8的日期和时间API

    ​本系列文章经补充和完善,已修订整理成书<Java编程的逻辑>,由机械工业出版社华章分社出版,于2018年1月上市热销,读者好评如潮!各大网店和书店有售,欢迎购买,京东自营链接:http: ...

  4. Java 8 日期和时间解读

    转载自 Java 8 日期和时间解读 现在,一些应用程序仍然在使用java.util.Date和java.util.Calendar API和它们的类库,来使我们在生活中更加轻松的处理日期和时间,比如 ...

  5. 《Java8实战》笔记(12):新的日期和时间API

    新的日期和时间API 相信大多数有经验的程序员都会赞同Java 8之前的库对日期和时间的支持就非常不理想.值得高兴的是 Java 8中引入全新的日期和时间API就是要解决这一问题. Java 8之前的 ...

  6. java 8 新特性 时间api使用实例

    2019独角兽企业重金招聘Python工程师标准>>> java 8 提供的 时间api java.time 比原来的Calendar 方便很多.主要提供了 日期类:LocalDat ...

  7. Java 8 - 日期和时间实用技巧

    Java 8 – 日期和时间实用技巧 当你开始使用Java操作日期和时间的时候,会有一些棘手.你也许会通过System.currentTimeMillis() 来返回1970年1月1日到今天的毫秒数. ...

  8. Java 8 日期、时间、时间矫正器操作

    Java 8 日期.时间操作 真放肆不在饮酒放荡,假矜持偏要慷慨激昂.万事留一线,江湖好相见–老郭经典语录 本篇描述LocalDate.LocalTime.LocalDateTime.Temporal ...

  9. java国际化——日期和时间+排序

    [0]README 1) 本文部分文字描述转自 core java volume 2 , 测试源代码均为原创, 旨在理解 java国际化--日期和时间+排序 的基础知识 : [1]日期和时间 1)当格 ...

最新文章

  1. 如何判断一个元素在亿级数据中是否存在?
  2. 005-JQuery之CSS
  3. codeforces C. Inna and Huge Candy Matrix 解题报告
  4. 关于vue的语法规则检测报错问题
  5. 微信授权,重定向两次
  6. 零基础入门Python3-循环详解
  7. 4.3-软件开发中,“原型图”的作用与绘制方法说明
  8. 装完系统还要装什么_一键重装系统后需要干嘛
  9. 字典遍历时不能修改字典元素
  10. 微信小程序getUserProfile详解
  11. Thingworx自定义扩展开发(一)- 开发环境搭建、Extension Demo Coding
  12. 百度地图 android 自身地点,Android使用百度地图SDK获得当前设备位置所在的省、市(系列1)...
  13. linux图形界面安装rpm包,linux中alias别名及rpm安装软件
  14. 城域网IPv6过渡技术——MAP技术
  15. java 图片 缩略图_java 图片缩略图的两种方法
  16. matlab gps信号,gps信号和其干扰的matlab仿真
  17. window系统下nodejs安装及环境配置
  18. Ae:表达式应用基础
  19. Oracle创建同义词并授权
  20. Linux objdump命令(反汇编、查看符号)

热门文章

  1. JAVAWEB(笔记)
  2. 检查异常和非检查异常 有空你去学一下检查异常和非检查异常
  3. 修改Sublime Text3 的侧边栏字体大小
  4. pythonnumpy教程_Python教程:numpy的基本介绍
  5. java日志——基本日志+高级日志
  6. 对象包装器与自动(拆箱)装箱+参数数量可变的方法+枚举类
  7. 小程序真机测试错误代码_测试不充分:知道您的代码是否真的可以投入生产的5种方法...
  8. activiti dmn_新的DMN编辑器预览
  9. cassandra可视化_容器化Spring Data Cassandra应用程序
  10. 用xshell传输jdk_在JDK 9中将InputStream传输到OutputStream