学习笔记:LocalDateTime


1. 环境

Since JDK8


LocalDateTime 的好处

  • 每一个时间对象,都是线程安全的
  • 每一个对象都没有公开的构造器,如果需要一个对象你首先想的不是 new,而是静态工厂方法: now、of、from
  • 如果你喜欢敲全类名,请在使用时间api时忘记java.util和java.text,记住java.time

2. 代码

为什么建议使用你 LocalDateTime ,而不是 Date?
根据这篇博客学习,下面练习的代码, 并附上了输出结果.

JDK8新增的 java.time

JDK8 新增的 java.time 这篇讲得好
JDK8 的新特性 这个不错

20220210补充的 JDK8 新时间

     2.1 LocalDate: 获取年月日
	/** LocalDate: 获取年月日 */
	@Test
	public void m1() {
		//获取当前年月日
		LocalDate localDate = LocalDate.now();
		//构造指定的年月日
		LocalDate localDate1 = LocalDate.of(2019, 9, 10);
		System.out.println("localDate = " + localDate); // localDate = 2020-07-04
		System.out.println("localDate1 = " + localDate1); // localDate1 = 2019-09-10
		
		int year = localDate.getYear();
		System.out.println("year = " + year); // year = 2020
		int year1 = localDate.get(ChronoField.YEAR);
		System.out.println("year1= " + year1); // year1= 2020
		Month month = localDate.getMonth();
		System.out.println("month= " + month); // month= JULY
		int month1 = localDate.get(ChronoField.MONTH_OF_YEAR);
		System.out.println("month1= " + month1); // month1= 7
		int day = localDate.getDayOfMonth();
		System.out.println("day= " + day); // day= 6
		int day1 = localDate.get(ChronoField.DAY_OF_MONTH);
		System.out.println("day1= " + day1); // day1= 6
		DayOfWeek dayOfWeek = localDate.getDayOfWeek();
		System.out.println("dayOfWeek= " + dayOfWeek); // dayOfWeek= MONDAY
		int dayOfWeek1 = localDate.get(ChronoField.DAY_OF_WEEK);
		System.out.println("dayOfWeek1= " + dayOfWeek1); // dayOfWeek1= 1
	}
     2.2 LocalTime: 获取时分秒
	/** LocalTime: 获取时分秒 */
	@Test
	public void m2() {
		// 获取当前时分秒
		LocalTime localTime = LocalTime.now();
		// 构造指定的时分秒
		LocalTime localTime1 = LocalTime.of(10, 30, 55);
		System.out.println("localTime= " + localTime); // localTime= 10:34:27.591553
		System.out.println("localTime1= " + localTime1); // localTime1= 10:30:55
		

		//获取小时
		int hour = localTime.getHour(); 
		int hour1 = localTime.get(ChronoField.HOUR_OF_DAY);
		System.out.println("hour= " + hour); // hour= 10
		System.out.println("hour1= " + hour1); // hour1= 10
		//获取分
		int minute = localTime.getMinute();
		int minute1 = localTime.get(ChronoField.MINUTE_OF_HOUR);
		System.out.println("minute = " + minute); // minute = 34
		System.out.println("minute1 = " + minute1); // minute1 = 34
		//获取秒
		int second = localTime.getSecond();
		int second1 = localTime.get(ChronoField.SECOND_OF_MINUTE);
		System.out.println("second = " + second); // second = 27
		System.out.println("second1 = " + second1); // second1 = 27
	}
     2.3 LocalDateTime: 获取年月日时分秒
	/** LocalDateTime: 获取年月日时分秒 */
	@Test
	public void m3() {
		
		//获取当前年月日
		LocalDate localDate = LocalDate.now();
		// 获取当前时分秒
		LocalTime localTime = LocalTime.now();
		
		LocalDateTime localDateTime = LocalDateTime.now();
		LocalDateTime localDateTime1 = LocalDateTime.of(LocalDate.of(2020, 7, 3), LocalTime.of(10, 38, 55));
		LocalDateTime localDateTime2 = LocalDateTime.of(2019, Month.SEPTEMBER, 10, 14, 46, 56);
		LocalDateTime localDateTime3 = localDate.atTime(localTime); // 相当于 localDate + localTime = LocalDateTime
		LocalDateTime localDateTime4 = localTime.atDate(localDate); // 相当于 localDate + localTime = LocalDateTime
		
		System.out.println("localDateTime = " + localDateTime); // localDateTime = 2020-07-06T10:40:10.128524
		System.out.println("localDateTime1 = " + localDateTime1); // localDateTime1 = 2020-07-03T10:38:55
		System.out.println("localDateTime2 = " + localDateTime2); // localDateTime2 = 2019-09-10T14:46:56
		System.out.println("localDateTime3 = " + localDateTime3); // localDateTime3 = 2020-07-08T14:58:20.685306
		System.out.println("localDateTime4 = " + localDateTime4); // localDateTime4 = 2020-07-08T14:58:20.685306
		
		
		// 获取LocalDate
		LocalDate localDate2 = localDateTime.toLocalDate();
		// 获取LocalTime
		LocalTime localTime2 = localDateTime.toLocalTime();
		System.out.println("localDate2 = " + localDate2); // localDate2 = 2020-07-08;  localDateTime = 2020-07-08T15:05:34.630987
		System.out.println("localTime2 = " + localTime2); // localTime2 = 15:05:34.630987;  localDateTime = 2020-07-08T15:05:34.630987
		
		
		// 获取秒数. ( 用 System.currentTimeMills()更方便 )
		Instant instant = Instant.now();
		long currentSecond = instant.getEpochSecond();
		long timeStamp1 = instant.toEpochMilli();
		long timeStamp2 = System.currentTimeMillis();
		System.out.println("currentSecond = " + currentSecond); // currentSecond = 1594192226
		System.out.println("timeStamp1 = " + timeStamp1); // timeStamp1 = 1594192226826
		System.out.println("timeStamp2 = " + timeStamp2); // timeStamp2 = 1594192226826
	}
     2.4 LocalDateTime 年月日时分秒的 操作.
	/** 
	 * LocalDateTime 年月日时分秒的 操作.
	 * 
	 * LocalDate、LocalTime、LocalDateTime、Instant为不可变对象,修改这些对象对象会返回一个副本
	 * 
	 * plusXX(): 在原来的基础上加
	 * withXX(): 直接设定值
	 */
	@Test
	public void m4() {
		LocalDateTime localDateTime = LocalDateTime.of(1997, Month.FEBRUARY, 2, 9, 13, 14);
		System.out.println("localDateTime = " + localDateTime); // localDateTime = 1997-02-02T09:13:14

		//增加一年 plusYears()
		localDateTime = localDateTime.plusYears(1);
		System.out.println("localDateTime = " + localDateTime); // localDateTime = 1998-02-02T09:13:14
		localDateTime = localDateTime.plus(1, ChronoUnit.YEARS);
		System.out.println("localDateTime = " + localDateTime); // localDateTime = 1999-02-02T09:13:14
		// 减少一年 minusYears()
		localDateTime = localDateTime.minusYears(1);
		System.out.println("localDateTime = " + localDateTime); // localDateTime = 1998-02-02T09:13:14
		
		//减少一个月 minusMonths(); 同理增加一月 就是 plusMonths(); 还可以修改 日、时分秒、周等等.
		localDateTime = localDateTime.minusMonths(1);
		System.out.println("localDateTime = " + localDateTime); // localDateTime = 1998-01-02T09:13:14
		localDateTime = localDateTime.minus(1, ChronoUnit.MONTHS);
		System.out.println("localDateTime = " + localDateTime); // localDateTime = 1997-12-02T09:13:14
		
		/* with: 设定值 */
		//修改年为2020
		localDateTime = localDateTime.withYear(2020);
		System.out.println("localDateTime = " + localDateTime); // localDateTime = 2020-12-02T09:13:14
		//修改为2022
		localDateTime = localDateTime.with(ChronoField.YEAR, 2022);
		System.out.println("localDateTime = " + localDateTime); // localDateTime = 2022-12-02T09:13:14
	}
     2.5 时间计算
	/**
	 * 时间计算
	 * 
	 * 比如有些时候想知道这个月的最后一天是几号、下个周末是几号,通过提供的时间和日期API可以很快得到答案
	 */
	@Test
	public void m5() {
		LocalDate localDate = LocalDate.now();
		System.out.println("localDate = " + localDate); // localDate = 2020-07-08
		
		// 年的第一天
		LocalDate localDate1 = localDate.with(TemporalAdjusters.firstDayOfYear());
		System.out.println("localDate1 = " + localDate1); // localDate1 = 2020-01-01
		
		// 月的第一天; 还有很多其他的, 点进去看吧.
		localDate = localDate.with(TemporalAdjusters.firstDayOfMonth());
		System.out.println("localDate = " + localDate); // localDate = 2020-07-01
	}
     2.6 格式化时间

LocalDateTime -> String

	/** 
	 * 格式化时间 
	 * 
	 * DateTimeFormatter默认提供了多种格式化方式,如果默认提供的不能满足要求,可以通过DateTimeFormatter的ofPattern方法创建自定义格式化方式
	 */
	@Test
	public void m6() {
		LocalDate localDate = LocalDate.of(2019, 9, 10);
		String s1 = localDate.format(DateTimeFormatter.BASIC_ISO_DATE);
		String s2 = localDate.format(DateTimeFormatter.ISO_LOCAL_DATE);
		//自定义格式化
		DateTimeFormatter dateTimeFormatter =   DateTimeFormatter.ofPattern("dd/MM/yyyy");
		String s3 = localDate.format(dateTimeFormatter);
		System.out.println("localDate = " + localDate); // localDate = 2019-09-10
		System.out.println("s1 = " + s1); // s1 = 20190910
		System.out.println("s2 = " + s2); // s2 = 2019-09-10
		System.out.println("s3 = " + s3); // s3 = 10/09/2019
		
		// LocalDateTime 转换成 特定格式的 字符串
		LocalDateTime now = LocalDateTime.now();
		String nowStr1 = now.format(DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss"));
		String nowStr2 = now.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm"));
		System.out.println("now = " + now); // now = 2020-07-08T16:41:12.647672
		System.out.println("nowStr1 = " + nowStr1); // nowStr1 = 2020/07/08 16:41:12
		System.out.println("nowStr2 = " + nowStr2); // nowStr2 = 2020-07-08 16:42
		
		// format 是线程不安全的.  用 parse() 方法时候 需要特定格式的, 并且还要 try-catch
		String dateStr = "";
		Date date = new Date();
		if (date != null) {
			dateStr = new SimpleDateFormat("yyyy MM dd HH:mm").format(date);
		}
		System.out.println("dateStr = " + dateStr); // dateStr = 2020 07 08 16:43
	}
     2.7 解析时间:

String -> LocalDateTime

	/** 
	 * 解析时间: 感觉还是 SimpleDateTime好用, 即使它线程不安全, 但是在开辟一个线程处理 好了.
	 * 
	 * 注意: 
	 * 1. 要解析的字符串, 格式必须要和 设定的pattern是一致的, 不然就报错。 
	 * 2. 使用 解析必须要 try-catch,  SimpleDateFormate的parse还会提示要处理异常, LocalDateTime居然不提示...
	 */
	@Test
	public void m7() {
		String dateStr = "1997-02-02 17:13:14";
		LocalDateTime localDateTime = null;
		try {
			localDateTime = LocalDateTime.parse(dateStr, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
		} catch (Exception e) {
			e.printStackTrace();
		}
		System.out.println("localDateTime = " + localDateTime); // localDateTime = 1997-02-02T17:13:14
		
		/*
		 * 自我感觉 没 SimpleDateTime好用啊... 虽然 SimpleDateTime是线程不安全的
		 * 
		 * 1. LocatDateTime的parse() 使用 LocalDateTime 那字符串必须要 年月日 时分秒, 如果只写年月日, 就算 ofPattern("yyyy-MM-dd") 也不行. 需要用 LocalDate.parse()
		 * 2. 而SimpleDateFormat.parse() 就算只写了 "yyyy-MM-dd" 只需要保证 年月日是此格式即可, 后面的时分秒无所谓.
		 */
		
		Date date = null;
		try {
			date = new SimpleDateFormat("yyyy-MM-dd").parse(dateStr);
		} catch (ParseException e) {
			e.printStackTrace();
		}
		System.out.println("date = " + date); // date = Sun Feb 02 00:00:00 CST 1997
		
		
		// LocalDate, 这样是不会报错的, 字符串只写了年月日 就必须用 LocalDate来解析.
		String dateStr2 = "1997-02-02";
		LocalDate localDate = null;
		try {
			localDate = LocalDate.parse(dateStr2, DateTimeFormatter.ofPattern("yyyy-MM-dd"));
		} catch (Exception e) {
			e.printStackTrace();
		}
		System.out.println("localDate = " + localDate); // localDate = 1997-02-02
	}
     2.8 看得懂的时间输出

挺好用的东西… JDK 14 会报错, JDK8没问题

	/** 挺好用的东西.. JDK 14 会报错, JDK8没问题 */
	@Test
	public void m8() {
		LocalDateTime d1=LocalDateTime.now();
		FormatStyle dateTimeStyle=FormatStyle.LONG;
		 
		Locale.setDefault(Locale.CHINA);
		DateTimeFormatter formater=DateTimeFormatter.ofLocalizedDateTime(dateTimeStyle);
		String format = d1.format(formater);
		System.out.println(format);//2017年11月30日 下午04时10分32秒
		 
		dateTimeStyle=FormatStyle.MEDIUM;
		 
		Locale.setDefault(Locale.CHINA);
		formater=DateTimeFormatter.ofLocalizedDateTime(dateTimeStyle);
		format = d1.format(formater);
		System.out.println(format);//2017-11-30 16:10:32
		 
		Locale.setDefault(Locale.UK);
		format = d1.format(formater);
		System.out.println(formater);//2017-11-30 16:10:32
		
		// Locale.setDefault 和 DateTimeFormatter.ofLocalizedDateTime 必须重新设置一次, 否则像上面这样的输出结果和 第2个一样
		Locale.setDefault(Locale.UK);
		formater=DateTimeFormatter.ofLocalizedDateTime(dateTimeStyle);
		format = d1.format(formater);
		System.out.println(format);//30-Nov-2017 16:10:32
	}
     2.9 日期加减日期
         2.91 LocalDateTime.util()
         2.92 Duration.between()
public class Test02_LocalDateTime {

	public static void main(String[] args) {
		
		ZoneId zoneId = ZoneId.systemDefault();
		System.out.println("zoneId = " + zoneId); // zoneId = Asia/Shanghai
		
		LocalDateTime now = LocalDateTime.now();
		String dateStr1 = now.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
		System.out.println("dateStr1 = " + dateStr1);
		LocalDateTime loc = LocalDateTime.of(1997, 07, 13, 14, 55, 59);
		String dateStr2 = loc.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
		System.out.println("locStr = " + dateStr2); // dateStr2 = 1997-07-13 14:55:00

/// JDK14 报错, JDK8 可以.		
//		FormatStyle formatStyle = FormatStyle.LONG;
//		Locale.setDefault(Locale.CHINA);
//		DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofLocalizedDateTime(formatStyle);
//		String f1 = now.format(dateTimeFormatter);
//		System.out.println("f1 = " + f1);
		
		/* 
		 * 日期加减日期
		 * 
		 * 1. minusXX/plusXX: 只能单独加减年月日 or 时分秒的.
		 *    TemporalAmount 实现类之一是: Duration
		 * 3. LocalDateTime.until(): 第二个参数 - 第一个参数 的出来的正负天数.
		 * 4. Duration.between(): 第二个参数 - 第一个参数 的出来的正负天数.   
		 */
		Duration duration = Duration.between(now, loc);
		System.out.println("duration = " + duration); // duration = PT-201690H-36M-19.603835S .
		
		now = LocalDateTime.of(2020, 7, 16, 10, 13, 14);
		dateStr1 = now.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
		System.out.println("dateStr1 = " + dateStr1); // dateStr1 = 2020-07-16 10:13:14
		
		// locStr = 1997-07-13 14:55:59
		now = now.minusYears(loc.getYear()); // 1997
		dateStr1 = now.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
		System.out.println("dateStr1 = " + dateStr1); // dateStr1 = 0023-07-16 10:13:14
		
		now = now.minusDays(loc.getDayOfMonth()); // 13
		dateStr1 = now.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
		System.out.println("dateStr1 = " + dateStr1); // dateStr1 = 0023-07-03 10:13:14
		now = now.plusDays(13);
		
		TemporalAmount amountToSubtract = Duration.ofDays(13);
		now = now.minus(amountToSubtract);
		dateStr1 = now.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
		System.out.println("dateStr1 = " + dateStr1); // dateStr1 = 0023-07-03 10:13:14
		
		
		/*
		 * 时间与时间的计算
		 * 
		 * 两个时间之间的计算,结果为一个量。如,计算两个时间相隔多少天。
		 * 举例,计算2016年元旦到五一劳动节相隔多少天?
		 */
		LocalDateTime d1=LocalDateTime.of(2020, 07, 16, 11, 04);
		LocalDateTime d2=LocalDateTime.of(1997, 01, 03, 13, 14);
		System.err.println("d1 = " + d1.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))); // d1 = 2020-07-16 11:04:00
		System.err.println("d2 = " + d2.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))); // d2 = 1997-01-03 13:14:00
		
		long interval = d2.until(d1, ChronoUnit.DAYS);
		System.out.println(interval); // 8594

		// 也可以使用时间量的计算:
		Duration d = Duration.between(d1, d2);
		System.out.println(d.toDays()); // -8594
		System.out.println(d.toHours()); // -206277
		
		long age = d2.until(d1, ChronoUnit.YEARS);
		System.out.println("age = " + age); // age = 23, 这个算年龄...  但是不算天数, 自己写的 age计算的工具类 会把天算上.
	}
}
     7.0 相关工具类
	/** 听说是 解决 SImpleDateFormat线程不安全问题 */
	private static final ThreadLocal<SimpleDateFormat> local = new ThreadLocal<SimpleDateFormat>();
	private static SimpleDateFormat getTime() {
		SimpleDateFormat sdf = local.get();
		if (sdf == null) {
			sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
			local.set(sdf);
		}
		return sdf;
	}
	
    /** LocalDate转Date */
    public static Date localDateToDate(LocalDate localDate) {
        if (null == localDate) {
            return null;
        }
        ZonedDateTime zonedDateTime = localDate.atStartOfDay(ZoneId.systemDefault());
        return Date.from(zonedDateTime.toInstant());
    }

    /** Date转LocalDate */
    public static LocalDate dateToLocalDate(java.util.Date date) {
        if (null == date) {
            return null;
        }
        return date.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
    }

    /** Date转换为LocalDateTime */
    public static LocalDateTime dateToLocalDateTime(Date date){
        if (null == date) {
            return null;
        }
        Instant instant = date.toInstant();
        ZoneId zoneId = ZoneId.systemDefault();
        LocalDateTime localDateTime = instant.atZone(zoneId).toLocalDateTime();
        return localDateTime;
    }

    /** LocalDateTime转换为Date */
    public static Date localDateTimeToDate( LocalDateTime localDateTime){
    	if (localDateTime == null) {
    		return null;
    	}
        ZonedDateTime zdt = localDateTime.atZone(ZoneId.systemDefault());
        return Date.from(zdt.toInstant());
    }
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值