java 时间日期 详解

在 JDK1.8 之前都使用时将相关的操作存在多线程问题,可以通过 ThreadLocal 来解决
public class DateFormatThreadLocal {
    private static final ThreadLocal<DateFormat> df = new ThreadLocal<DateFormat>() {
        @Override
        protected DateFormat initialValue() {
            return new SimpleDateFormat( "yyyyMMdd" );
        }
    };
    public static final Date convert(String source) throws ParseException {
        return df .get().parse(source);
    }
}

使用 LocalDate、 LocalTime、 LocalDateTime
LocalDate、 LocalTime、 LocalDateTime 类的实例是不可变的对象,分别表示使用 ISO-8601日历系统的日期、时间、日期和时间。它们提供简单的日期或时间,并不包含当前的时间信息,也不包含与时区相关的信息
注 : ISO-8601日历系统是国际标准化组织制定的现代公民的日期和时间的表示法

LocalDateTime ldt = LocalDateTime. now ();
System. out .println(ldt);

LocalDateTime ld2 = LocalDateTime. of ( 2016 , 11 , 21 , 10 , 10 , 10 );
System. out .println(ld2);

LocalDateTime ldt3 = ld2.plusYears( 20 );
System. out .println(ldt3);

LocalDateTime ldt4 = ld2.minusMonths( 2 );
System. out .println(ldt4);

System. out .println(ldt.getYear());
System. out .println(ldt.getMonthValue());
System. out .println(ldt.getDayOfMonth());
System. out .println(ldt.getHour());
System. out .println(ldt.getMinute());
System. out .println(ldt.getSecond());
方法描述示例
now()静态方法,根据当前时间创建对象
LocalDate localDate = LocalDate.now();
LocalTime localTime = LocalTime.now();
LocalDateTime localDateTime = LocalDateTime.now();
of()静态方法,根据指定日期/时间创建对象
LocalDate localDate = LocalDate.of(2016, 10, 26);
LocalTime localTime = LocalTime.of(02, 22, 56);
LocalDateTime localDateTime = LocalDateTime.of(2016, 10, 26, 12, 10, 55);
plusDays, plusWeeks,
plusMonths, plusYears
向当前 LocalDate 对象添加几天、几周、 几个月、 几年 
minusDays, minusWeeks,
minusMonths, minusYears
从当前 LocalDate 对象减去几天、几周、 几个月、 几年 
plus, minus添加或减少一个 Duration 或 Period 
withDayOfMonth,
withDayOfYear,
withMonth,
withYear
将月份天数、 年份天数、 月份、 年份 修 改 为 指 定 的 值 并 返 回 新 的LocalDate 对象 
getDayOfMonth获得月份天数(1-31) 
getDayOfYear获得年份天数(1-366) 
getDayOfWeek获得星期几(返回一个 DayOfWeek枚举值) 
getMonth获得月份, 返回一个 Month 枚举值 
getMonthValue获得月份(1-12) 
getYear获得年份 
until获得两个日期之间的 Period 对象,或者指定 ChronoUnits 的数字 
isBefore, isAfter比较两个 LocalDate 
isLeapYear判断是否是闰年 

Instant 时间戳 (使用 Unix 元年 1970年1月1日 00:00:00 所经历的毫秒值)
用于“时间戳”的运算。它是以Unix元年(传统的设定为UTC时区1970年1月1日午夜时分)开始所经历的描述进行运算
Instant ins = Instant. now ();  //默认使用 UTC 时区
System. out .println(ins);

OffsetDateTime odt = ins.atOffset(ZoneOffset. ofHours ( 8 ));
System. out .println(odt);

System. out .println(ins.getNano());

Instant ins2 = Instant. ofEpochSecond ( 5 );
System. out .println(ins2);

Duration 和 Period
Duration : 用于计算两个“时间”间隔
Period : 用于计算两个“日期”间隔
Instant ins1 = Instant. now ();

System. out .println( "--------------------" );
try {
    Thread. sleep ( 1000 );
} catch (InterruptedException ignored) {
}

Instant ins2 = Instant. now ();

System. out .println( "所耗费时间为:" + Duration. between (ins1, ins2));

System. out .println( "----------------------------------" );

LocalDate ld1 = LocalDate. now ();
LocalDate ld2 = LocalDate. of ( 2011 , 1 , 1 );

Period pe = Period. between (ld2, ld1);
System. out .println(pe.getYears());
System. out .println(pe.getMonths());
System. out .println(pe.getDays());

日期的操纵
TemporalAdjuster : 时间校正器。有时我们可能需要获取例如 : 将日期调整到“下个周日”等操作
TemporalAdjusters : 该类通过静态方法提供了大量的常用 TemporalAdjuster 的实现
例如获取下个周日:
LocalDate nextSunday = LocalDate. now ().with(TemporalAdjusters. next (DayOfWeek. SUNDAY ));

LocalDateTime ldt = LocalDateTime. now ();
System. out .println(ldt);

LocalDateTime ldt2 = ldt.withDayOfMonth( 10 );
System. out .println(ldt2);

LocalDateTime ldt3 = ldt.with(TemporalAdjusters. next (DayOfWeek. SUNDAY ));
System. out .println(ldt3);

// 自定义:下一个工作日
LocalDateTime ldt5 = ldt.with((l) -> {
    LocalDateTime ldt4 = (LocalDateTime) l;
    DayOfWeek dow = ldt4.getDayOfWeek();
    if (dow.equals(DayOfWeek. FRIDAY )) {
        return ldt4.plusDays( 3 );
    } else if (dow.equals(DayOfWeek. SATURDAY )) {
        return ldt4.plusDays( 2 );
    } else {
        return ldt4.plusDays( 1 );
    }
});
System. out .println(ldt5);

解析与格式化
java.time.format.DateTimeFormatter 类:该类提供了三种格式化方法 :
1> 预定义的标准格式
2> 语言环境相关的格式
3> 自定义的格式
//     DateTimeFormatter dtf = DateTimeFormatter.ISO_LOCAL_DATE;
DateTimeFormatter dtf = DateTimeFormatter. ofPattern ( "yyyy年MM月dd日 HH:mm:ss E" );

LocalDateTime ldt = LocalDateTime. now ();
String strDate = ldt.format(dtf);
System. out .println(strDate);

LocalDateTime newLdt = ldt. parse (strDate, dtf);
System. out .println(newLdt);

时区的处理
Java8 中加入了对时区的支持,带时区的时间为分别为 : ZonedDate、 ZonedTime、 ZonedDateTime
其中每个时区都对应着 ID,地区ID都为 “ {区域}/{城市}”的格式
例如 : Asia/Shanghai 等
ZoneId : 该类中包含了所有的时区信息
              getAvailableZoneIds() : 可以获取所有时区时区信息
              of(id) : 用指定的时区信息获取 ZoneId 对象

Set<String> set = ZoneId. getAvailableZoneIds ();
set.forEach(System. out ::println);

LocalDateTime ldt = LocalDateTime. now (ZoneId. of ( "Asia/Shanghai" ));
System. out .println(ldt);

ZonedDateTime zdt = ZonedDateTime. now (ZoneId. of ( "US/Pacific" ));
System. out .println(zdt);

与传统日期处理的转换
To 遗留类 
From 遗留类
java.time.Instant
java.util.Date
Date.from(instant)date.toInstant()
java.time.Instant
java.sql.Timestamp
Timestamp.from(instant)timestamp.toInstant()
java.time.ZonedDateTime
java.util.GregorianCalendar
GregorianCalendar.from(zonedDateTime)cal.toZonedDateTime()
java.time.LocalDate
java.sql.Time
Date.valueOf(localDate)date.toLocalDate()
java.time.LocalTime
java.sql.Time
Date.valueOf(localDate)date.toLocalTime()
java.time.LocalDateTime
java.sql.Timestamp
Timestamp.valueOf(localDateTime)timestamp.toLocalDateTime()
java.time.ZoneId
java.util.TimeZone
Timezone.getTimeZone(id)timeZone.toZoneId()
java.time.format.DateTimeFormatter
java.text.DateFormat
formatter.toFormat()

JDK1.8前的时间操作与之后的时间操作
以下操作存在问题
SimpleDateFormat sdf = new SimpleDateFormat( "yyyyMMdd" );
Callable<Date> task = new Callable<Date>() {
   @Override
   public Date call() throws Exception {
      return sdf .parse( "20161121" );
   }
};
ExecutorService pool = Executors. newFixedThreadPool ( 10 );
List<Future<Date>> results = new ArrayList<>();
for ( int i = 0 ; i < 10 ; i++) {
   results.add(pool.submit(task));
}
for (Future<Date> future : results) {
   System. out .println(future.get());
}
pool.shutdown();

解决多线程安全问题
Callable<Date> task = new Callable<Date>() {
    @Override
    public Date call() throws Exception {
        return DateFormatThreadLocal. convert ( "20161121" );
    }
};
ExecutorService pool = Executors. newFixedThreadPool ( 10 );
List<Future<Date>> results = new ArrayList<>();
for ( int i = 0 ; i < 10 ; i++) {
    results.add(pool.submit(task));
}
for (Future<Date> future : results) {
    System. out .println(future.get());
}
pool.shutdown();

使用 JDK1.8 的 DateTimeFormatter 就不存在 多线程问题
DateTimeFormatter dtf = DateTimeFormatter. ofPattern ( "yyyyMMdd" );
Callable<LocalDate> task = new Callable<LocalDate>() {
    @Override
    public LocalDate call() throws Exception {
        LocalDate ld = LocalDate. parse ( "20161121" , dtf );
        return ld;
    }
};
ExecutorService pool = Executors. newFixedThreadPool ( 10 );
List<Future<LocalDate>> results = new ArrayList<>();
for ( int i = 0 ; i < 10 ; i++) {
    results.add(pool.submit(task));
}
for (Future<LocalDate> future : results) {
    System. out .println(future.get());
}
pool.shutdown();

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值