JDK8中好用的日期处理-LocalDate类-LocalTime-LocalDateTIme,mysql解决时区相差13小时的问题,日期格式器DateTimeFormatter

介绍

LocalDate是一种更为高效的日期类,比起Date的复杂具有相当高的简洁性,吸取了企业级别的joda.time时间处理的优点,避免了传统的Date和Calendar复合起来计算的难处

LocalDate

写在最前面
两个特性务必记住!!!!

  • 线程安全
  • 所有修改返回皆为新对象,对之前的对象没有影响

示例代码:

package LocalDate;

import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;

package LocalDate;

import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;

public class Demo3 {

    private LocalDate localDate = LocalDate.now();
    private List<Integer> list = new ArrayList<>();

    public void change() {
        localDate.plusDays(1);
        list.add(1);
    }

    public static void main(String[] args) {
        Demo3 demo3 = new Demo3();

        Runnable runnable = demo3::change;
        List<Thread> list = new ArrayList<>();
        for (int i = 0; i < 50; i++) {
            list.add(new Thread(runnable));
        }
        for (Thread thread : list) {
            thread.start();
        }
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(demo3.list.size());
        System.out.println(demo3.localDate);
    }
}


--------结果-------
49
2018-07-30

分析:

  • 为了让结果更清楚这里用了list作为比较,笔者实验的日期就是7.30,结果localDate本身并没有改变还是7.30,可以看出,所有的修改不是在原来的对象上进行更改,而是new出了新的对象。这点得以证明
  • 线程安全:由于是new出新对象,就不存在对同一资源的存取这个竞争条件,没有了竞争条件,自然不存在线程安不安全的问题,list50次是对同一个对象进行存取,所以会出现线程安全问题。这么一对比就能知晓了。官方也指出了它的线程安全性,此处只是取一个方法试试看。
  • 注意:不可以再赋值比如localDate=localDate.plusDays(1); 如果这样就人为地加入了赋值这个操作,就不能够准确检测出方法的线程安全性。

常用API:
这里写图片描述

localTime

与LocalDate相似:
这里写图片描述

日期更改

涉及到日期的更改就需要另一个强大的类:TemporalAdjusters
这里写图片描述
相关API查看文档即可,不多。

简单小例子

System.out.println("今天的日期是" + today);
System.out.println("上周的星期一为:" + today.minusWeeks(1).with(DayOfWeek.MONDAY));
System.out.println("下个月的第二个周一的时间为:" + today.plusMonths(1).with(TemporalAdjusters.dayOfWeekInMonth(2, DayOfWeek.MONDAY)));

--------输出--------
今天的日期是2018-07-30
上周的星期一为:2018-07-23
下个月的第二个周一的时间为:2018-08-13

// 取当前日期:
LocalDate today = LocalDate.now(); // -> 2014-12-24
// 根据年月日取日期,12月就是12:
LocalDate crischristmas = LocalDate.of(2014, 12, 25); // -> 2014-12-25
// 根据字符串取:
LocalDate endOfFeb = LocalDate.parse("2014-02-28"); // 严格按照ISO yyyy-MM-dd验证,02写成2都不行,当然也有一个重载方法允许自己定义格式
LocalDate.parse("2014-02-29"); // 无效日期无法通过:DateTimeParseException: Invalid date

// 取本月第1天:
LocalDate firstDayOfThisMonth = today.with(TemporalAdjusters.firstDayOfMonth()); // 2014-12-01
// 取本月第2天:
LocalDate secondDayOfThisMonth = today.withDayOfMonth(2); // 2014-12-02
// 取本月最后一天,再也不用计算是282930还是31:
LocalDate lastDayOfThisMonth = today.with(TemporalAdjusters.lastDayOfMonth()); // 2014-12-31
// 取下一天:
LocalDate firstDayOf2015 = lastDayOfThisMonth.plusDays(1); // 变成了2015-01-01
// 取20151月第一个周一,这个计算用Calendar要死掉很多脑细胞:
LocalDate firstMondayOf2015 = LocalDate.parse("2015-01-01").with(TemporalAdjusters.firstInMonth(DayOfWeek.MONDAY)); // 2015-01-05

例子来自于廖雪峰老师的。
这里写图片描述

和sql对应的关系

SQL -> Java

date -> LocalDate
time -> LocalTime
timestamp -> LocalDateTime

实战:jdbc连接

示例:

LocalDateTime nowTime = LocalDateTime.now();
Connection connection = null;
PreparedStatement statement = null;

try {
    String url = "jdbc:mysql://localhost:3306/laboratory?timeZone=TMC&useSSL=true";
    String user = "root";
    String password = "lyy1314520";
    // 加载驱动
    Class.forName("com.mysql.cj.jdbc.Driver");

    //获取连接
    connection = DriverManager.getConnection(url, user, password);

    String sql = "insert into time(time) values(?)";
    //获取statement对象
    statement = connection.prepareStatement(sql);
    statement.setTimestamp(1, Timestamp.valueOf(nowTime));

    // 执行sql语句
    statement.executeUpdate();
} catch (Exception e) {
    e.printStackTrace();
} finally {
    if (statement!=null){
        try {
            statement.close();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
    if (connection != null){
        try {
            connection.close();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
  }

发现问题:存储在数据库的时间少了13个小时,搜索资料后,原来是时区不对,只需要在命令行窗口输入这样的两条代码设置时区即可。默认是使用系统的。

set global time_zone='+08:00';
set time_zone = '+08:00';

show variables like '%time_zone:'
这里写图片描述

再次执行代码,插入准确时间。

准确插入时间图:
这里写图片描述
附上,TimeStamp->LocalDateTime方法:

LocalDateTime localDateTime = time.toLocalDateTime();

格式转换

介绍:
说到转换格式,有SimpleDateFormat和DateFormat,但是它们两者都是线程不安全的!啥情况下会有这样的问题呢?如果我们为了实现日期转换这样的工具,每次都new一个对象,但是用完了就不用了,就造成了浪费,为此我们会将它写成单例的,但是单例的同时,一个对象供多个线程使用的时候,就会出现线程安全的问题。这个时候就需要这个新的jdk8出的DateTimeformatter这个类。

字符串->类

写在前面。如果是很工整的格式,yyyy-MM-dd 这种日期格式字符串,直接用LocalDate.parse()进行转换就行了,相对应的时间也是。既有时间又有日期的用DateTimeformatte这个类就行。
示例:

String time = "1997-01-31 18:39:20";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
LocalDateTime dateTime =LocalDateTime.from(formatter.parse(time));

或者:
String time = "1997-01-31 18:39:20";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
LocalDateTime dateTime = LocalDateTime.parse(time,formatter);

类->字符串

  • 如果是LocalDate这种标准格式的,直接toString就可以了,-
  • 如果是LocalTime这种格式的,toString会附带纳秒值21:06:30.760163
    这个时候你可以使用日期格式器,或者这样
    LocalTime time1 = LocalTime.now().withNano(0),把纳秒直接清0.
  • 如果是LocalDateTime,这个时候是需要一个日期转换器的。才能由时间+日期->想要的时间,
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
LocalDateTime nowTime = LocalDateTime.now();
String result = nowTime.format(formatter);

附上一张字符转换表,个人习惯这种字母的,不喜欢系统设定的这些常量。

  Symbol  Meaning                     Presentation      Examples
  ------  -------                     ------------      -------
   G       era                         text              AD; Anno Domini; A
   u       year                        year              2004; 04
   y       year-of-era                 year              2004; 04
   D       day-of-year                 number            189
   M/L     month-of-year               number/text       7; 07; Jul; July; J
   d       day-of-month                number            10

   Q/q     quarter-of-year             number/text       3; 03; Q3; 3rd quarter
   Y       week-based-year             year              1996; 96
   w       week-of-week-based-year     number            27
   W       week-of-month               number            4
   E       day-of-week                 text              Tue; Tuesday; T
   e/c     localized day-of-week       number/text       2; 02; Tue; Tuesday; T
   F       week-of-month               number            3

   a       am-pm-of-day                text              PM
   h       clock-hour-of-am-pm (1-12)  number            12
   K       hour-of-am-pm (0-11)        number            0
   k       clock-hour-of-am-pm (1-24)  number            0

   H       hour-of-day (0-23)          number            0
   m       minute-of-hour              number            30
   s       second-of-minute            number            55
   S       fraction-of-second          fraction          978
   A       milli-of-day                number            1234
   n       nano-of-second              number            987654321
   N       nano-of-day                 number            1234000000

   V       time-zone ID                zone-id           America/Los_Angeles; Z; -08:30
   z       time-zone name              zone-name         Pacific Standard Time; PST
   O       localized zone-offset       offset-O          GMT+8; GMT+08:00; UTC-08:00;
   X       zone-offset 'Z' for zero    offset-X          Z; -08; -0830; -08:30; -083015; -08:30:15;
   x       zone-offset                 offset-x          +0000; -08; -0830; -08:30; -083015; -08:30:15;
   Z       zone-offset                 offset-Z          +0000; -0800; -08:00;

   p       pad next                    pad modifier      1

   '       escape for text             delimiter
   ''      single quote                literal           '
   [       optional section start
   ]       optional section end
   #       reserved for future use
   {       reserved for future use
   }       reserved for future use

总结

这次主要学习了jdk8的日期LocalDate简单入门,总结如下:

  • LocalDate日期是一个便于使用的日期类,线程安全,Date类比较复杂,时间计算麻烦。
  • DateTimeFormatter的使用也安全,方便。以后用它来代替SimpleDateFormat
  • JDBC的TimeStamp类和LocalDateTime的转换也很方便,提供了相应的方法。
  • 使用的时候,日期必须是标准的yyyy-MM-dd格式,比如1月必须写成01,不然会报错。
  • 这就是我总结的知识点,算是入个门,能解决正常的使用。如有错误,还望指出,及时更正。与君共勉。

猜你喜欢

转载自blog.csdn.net/qq_41376740/article/details/81292504
今日推荐