java8-新的日期API java新建日期
bigegpt 2024-10-25 10:24 5 浏览
背景
java的日期和时间API设计不理想,java8引入新的时间和日期API就是为了解决这个问题。
老的日期API的核心类 缺点 Date 月从0开始,年最小从1900年开始,没有时区的概念 Calendar 月从0开始 DateFormat 线程不安全 其它 同时存在Date和Calendar难以选择; Date和Calendar类都是可变的,维护噩梦 java8引入了类似joda-time的新特性。核心类如下:
LocalDate
标识日期。下面是javadoc的翻译:
日期没有时区,处在ISO-8601日历系统下。例如:2007-12-03
是一个不可变日期对象常见表示是年月日,其它的日期字段比如dayOfYear,dayOfWeek,weekOfYear也是可以访问的。
LocalDate.now().get(ChronoField.ALIGNED_WEEK_OF_YEAR);
举个例子, 2007年10月2日可以存放在LocalDate里。
这个类没有存储或者代表时间或者时区。
相反,它描叙了日期,比如可以用来表示生日,他不能代表一个时间线上的没有附加信息的瞬间,比如一个偏移量后者时区。
这是一个基于值的类,使用标识敏感的操作,比如 == , hashCode(), 或者LocalDate对象的同步操作可能会有无法预测的结果,并且应该避免。equals方法应该被用来比较。
这个类是不可变并且线程安全的。
下面是javadoc原文,不重要的内容我删掉了。
/**
* A date without a time-zone in the ISO-8601 calendar system,
* such as {@code 2007-12-03}.
* <p>
* {@code LocalDate} is an immutable date-time object that represents a date,
* often viewed as year-month-day. Other date fields, such as day-of-year,
* day-of-week and week-of-year, can also be accessed.
* For example, the value "2nd October 2007" can be stored in a {@code LocalDate}.
* <p>
* This class does not store or represent a time or time-zone.
* Instead, it is a description of the date, as used for birthdays.
* It cannot represent an instant on the time-line without additional information
* such as an offset or time-zone.
* <p>
* This is a <a href="{@docRoot}/java/lang/doc-files/ValueBased.html">value-based</a>
* class; use of identity-sensitive operations (including reference equality
* ({@code ==}), identity hash code, or synchronization) on instances of
* {@code LocalDate} may have unpredictable results and should be avoided.
* The {@code equals} method should be used for comparisons.
* This class is immutable and thread-safe.
public final class LocalDate
implements Temporal, TemporalAdjuster, ChronoLocalDate, Serializable
主要有4种构造方法:
构造方法种类 说明 of类 有4个, of(int year,int month, int day) , of(int year, Month month, int day) , ofYearDay(int year, int dayofYear), ofEpochday(long epochDay) 1970年1月1日为机器元年 now类3个 实际上重载了now(Clock clock), 其它两个 now(), now(ZoneId zoneId) 取得是机器在某个时区的始终,取的日期,然后调用ofEpochday(long epochDay)来初始化日期 from类1个 from(TemporalAccessor temporal) 通过一个Temporal对象来初始化日期,具体用法见例子 parse类2个 pase(string date),parse(String date , DateTimeFormatter formater)以字符串的方式初始化日期 获取类方法:
获取类方法 说明 getYear() 获取年 getMonthValue() 获取月份数值 getMonth() 得到月份对象 getDayOfMonth 得到月份的天数值 getDayOfWeek 得到一周的星期数 package com.test.time;
import java.time.LocalDate;
import java.time.chrono.ChronoLocalDate;
import java.time.format.DateTimeFormatter;
import java.time.temporal.TemporalAccessor;
import java.time.temporal.TemporalField;
import java.util.Objects;
/**
* 说明:localDate类研究
* @author carter
* 创建时间: 2019年11月11日 15:31
**/
public class LocalDateTest {
public static void main(String[] args) {
LocalDate localDate = LocalDate.of(2019,11,11);
print("localDate.getYear()",localDate.getYear());
print("localDate.getMonth().getValue()",localDate.getMonth().getValue());
print("localDate.lengthOfMonth()",localDate.lengthOfMonth());
print("localDate.getMonthValue()",localDate.getMonthValue());
print("localDate.getDayOfMonth()",localDate.getDayOfMonth());
print("localDate.getDayOfWeek().getValue()",localDate.getDayOfWeek().getValue());
print("localDate.getDayOfYear()",localDate.getDayOfYear());
print("localDate.lengthOfYear()",localDate.lengthOfYear());
print("localDate.getChronology()",localDate.getChronology());
print("localDate.getEra()",localDate.getEra());
print("localDate.isLeapYear()",localDate.isLeapYear());
final LocalDate localDateNow = LocalDate.now();
print("localDateNow.atStartOfDay()",localDateNow.atStartOfDay());
final LocalDate localDateOfEpo = LocalDate.ofEpochDay(1L);
print("localDateOfEpo.format(DateTimeFormatter.BASIC_ISO_DATE)",localDateOfEpo.format(DateTimeFormatter.BASIC_ISO_DATE));
final LocalDate localDateFrom = LocalDate.from(new TemporalAccessor() {
@Override
public boolean isSupported(TemporalField field) {
return true;
}
@Override
public long getLong(TemporalField field) {
//这块实际上设置的是epochDay,即机器的增量日期
return 2;
}
});
print("localDateFrom.format(DateTimeFormatter.BASIC_ISO_DATE)",localDateFrom.format(DateTimeFormatter.BASIC_ISO_DATE));
final LocalDate localDateParse = LocalDate.parse("2019-11-11");
print("localDateParse.format(DateTimeFormatter.BASIC_ISO_DATE)",localDateParse.format(DateTimeFormatter.BASIC_ISO_DATE));
}
private static void print(String title,Object printContent){
System.out.println(title + " : " + Objects.toString(printContent));
}
}
输出:
localDate.getYear() : 2019
localDate.getMonth().getValue() : 11
localDate.lengthOfMonth() : 30
localDate.getMonthValue() : 11
localDate.getDayOfMonth() : 11
localDate.getDayOfWeek().getValue() : 1
localDate.getDayOfYear() : 315
localDate.lengthOfYear() : 365
localDate.getChronology() : ISO
localDate.getEra() : CE
localDate.isLeapYear() : false
localDateNow.atStartOfDay() : 2019-11-12T00:00
localDateOfEpo.format(DateTimeFormatter.BASICISODATE) : 19700102
localDateFrom.format(DateTimeFormatter.BASICISODATE) : 19700103
localDateParse.format(DateTimeFormatter.BASICISODATE) : 20191111
其它的方法先不做探究,后面会研究到。先提出这块的代码参考。
LocalTime
跟LocalDate类似,javadoc类似,区别是它可以标示的值通常表现为时分秒,可以精确到纳秒。
通过获取机器时间的时分秒纳秒部分来初始化。
package com.test.time;
import java.time.LocalDate;
import java.time.LocalTime;
/**
* 说明:localTime类研究
* @author carter
* 创建时间: 2019年11月12日 10:35
**/
public class LocalTimeTest {
public static void main(String[] args) {
final LocalTime localTime = LocalTime.of(12, 0, 0, 0);
System.out.println(localTime);
System.out.println( "LocalTime.hour"+ " : "+localTime.getHour());
System.out.println( "LocalTime.getMinute"+ " : "+localTime.getMinute());
System.out.println( "LocalTime.getSecond"+ " : "+localTime.getSecond());
System.out.println( "LocalTime.getNano"+ " : "+localTime.getNano());
System.out.println( "LocalTime.MIDNIGHT"+ " : "+LocalTime.MIDNIGHT);
System.out.println("LocalTime.NOON"+ " : "+LocalTime.NOON);
System.out.println("LocalTime.MIN"+ " : "+LocalTime.MIN);
System.out.println("LocalTime.MAX"+ " : "+LocalTime.MAX);
}
}
LocalDateTime
是localDate,localTime的合体,标示日期时间。
package com.test.time;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneId;
import java.time.ZoneOffset;
/**
* 说明:localdatetime的简单研究
* @author carter
* 创建时间: 2019年11月12日 10:47
**/
public class LocalDateTimeTest {
public static void main(String[] args) {
LocalDateTime localDateTime = LocalDateTime.now();
System.out.println("localDateTime.getYear()" + " : " + localDateTime.getYear());
System.out.println("localDateTime.getMonthValue()" + " : " + localDateTime.getMonthValue());
System.out.println("localDateTime.getDayOfMonth()" + " : " + localDateTime.getDayOfMonth());
System.out.println("localDateTime.getHour()" + " : " + localDateTime.getHour());
System.out.println("localDateTime.getMinute()" + " : " + localDateTime.getMinute());
System.out.println("localDateTime.getSecond()" + " : " + localDateTime.getSecond());
System.out.println("localDateTime.getNano()" + " : " + localDateTime.getNano());
final LocalDateTime ofEpochSecond = LocalDateTime.ofEpochSecond(System.currentTimeMillis() / 1000, 0,ZoneOffset.ofHours(8));
System.out.println("ofEpochSecond" + " : " + ofEpochSecond);
//通过localdatetime获取localdate, localtime,也可以通过localdate,localtime得到localdatetime
final LocalDate localDate = localDateTime.toLocalDate();
final LocalTime localTime = localDateTime.toLocalTime();
System.out.println("localDate" + " : " + localDate);
System.out.println("localTime" + " : " + localTime);
final LocalDateTime localDateTimeFromLocalDate = localDate.atTime(LocalTime.MIN);
final LocalDateTime localDateTimeFromLoalTime = localTime.atDate(LocalDate.now());
System.out.println("localDateTimeFromLocalDate" + " : " + localDateTimeFromLocalDate);
System.out.println("localDateTimeFromLoalTime" + " : " + localDateTimeFromLoalTime);
}
}
Instant
机器的时间模型:是以机器元年1970年1月1日经历的秒数来计算;等同于LocalDateTime. 但是只能从中获取秒和纳秒,无法获取年月日时分等时间。
package com.test.time;
import java.time.Instant;
import java.time.temporal.ChronoField;
import java.time.temporal.ChronoUnit;
/**
* 说明:TODO
* @author carter
* 创建时间: 2019年11月12日 11:08
**/
public class InstanceTest {
public static void main(String[] args) {
Instant instant1 = Instant.ofEpochSecond(3);
Instant instant2 = Instant.ofEpochSecond(2,1000000000);
System.out.println("instant1" + " : " + instant1);
System.out.println("instant2" + " : " + instant2);
System.out.println(instant1.get(ChronoField.DAY_OF_YEAR));
}
}
Exception in thread "main" java.time.temporal.UnsupportedTemporalTypeException: Unsupported field: DayOfYearat java.time.Instant.get(Instant.java:566)at com.test.time.InstanceTest.main(InstanceTest.java:25)
LocalDate,LocalTime.LocalDateTime.Instant都实现Temporal接口,可以读取和设置时间,接下来的Duration,Period是基于两个Temporal接口来建模的。
Duration
主要获取秒和纳秒的单位,不可计算LocalDate的时间差;