Java8-日期和时间

2019-03-04  本文已影响0人  PawsUp
LocalDate date = LocalDate.of(2014, 3, 18);//2014-03-18
int year = date.getYear();//2014
Month month = date.getMonth();//MARCH
int day = date.getDayOfMonth();//18
DayOfWeek dow = date.getDayOfWeek();//TUESDAY
int len = date.lengthOfMonth();//31(这个月有多少天)
boolean leap = date.isLeapYear();//false(是不是闰年)

还可以使用工厂方法从系统时钟中获取当前的日期:

LocalDate today = LocalDate.now();   

这些日期-时间类,都提供了这些静态工厂方法,还可以通过传递一个TemporalField参数给get方法拿到同样的信息。TemporalField是一个接口,它定义了如何访问temporal对象某个字段的值。ChronoField枚举实现了这一接口,所以可以很方便地使用get方法得到枚举元素的值。(这些类都实现了Temporal接口,Temporal接口定义了如何读取和操纵为时间建模的对象的值。)


int year = date.get(ChronoField.YEAR);
int month = date.get(ChronoField.MONTH_OF_YEAR);
int day = date.get(ChronoField.DAY_OF_MONTH);

使用静态方法parse,LocalDateLocalTime都可以通过解析代表它们的字符串创建,一旦传递的字符串参数无法被解析为合法的LocalDateLocalTime对象,这两个parse方法都会抛出一个继承自RuntimeExceptionDateTimeParseException异常。

LocalDate date = LocalDate.parse("2014-03-18");
LocalTime time = LocalTime.parse("13:45:20"); 
// 2014-03-18T13:45:20
LocalDateTime dt1 = LocalDateTime.of(2014, Month.MARCH, 18, 13, 45, 20);
LocalDateTime dt2 = LocalDateTime.of(date, time);
LocalDateTime dt3 = date.atTime(13, 45, 20);
LocalDateTime dt4 = date.atTime(time);
LocalDateTime dt5 = time.atDate(date);

通过atTime或者atDate方法,向LocalDate传递一个时间对象,或者向LocalTime传递一个日期对象的方式,可以创建一个LocalDateTime对象。

也可以使用toLocalDate或者toLocalTime方法,从LocalDateTime中提取LocalDate或者LocalTime组件

LocalDate date1 = dt1.toLocalDate();
LocalTime time1 = dt1.toLocalTime(); 
Instant.ofEpochSecond(3);
Instant.ofEpochSecond(3, 0);
Instant.ofEpochSecond(2, 1_000_000_000);//2秒之后加上100万纳秒(1秒)
Instant.ofEpochSecond(4, -1_000_000_000); 4秒之前100弯纳秒(1秒)

由于Instant类也支持静态工厂方法now,它能够帮你获取当前时刻的时间戳,但是,Instant的设计初衷是为了便于机器使用。它包含的是由秒及纳秒所构成的数字。所以,它无法处理那些我们非常容易理解的时间单位。

int day = Instant.now().get(ChronoField.DAY_OF_MONTH); 

会抛出如下异常:

java.time.temporal.UnsupportedTemporalTypeException: Unsupported field:
     DayOfMonth 
Duration d1 = Duration.between(time1, time2);
Duration d1 = Duration.between(dateTime1, dateTime2);
Duration d2 = Duration.between(instant1, instant2); 

以年、月或者日的方式对多个时间单位建模,可以使用Period类。使用该类的工厂方法between,可以得到两个LocalDate之间的时长,

Period tenDays = Period.between(LocalDate.of(2014, 3, 8),
                                LocalDate.of(2014, 3, 18)); 
image.png image.png

以上这些日期-时间对象都是不可修改的,为了更好地支持函数式编程,确保线程安全。

//所有的方法都返回一个修改了属性的对象。它们都不会修改原来的对象!
LocalDate date1 = LocalDate.of(2014, 3, 18);
LocalDate date2 = date1.withYear(2011);
LocalDate date3 = date2.withDayOfMonth(25);
LocalDate date4 = date3.with(ChronoField.MONTH_OF_YEAR, 9);
LocalDate date1 = LocalDate.of(2014, 3, 18);
LocalDate date2 = date1.plusWeeks(1);
LocalDate date3 = date2.minusYears(3);
LocalDate date4 = date3.plus(6, ChronoUnit.MONTHS); //2011-09-25

plus方法也是通用方法,它和minus方法都声明于Temporal接口中,通过这些方法,对TemporalUnit对象加上或者减去一个数字,能非常方便地将Temporal对象前溯或者回滚至某个时间段,通过ChronoUnit枚举可以非常方便地实现TemporalUnit接口。

image.png
import static java.time.temporal.TemporalAdjusters.*;
LocalDate date1 = LocalDate.of(2014, 3, 18);
LocalDate date2 = date1.with(nextOrSame(DayOfWeek.SUNDAY));//2014-03-18
LocalDate date3 = date2.with(lastDayOfMonth()); //2014-03-31
image.png

也可以自定义一个TemporalAdjuster接口

@FunctionalInterface
public interface TemporalAdjuster {
     Temporal adjustInto(Temporal temporal);
} 
TemporalAdjuster nextWorkingDay = TemporalAdjusters.ofDateAdjuster(
     temporal -> {
         DayOfWeek dow =
               DayOfWeek.of(temporal.get(ChronoField.DAY_OF_WEEK));
         int dayToAdd = 1;
         if (dow == DayOfWeek.FRIDAY) dayToAdd = 3;
         if (dow == DayOfWeek.SATURDAY) dayToAdd = 2;
         return temporal.plus(dayToAdd, ChronoUnit.DAYS);
     });

    date = date.with(nextWorkingDay); 

ofDateAdjuster接受一个UnaryOperator<LocalDate>的参数。

LocalDate date = LocalDate.of(2014, 3, 18);
String s1 = date.format(DateTimeFormatter.BASIC_ISO_DATE);//20140318 
String s2 = date.format(DateTimeFormatter.ISO_LOCAL_DATE); //2014-03-18

使用工厂方法parse达到重创该日期对象的目的:

LocalDate date1 = LocalDate.parse("20140318",
                                 DateTimeFormatter.BASIC_ISO_DATE);
LocalDate date2 = LocalDate.parse("2014-03-18",
                                 DateTimeFormatter.ISO_LOCAL_DATE); 

和老的java.util.DateFormat相比较,所有的DateTimeFormatter实例都是线程安全的。所以,你能够以单例模式创建格式器实例,就像DateTimeFormatter所定义的那些常量,并能在多个线程间共享这些实例。

也可以按照某个特定的模式创建格式器:

DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd/MM/yyyy"); 
LocalDate date1 = LocalDate.of(2014, 3, 18);
String formattedDate = date1.format(formatter);//按照指定模式生成字符串
LocalDate date2 = LocalDate.parse(formattedDate, formatter); //利用同样的格式器解析生成的字符串

DateTimeFormatterBuilder类还提供了更复杂的格式器,你可以选择恰当的方法,一步一步地构造自己的格式器。同时,提供了强大的解析功能。

‘DateTimeFormatter italianFormatter = new DateTimeFormatterBuilder()
       .appendText(ChronoField.DAY_OF_MONTH)
       .appendLiteral(". ")
       .appendText(ChronoField.MONTH_OF_YEAR)
       .appendLiteral(" ")
       .appendText(ChronoField.YEAR)
       .parseCaseInsensitive()
       .toFormatter(Locale.ITALIAN); 

//处理不同的时区和使用不同的日历 12.3

上一篇下一篇

猜你喜欢

热点阅读