Java中日期 JavaSE Spring

2021-11-01 约 6496 字 阅读时长13 分钟

Java中日期

Java中日期

概念

本地时间

不同的时区,在同一时刻,本地时间是不同的。全球一共分为24个时区,伦敦所在的时区称为标准时区,其他时区按东/西偏移的小时区分,北京所在的时区是东八区。

时区

通过本地时间无法确定一个准确的时刻,所以需要添加时区

时区表示方式:

  1. GMT或者UTC加时区偏移表示,基本等价,UTC使用了更加精确的原子钟计时;例:GMT+08:00或者UTC+08:00表示东八区
  2. 缩写,缩写容易产生混淆,一般不使用;例如:CST表示中国标准时间China Standard Time,也可以表示美国中部时间Central Standard Time USA
  3. 洲/城市;例如:Asia/Shanghai表示上海所在地的时区。特别注意城市名称不是任意的城市,而是由国际标准组织规定的城市

夏令时

夏令时,就是夏天开始的时候,把时间往后拨1小时,夏天结束的时候,再把时间往前拨1小时

涉及到夏令时,相同的时区如果表达方式不同,转换出来的时间是不同的,例如:

对于2019-11-20和2019-6-20两个日期来说,假设北京人在纽约:

  • 如果以GMT或者UTC作为时区,无论日期是多少,时间都是19:00
  • 如果以国家/城市表示,例如America/NewYork,虽然纽约也在西五区,但是,因为夏令时的存在,在不同的日期,GMT时间和纽约时间可能是不一样的

image-20211015105637649

在程序中应统一配置:数据库服务器,JVM,JSON转化工具的时区为GMT+8,忽略夏令时的使用

注意:JSON转化工具和链接数据库设置的时区一定需要一致,否则可能出现多一个小时或者少一个小时的奇怪问题

本地化

计算机通过Locale来针对当地用户习惯格式化日期、时间、数字、货币等

Java.lang.Locale代表特定的地理、政治和文化。需要Locale来执行其任务的操作叫语言环境敏感的操作

构造一个系统默认的Locale:Locale defaultLocale = Locale.getDefault();

GMT+8 和 Asia/Shanghai 的区别

java
 1public static void main(String[] args) throws ParseException {
 2    String strDate="1986-05-04 02:00:00";   //夏令营时段
 3    SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
 4    Date date = sdf.parse(strDate);  //Sun May 04 03:00:00 CDT 1986
 5
 6    SimpleDateFormat sdf1=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
 7    sdf1.setTimeZone(TimeZone.getTimeZone("GMT+8"));
 8    String format1 = sdf1.format(date);    //1986-05-04 02:00:00
 9
10    SimpleDateFormat sdf2=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
11    sdf2.setTimeZone(TimeZone.getTimeZone("Asia/Shanghai"));
12    String format2 = sdf2.format(date);    //1986-05-04 03:00:00
13}

夏令时(Daylight Saving Time: DST),也叫 夏时制,是指为了节约能源,在天亮的早的夏季,人为将时间调快一小时,以充分利用光照资源,节约照明用电;在冬季光照时间变短后,将时间再拨回一小时的标准时间,也称为冬令时

  • GMT+8 因为没有位置信息,所以无法使用夏令时
  • Asia/Shanghai 使用夏令时

时间戳字符串中不包含时区信息时,解析到的具体时区如果是使用夏令时的,就会跟不使用夏令时的时区,时间不一致。

Date和Calendar

Java.util.Date:日期类

Java.text.SimpleDateFormat:专门格式化日期的类

Java.util.Calendar:日历

  1. 生成时间 new Date ();格式化时间 (new SimpleDateFoamat).format (new Date ());
  2. 获取当前时间戳,System.currentTimeMillis ()
  3. Date–>String,日期格式化,SimpleDateFormat.format (日期对象);String–>Date,SimpleDateFormat.parse (“日期字符串”)

示例代码

java
 1Date time=new Date();
 2SimpleDateFormat sdf1=new SimpleDateFormat("yyyy/MM/dd HH:mm:ss SSS");
 3
 4System.out.println(sdf1.format(time)); //格式化时间,输出:2020/07/02 12:16:39 092
 5System.out.println(time);   //输出:Thu Jul 02 12:16:39 CST 2020
 6
 7String time3="1998/06/27 24:00:00 000";
 8Date time4=sdf1.parse(time3); //将字符串解析为时间,必须是相应格式
 9System.out.println(time4); //输出Sun Jun 28 00:00:00 CST 1998
10
11long currentTime=System.currentTimeMillis();    //获取当前时间戳
12System.out.println(currentTime);    //输出:1593663508687
13
14Date time5=new Date(System.currentTimeMillis()-1000*60*60*24); //传递时间戳,构造时间 这里获取昨天这个时候时间
15System.out.println(sdf1.format(time5)); //输出昨天这时的时间

JDK1.8之前

Date类

表示特定的瞬间,精确到毫秒。在 JDK 1.1 之前,类 Date 有两个其他的函数。它允许把日期解释为年、月、日、小时、分钟和秒值。它也允许格式化和解析日期字符串。不过,这些函数的 API 不易于实现国际化。从 JDK 1.1 开始,应该使用 Calendar 类实现日期和时间字段之间转换,使用 DateFormat 类来格式化和解析日期字符串。Date 中的相应方法已废弃(查阅自API文档) Calendar类 Calendar 类是一个抽象类,它为特定瞬间与一组诸如 YEAR、MONTH、DAY_OF_MONTH、HOUR 等 日历字段之间的转换提供了一些方法,并为操作日历字段(例如获得下星期的日期)提供了一些方法。瞬间可用毫秒值来表示,它是距历元(即格林威治标准时间 1970 年 1 月 1 日的 00:00:00.000,格里高利历)的偏移量。 该类还为实现包范围外的具体日历系统提供了其他字段和方法。这些字段和方法被定义为 protected。 与其他语言环境敏感类一样,Calendar 提供了一个类方法 getInstance,以获得此类型的一个通用的对象。Calendar 的 getInstance 方法返回一个 Calendar 对象,其日历字段已由当前日期和时间初始化

Date(时间)

构造方法

  • 无参构造:获取当前时间
  • 有参构造:传入时间戳(毫秒),获取时间戳的时间
  • 其余构造方法已经弃用

常用方法

java
1leftdate.before(rightdate);		//leftdate小于rightdate时返回true
2
3leftdate.after(rightdate);		//leftdate大于rightdate时返回true
4
5date1.getTime();	//获取时间戳(毫秒)
6
7date.setTime(1649927726538L);	//根据时间戳设置时间
8
9leftdate.compareTo(rightdate);	//leftdate < rightdate 返回 -1; leftdate = rightdate 返回 0; leftdate > rightdate 返回 1

Calendar(日历)

创建对象

java
1Calendar calendar=Calendar.getInstance();	//获取当前时间的日历对象,默认时区和语言环境
2
3Calendar calendar2 = Calendar.getInstance(Locale.ENGLISH);	//获取当前时间的日历对象,默认时区和指定的语言环境
4
5Calendar calendar3=Calendar.getInstance(TimeZone.getTimeZone(ZoneId.of("GMT-8")));
6Calendar calendar3=Calendar.getInstance(TimeZone.getTimeZone("UTC"));	//获取当前时间的日历对象指定时区和默认语言环境

TimeZone.getAvailableIDs()可以列出所有有效时区

常用方法

java
 1calendar1.getTimeZone();	//获取时区
 2
 3calendar1.getWeekYear();	//获取年
 4
 5calendar3.yearLength();		//以天为单位,返回一年长度
 6
 7calendar1.monthLength(1);	//以天为单位,返回某月长度,参数为月数-1
 8
 9calendar1.add(Calendar.YEAR,5);		//日历年份 +5
10
11calendar1.add(Calendar.DAY_OF_MONTH,-1);	//日历月数 -1
12
13calendar1.add(Calendar.DAY_OF_MONTH,29);	//日历天数 +29
14
15calendar1.add(Calendar.HOUR,12);	//日历时间 +12小时

时间工具类

java
  1public class OldDateUtil {
  2    private OldDateUtil(){}
  3    /**
  4     * 获得当前日期
  5     */
  6    public static String getCurrentDate(String format) {
  7        SimpleDateFormat f = new SimpleDateFormat(format);
  8        Date date = new Date();
  9        return f.format(date);
 10    }
 11
 12    /**
 13     * 时间转换为字符串,如果转换格式为空使用默认格式
 14     */
 15    public static String dateToStr(Date date, String format) {
 16        if (format==null||format.length()==0){
 17            format=TimeFormat.DEFAULT_FORMAT.format;
 18        }
 19        SimpleDateFormat f = new SimpleDateFormat(format);
 20        return f.format(date);
 21    }
 22
 23    /**
 24     * 字符串转换为时间,如果转换格式为空使用默认格式
 25     */
 26    public static Date strToDate(String dateTime, String format) throws Exception {
 27        if (format==null||format.length()==0){
 28            format=TimeFormat.DEFAULT_FORMAT.format;
 29        }
 30        SimpleDateFormat f = new SimpleDateFormat(format);
 31        return f.parse(dateTime);
 32    }
 33
 34    /**
 35     * 时间包括在某个时间段内
 36     */
 37    public static Boolean timeInclude(Date checkTime, Date begntime, Date endtime) {
 38        if(begntime!=null&&endtime!=null){
 39            return checkTime.after(begntime)&&checkTime.before(endtime);
 40        }
 41        return false;
 42    }
 43
 44    /**
 45     * 时间大小比较
 46     * 大于返回 1、小于返回 -1、等于返回 0
 47     */
 48    public static int checkTime(Date left, Date right) {
 49        return left.compareTo(right);
 50    }
 51
 52    /**
 53     * 将月数转换成年数
 54     */
 55    public static double monthToYear(int month) {
 56        return month / 12D;
 57    }
 58
 59    /**
 60     * 时间戳转换为字符串
 61     */
 62    public static String timestamp2Str(Timestamp time) {
 63        Date date = null;
 64        if (null != time) {
 65            date = new Date(time.getTime());
 66        }
 67        return dateToStr(date, TimeFormat.DEFAULT_FORMAT.format);
 68    }
 69
 70    /**
 71     * 字符串转化为时间戳
 72     */
 73    public static Timestamp str2Timestamp(String str) throws Exception {
 74        Date date = strToDate(str, TimeFormat.DEFAULT_FORMAT.format);
 75        return new Timestamp(date.getTime());
 76    }
 77
 78    /**
 79     * 计算日期之间相差天数
 80     */
 81    public static int getBetweenDays(Date date1, Date date2) {
 82        long betweenDays = date1.getTime() - date2.getTime();
 83        betweenDays = betweenDays / 1000 / 60 / 60 / 24;
 84        return Math.abs((int) betweenDays);
 85    }
 86
 87    /**
 88     * 时间转换为整数
 89     */
 90    public static Integer date2Integer(Date date, String format) {
 91        String str = dateToStr(date, format);
 92        return Integer.valueOf(str);
 93    }
 94
 95    /**
 96     * date增减分钟
 97     */
 98    public static Date addMinute(Date date, int minute) {
 99        Calendar calendar = Calendar.getInstance();
100        calendar.setTime(date);
101        calendar.add(Calendar.MINUTE, minute);
102        return calendar.getTime();
103    }
104
105    /**
106     * date增减天数
107     */
108    public static Date addDay(Date date, int day) {
109        Calendar calendar = Calendar.getInstance();
110        calendar.setTime(date);
111        calendar.add(Calendar.DAY_OF_MONTH, day);
112        return calendar.getTime();
113    }
114
115    /**
116     * date增减月数
117     */
118    public static Date addMonth(Date date, int month) {
119        Calendar calendar = Calendar.getInstance();
120        calendar.setTime(date);
121        calendar.add(Calendar.MONTH, month);
122        return calendar.getTime();
123    }
124
125    /**
126     * 计算到指定时间的年龄
127     */
128    public static int getAge(Date birthDay, Date endDate) {
129        int age = 0;
130        SimpleDateFormat format_y = new SimpleDateFormat("yyyy");
131        SimpleDateFormat format_M = new SimpleDateFormat("MM");
132
133        String birth_year = format_y.format(birthDay);
134        String this_year = format_y.format(endDate);
135
136        String birth_month = format_M.format(birthDay);
137        String this_month = format_M.format(endDate);
138
139        // 初步,估算
140        age = Integer.parseInt(this_year) - Integer.parseInt(birth_year);
141
142        // 如果未到出生月份,则age - 1
143        if (this_month.compareTo(birth_month) < 0) {
144            age -= 1;
145        }
146        if (age < 0) { // age小于0,未满一岁
147            age = 0;
148        }
149        return age;
150    }
151
152    /**
153     * 验证字符串日期格式
154     */
155    public static boolean ValidateDate(String str,OldDateUtil.TimeFormat timeFormat){
156        return str.matches(timeFormat.regExp);
157    }
158
159    enum TimeFormat{
160        HH_MM_SS_COLON ("HH:mm:ss","^([01][0-9]|2[0-3]):[0-5][0-9]:([0-5][0-9]|60)$") ,
161        HH_MM_SS_MILSEC_COLON("HH:mm:ss.SSS","^([01][0-9]|2[0-3]):[0-5][0-9]:([0-5][0-9]|60).\\d{1,3}$"),
162        HH_MM_SS_CHINESE ("HH时mm分ss秒","^([01][0-9]|2[0-3])时[0-5][0-9]分([0-5][0-9]|60)秒$"),
163        YYYY_MM_DD_CHINESE("yyyy年MM月dd日","^[1-9]\\d{3}年(0[1-9]|1[0-2])月(0[1-9]|[1-2][0-9]|3[0-1])日$"),
164        YYYY_MM_DD_LINE("yyyy-MM-dd","^[1-9]\\d{3}-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1])$"),
165        YYYY_MM_DD_SLASH("yyyy/MM/dd","^[1-9]\\d{3}/(0[1-9]|1[0-2])/(0[1-9]|[1-2][0-9]|3[0-1])$"),
166        YYYY_MM_DD_BACKSLASH("yyyy\\MM\\dd","^[1-9]\\d{3}\\(0[1-9]|1[0-2])\\(0[1-9]|[1-2][0-9]|3[0-1])$"),
167        YYYY_MM_DD_NONE("yyyyMMdd","^[1-9]\\d{3}(0[1-9]|1[0-2])(0[1-9]|[1-2][0-9]|3[0-1])$"),
168        YYYY_MM("yyyyMM","^[1-9]\\d{3}(0[1-9]|1[0-2])$"),
169        YYYY("yyyy","^[1-9]\\d{3}$"),
170        YYYY_MM_DD_HH_MM_SS_CHINESE("yyyy年MM月dd日 HH时mm分ss秒","^[1-9]\\d{3}年(0[1-9]|1[0-2])月(0[1-9]|[1-2][0-9]|3[0-1])日 ([01][0-9]|2[0-3])时[0-5][0-9]分([0-5][0-9]|60)秒$"),
171        YYYY_MM_DD_HH_MM_SS_LINE("yyyy-MM-dd HH:mm:ss","^[1-9]\\d{3}-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1]) ([01][0-9]|2[0-3]):[0-5][0-9]:([0-5][0-9]|60)$"),
172        YYYY_MM_DD_HH_MM_SS_SLASH("yyyy/MM/dd HH:mm:ss","^[1-9]\\d{3}/(0[1-9]|1[0-2])/(0[1-9]|[1-2][0-9]|3[0-1]) ([01][0-9]|2[0-3]):[0-5][0-9]:([0-5][0-9]|60)$"),
173        YYYY_MM_DD_HH_MM_SS_BACKSLASH("yyyy\\MM\\dd HH:mm:ss","^[1-9]\\d{3}\\(0[1-9]|1[0-2])\\(0[1-9]|[1-2][0-9]|3[0-1]) ([01][0-9]|2[0-3]):[0-5][0-9]:([0-5][0-9]|60)$"),
174        YYYY_MM_DD_HH_MM_SS_NONE("yyyyMMdd HH:mm:ss","^[1-9]\\d{3}(0[1-9]|1[0-2])(0[1-9]|[1-2][0-9]|3[0-1]) ([01][0-9]|2[0-3]):[0-5][0-9]:([0-5][0-9]|60)$"),
175        YYYY_MM_DD_HH_MM_SS_BUS("yyyyMMddHHmmss","^[1-9]\\d{3}(0[1-9]|1[0-2])(0[1-9]|[1-2][0-9]|3[0-1])([01][0-9]|2[0-3])[0-5][0-9]([0-5][0-9]|60)$"),
176        YYYY_MM_DD_HH_MM_SS_MILSEC_LINE("yyyy-MM-dd HH:mm:ss.SSS","^[1-9]\\d{3}-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1]) ([01][0-9]|2[0-3]):[0-5][0-9]:([0-5][0-9]|60).\\d{1,3}$"),
177        YYYY_MM_DD_HH_MM_SS_MILSEC_SLASH("yyyy/MM/dd HH:mm:ss.SSS","^[1-9]\\d{3}/(0[1-9]|1[0-2])/(0[1-9]|[1-2][0-9]|3[0-1]) ([01][0-9]|2[0-3]):[0-5][0-9]:([0-5][0-9]|60).\\d{1,3}$"),
178        YYYY_MM_DD_HH_MM_SS_MILSEC_BACKSLASH("yyyy\\MM\\dd HH:mm:ss.SSS","^[1-9]\\d{3}\\(0[1-9]|1[0-2])\\(0[1-9]|[1-2][0-9]|3[0-1]) ([01][0-9]|2[0-3]):[0-5][0-9]:([0-5][0-9]|60).\\d{1,3}$"),
179        YYYY_MM_DD_HH_MM_SS_MILSEC_NONE("yyyyMMdd HH:mm:ss.SSS","^[1-9]\\d{3}(0[1-9]|1[0-2])(0[1-9]|[1-2][0-9]|3[0-1]) ([01][0-9]|2[0-3]):[0-5][0-9]:([0-5][0-9]|60).\\d{1,3}$"),
180        DEFAULT_FORMAT("yyyy-MM-dd HH:mm:ss","^[1-9]\\d{3}-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1]) ([01][0-9]|2[0-3]):[0-5][0-9]:([0-5][0-9]|60)$");
181        TimeFormat(String format, String regExp) {
182            this.format = format;
183            this.regExp = regExp;
184        }
185        final String format;
186        final String regExp;
187    }
188}

JDK1.8新引入

  • 本地日期和时间:LocalDateTimeLocalDateLocalTime
  • 带时区的日期和时间:ZonedDateTime
  • 时刻:Instant
  • 时区:ZoneIdZoneOffset
  • 时间间隔:Duration
  • 以及一套新的用于取代SimpleDateFormat的格式化类型DateTimeFormatter

LocalDate和LocalTime

基本使用

java
 1LocalDate localDate=LocalDate.now();    //获取当前日期
 2LocalTime localTime=LocalTime.now();    //获取当前时间
 3LocalDateTime localDateTime=LocalDateTime.now();    //获取当前时刻
 4
 5LocalDate localDate1=LocalDate.of(1998,6,27);   //获取指定日期
 6LocalTime localTime1=LocalTime.of(23,59,59);       //获取指定时间
 7LocalDateTime localDateTime1=LocalDateTime.of(1998,6,27,23,59,59);     //获取指定时刻
 8
 9System.out.println(localDate.toString()+" "+localTime.toString());   //2021-10-15 11:15:22.961561300
10System.out.println(localDateTime.toString());   //2021-10-15 11:15:22.961561300
11
12System.out.println(localDate1.toString()+" "+localTime1.toString());   //1998-06-27 23:59:59
13System.out.println(localDateTime1.toString());      //1998-06-27T23:59:59

相关转换

java
1LocalDateTime localDateTime=LocalDateTime.now();
2LocalDate localDate=localDateTime.toLocalDate();    //获取日期
3LocalTime localTime=localDateTime.toLocalTime();    //获取时间
4DateTimeFormatter dtf=DateTimeFormatter.ofPattern("yyyy-MMMM-dd HH:mm:ss");    //传入字符串
5System.out.println(localDateTime.format(dtf));

ZonedDateTime

LocalDateTime总是表示本地日期和时间,要表示一个带时区的日期和时间,就需要ZonedDateTime

可以简单地把ZonedDateTime理解成LocalDateTimeZoneIdZoneIdJava.time引入的新的时区类,注意和旧的Java.util.TimeZone区别。

基本使用

java
1ZonedDateTime zdt1 = ZonedDateTime.now(); // 默认时区
2ZonedDateTime zdt2 = ZonedDateTime.now(ZoneId.of("America/New_York")); // 用指定时区获取当前时间
3System.out.println(zdt1);	//2021-10-15T11:37:05.565490300+08:00[Asia/Shanghai]
4System.out.println(zdt2);	//2021-10-14T23:37:05.565490300-04:00[America/New_York]

打印的时间不同,但是属于同一时刻

转换

java
1// 以中国时区获取当前时间:
2ZonedDateTime zbj = ZonedDateTime.now(ZoneId.of("Asia/Shanghai"));
3// 转换为纽约时间:
4ZonedDateTime zny = zbj.withZoneSameInstant(ZoneId.of("America/New_York"));
5System.out.println(zbj);
6System.out.println(zny);

时间工具类

java
  1public class NewDateUtil {
  2    private NewDateUtil(){}
  3    /**
  4     * 获得当前时刻
  5     */
  6    public static String getCurrentDateTime(String format) {
  7        if (Objects.isNull(format)||format.length()==0){
  8            format=TimeFormat.DEFAULT_FORMAT.format;
  9        }
 10        DateTimeFormatter f = DateTimeFormatter.ofPattern(format);
 11        return LocalDateTime.now().format(f);
 12    }
 13
 14    /**
 15     * 时间转换为字符串,如果转换格式为空使用默认格式
 16     */
 17    public static String dateToStr(LocalDateTime date, String format) {
 18        if (format==null||format.length()==0){
 19            format= TimeFormat.DEFAULT_FORMAT.format;
 20        }
 21        DateTimeFormatter f = DateTimeFormatter.ofPattern(format);
 22        return f.format(date);
 23    }
 24
 25    /**
 26     * 时间转换为字符串,如果转换格式为空使用默认格式
 27     */
 28    public static String dateToStr(LocalDate date, String format) {
 29        if (format==null||format.length()==0){
 30            format= TimeFormat.DEFAULT_FORMAT.format;
 31        }
 32        DateTimeFormatter f = DateTimeFormatter.ofPattern(format);
 33        return f.format(date);
 34    }
 35
 36    /**
 37     * 时间转换为字符串,如果转换格式为空使用默认格式
 38     */
 39    public static String dateToStr(LocalTime date, String format) {
 40        if (format==null||format.length()==0){
 41            format= TimeFormat.DEFAULT_FORMAT.format;
 42        }
 43        DateTimeFormatter f = DateTimeFormatter.ofPattern(format);
 44        return f.format(date);
 45    }
 46
 47    /**
 48     * 字符串转换为时间,如果转换格式为空使用默认格式
 49     */
 50    public static LocalDateTime strToDateTime(String dateTime, String format) throws Exception {
 51        if (format==null||format.length()==0){
 52            format= TimeFormat.DEFAULT_FORMAT.format;
 53        }
 54        DateTimeFormatter f = DateTimeFormatter.ofPattern(format);;
 55        return LocalDateTime.parse(dateTime,f);
 56    }
 57
 58    /**
 59     * 字符串转换为日期,如果转换格式为空使用默认格式
 60     */
 61    public static LocalDate strToDate(String dateTime, String format) throws Exception {
 62        if (format==null||format.length()==0){
 63            format= TimeFormat.YYYY_MM_DD_LINE.format;
 64        }
 65        DateTimeFormatter f = DateTimeFormatter.ofPattern(format);;
 66        return LocalDate.parse(dateTime,f);
 67    }
 68
 69    /**
 70     * 字符串转换为日期,如果转换格式为空使用默认格式
 71     */
 72    public static LocalTime strToTime(String dateTime, String format) throws Exception {
 73        if (format==null||format.length()==0){
 74            format= TimeFormat.HH_MM_SS_COLON.format;
 75        }
 76        DateTimeFormatter f = DateTimeFormatter.ofPattern(format);;
 77        return LocalTime.parse(dateTime,f);
 78    }
 79
 80    /**
 81     * 时间包括在某个时间段内
 82     */
 83    public static Boolean timeInclude(LocalDateTime checkTime, LocalDateTime begntime, LocalDateTime endtime) {
 84        if(begntime!=null&&endtime!=null){
 85            return checkTime.isAfter(begntime)&&checkTime.isBefore(endtime);
 86        }
 87        return false;
 88    }
 89
 90    /**
 91     * 时间包括在某个时间段内
 92     */
 93    public static Boolean timeInclude(LocalDate checkTime, LocalDate begntime, LocalDate endtime) {
 94        if(begntime!=null&&endtime!=null){
 95            return checkTime.isAfter(begntime)&&checkTime.isBefore(endtime);
 96        }
 97        return false;
 98    }
 99
100    /**
101     * 时间包括在某个时间段内
102     */
103    public static Boolean timeInclude(LocalTime checkTime, LocalTime begntime, LocalTime endtime) {
104        if(begntime!=null&&endtime!=null){
105            return checkTime.isAfter(begntime)&&checkTime.isBefore(endtime);
106        }
107        return false;
108    }
109
110    /**
111     * 时间大小比较
112     * 大于返回 1、小于返回 -1、等于返回 0
113     */
114    public static int checkTime(LocalDateTime left, LocalDateTime right) {
115        return left.compareTo(right);
116    }
117
118    /**
119     * 时间大小比较
120     * 大于返回 1、小于返回 -1、等于返回 0
121     */
122    public static int checkTime(LocalDate left, LocalDate right) {
123        return left.compareTo(right);
124    }
125
126    /**
127     * 时间大小比较
128     * 大于返回 1、小于返回 -1、等于返回 0
129     */
130    public static int checkTime(LocalTime left, LocalTime right) {
131        return left.compareTo(right);
132    }
133
134    /**
135     * 将月数转换成年数
136     */
137    public static double monthToYear(int month) {
138        return month / 12D;
139    }
140
141    /**
142     * 时间戳转换为字符串
143     */
144    public static String timestamp2Str(Long time) {
145        LocalDateTime date = null;
146        if (null != time) {
147            date = LocalDateTime.ofEpochSecond(time/1000, 0, ZoneOffset.ofHours(8));
148        }
149        return dateToStr(date, TimeFormat.DEFAULT_FORMAT.format);
150    }
151
152    /**
153     * 字符串转化为时间戳(毫秒)
154     */
155    public static Long str2Timestamp(String str) throws Exception {
156        LocalDateTime date = strToDateTime(str, TimeFormat.DEFAULT_FORMAT.format);
157        return date.toInstant(OffsetDateTime.now().getOffset()).getEpochSecond();
158//        return date.toInstant(ZoneOffset.ofHours(8)).toEpochMilli();
159    }
160
161    /**
162     * 计算日期之间相差天数
163     */
164    public static long getBetweenDays(LocalDateTime date1, LocalDateTime date2) {
165        return Math.abs(date1.toLocalDate().toEpochDay()-date2.toLocalDate().toEpochDay());
166    }
167
168    /**
169     * 时间转换为整数
170     */
171    public static Integer date2Integer(LocalDateTime date, String format) {
172        String str = dateToStr(date, format);
173        return Integer.valueOf(str);
174    }
175
176    /**
177     * 计算到指定时间的年龄
178     */
179    public static int getAge(LocalDateTime birthDay, LocalDateTime endDate) {
180        int age = 0;
181        if (birthDay.isAfter(endDate)){
182            return -1;
183        }
184        // 初步,估算
185        age = endDate.getYear() - birthDay.getYear();
186
187        // 如果未到出生月份,则age - 1
188        if (endDate.getMonth().compareTo(birthDay.getMonth()) < 0) {
189            age -= 1;
190        }
191        if (age < 0) { // age小于0,未满一岁
192            age = 0;
193        }
194        return age;
195    }
196
197    /**
198     * 验证字符串日期格式
199     */
200    public static boolean ValidateDate(String str, NewDateUtil.TimeFormat timeFormat){
201        //日期的正则表达式
202        return str.matches(timeFormat.regExp);
203    }
204
205    enum TimeFormat{
206        HH_MM_SS_COLON ("HH:mm:ss","^([01][0-9]|2[0-3]):[0-5][0-9]:([0-5][0-9]|60)$") ,
207        HH_MM_SS_MILSEC_COLON("HH:mm:ss.SSS","^([01][0-9]|2[0-3]):[0-5][0-9]:([0-5][0-9]|60).\\d{1,3}$"),
208        HH_MM_SS_CHINESE ("HH时mm分ss秒","^([01][0-9]|2[0-3])时[0-5][0-9]分([0-5][0-9]|60)秒$"),
209        YYYY_MM_DD_CHINESE("yyyy年MM月dd日","^[1-9]\\d{3}年(0[1-9]|1[0-2])月(0[1-9]|[1-2][0-9]|3[0-1])日$"),
210        YYYY_MM_DD_LINE("yyyy-MM-dd","^[1-9]\\d{3}-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1])$"),
211        YYYY_MM_DD_SLASH("yyyy/MM/dd","^[1-9]\\d{3}/(0[1-9]|1[0-2])/(0[1-9]|[1-2][0-9]|3[0-1])$"),
212        YYYY_MM_DD_BACKSLASH("yyyy\\MM\\dd","^[1-9]\\d{3}\\(0[1-9]|1[0-2])\\(0[1-9]|[1-2][0-9]|3[0-1])$"),
213        YYYY_MM_DD_NONE("yyyyMMdd","^[1-9]\\d{3}(0[1-9]|1[0-2])(0[1-9]|[1-2][0-9]|3[0-1])$"),
214        YYYY_MM("yyyyMM","^[1-9]\\d{3}(0[1-9]|1[0-2])$"),
215        YYYY("yyyy","^[1-9]\\d{3}$"),
216        YYYY_MM_DD_HH_MM_SS_CHINESE("yyyy年MM月dd日 HH时mm分ss秒","^[1-9]\\d{3}年(0[1-9]|1[0-2])月(0[1-9]|[1-2][0-9]|3[0-1])日 ([01][0-9]|2[0-3])时[0-5][0-9]分([0-5][0-9]|60)秒$"),
217        YYYY_MM_DD_HH_MM_SS_LINE("yyyy-MM-dd HH:mm:ss","^[1-9]\\d{3}-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1]) ([01][0-9]|2[0-3]):[0-5][0-9]:([0-5][0-9]|60)$"),
218        YYYY_MM_DD_HH_MM_SS_SLASH("yyyy/MM/dd HH:mm:ss","^[1-9]\\d{3}/(0[1-9]|1[0-2])/(0[1-9]|[1-2][0-9]|3[0-1]) ([01][0-9]|2[0-3]):[0-5][0-9]:([0-5][0-9]|60)$"),
219        YYYY_MM_DD_HH_MM_SS_BACKSLASH("yyyy\\MM\\dd HH:mm:ss","^[1-9]\\d{3}\\(0[1-9]|1[0-2])\\(0[1-9]|[1-2][0-9]|3[0-1]) ([01][0-9]|2[0-3]):[0-5][0-9]:([0-5][0-9]|60)$"),
220        YYYY_MM_DD_HH_MM_SS_NONE("yyyyMMdd HH:mm:ss","^[1-9]\\d{3}(0[1-9]|1[0-2])(0[1-9]|[1-2][0-9]|3[0-1]) ([01][0-9]|2[0-3]):[0-5][0-9]:([0-5][0-9]|60)$"),
221        YYYY_MM_DD_HH_MM_SS_BUS("yyyyMMddHHmmss","^[1-9]\\d{3}(0[1-9]|1[0-2])(0[1-9]|[1-2][0-9]|3[0-1])([01][0-9]|2[0-3])[0-5][0-9]([0-5][0-9]|60)$"),
222        YYYY_MM_DD_HH_MM_SS_MILSEC_LINE("yyyy-MM-dd HH:mm:ss.SSS","^[1-9]\\d{3}-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1]) ([01][0-9]|2[0-3]):[0-5][0-9]:([0-5][0-9]|60).\\d{1,3}$"),
223        YYYY_MM_DD_HH_MM_SS_MILSEC_SLASH("yyyy/MM/dd HH:mm:ss.SSS","^[1-9]\\d{3}/(0[1-9]|1[0-2])/(0[1-9]|[1-2][0-9]|3[0-1]) ([01][0-9]|2[0-3]):[0-5][0-9]:([0-5][0-9]|60).\\d{1,3}$"),
224        YYYY_MM_DD_HH_MM_SS_MILSEC_BACKSLASH("yyyy\\MM\\dd HH:mm:ss.SSS","^[1-9]\\d{3}\\(0[1-9]|1[0-2])\\(0[1-9]|[1-2][0-9]|3[0-1]) ([01][0-9]|2[0-3]):[0-5][0-9]:([0-5][0-9]|60).\\d{1,3}$"),
225        YYYY_MM_DD_HH_MM_SS_MILSEC_NONE("yyyyMMdd HH:mm:ss.SSS","^[1-9]\\d{3}(0[1-9]|1[0-2])(0[1-9]|[1-2][0-9]|3[0-1]) ([01][0-9]|2[0-3]):[0-5][0-9]:([0-5][0-9]|60).\\d{1,3}$"),
226        DEFAULT_FORMAT("yyyy-MM-dd HH:mm:ss","^[1-9]\\d{3}-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1]) ([01][0-9]|2[0-3]):[0-5][0-9]:([0-5][0-9]|60)$");
227        TimeFormat(String format, String regExp) {
228            this.format = format;
229            this.regExp = regExp;
230        }
231        final String format;
232        final String regExp;
233    }
234}

Spring中日期处理

实体类Date类型是属于util包下

也可以使用jdk1.8 的 LocalDateTime LocalDate类型

jackson出参格式化(序列化)

出参格式化指的是,往前端传递参数时;spring 使用 json 工具将时间转换为怎么样的 json 串

格式化配置

优先级:@JsonFormat > ObjectMapper > properties配置

  • 提供一个自定义的ObjectMapper bean,全局生效

    java
     1@Bean
     2ObjectMapper objectMapper() {
     3    return new Jackson2ObjectMapperBuilder()
     4        .findModulesViaServiceLoader(true)
     5        //date 序列化格式
     6        .dateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"))
     7        .timeZone("GMT+8")
     8        //配置给定类型 序列化
     9        .serializerByType(LocalDateTime.class, new LocalDateTimeSerializer(
    10            DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")))
    11        //配置给定类型 反序列化
    12        .deserializerByType(LocalDateTime.class, new LocalDateTimeDeserializer(
    13            DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")))
    14        .serializerByType(LocalTime.class, new LocalTimeSerializer(
    15            DateTimeFormatter.ofPattern("HH:mm:ss")))
    16        .deserializerByType(LocalTime.class, new LocalTimeDeserializer(
    17            DateTimeFormatter.ofPattern("HH:mm:ss")))
    18        .build();
    19}
  • 字段添加注解

    java
    1@JsonFormat(pattern = "yyyy-MM-dd",timezone = "GMT+8")
    2private LocalDateTime createTime;
    3@JsonFormat(pattern = "yyyy-MM-dd",timezone = "GMT+8")
    4private Date ontDate;
  • 配置文件配置,注意 不会针对LocalDateTime不会生效

    properties
    1spring.jackson.date-format=yyyy-MM-dd HH:mm:ss
    2spring.jackson.time-zone=GMT+8

Date

默认格式化为:yyyy-MM-dd'T'HH:mm:ss.SSSXXX

LocalDate系列

默认格式化:

  • LocalDateTime:yyyy-MM-dd'T'HH:mm:ss.SSSXXX
  • LocalDate:yyyy-MM-dd
  • LocalTime:HH:mm:ss.SSSXXX

Fastjson出参格式化(序列化)

格式化配置

  • 全局配置

    java
    1fastJsonConfig.setDateFormat("yyy-MM-dd HH:ss");
  • 字段添加注解

    java
    1// 字段注解两个都可以
    2@JsonFormat(pattern = "yyyy-MM-dd HH")
    3@JSONField(format = "yyyy-MM-dd HH")

Date

默认格式为:yyyy-MM-dd HH:mm:ss

LocalDate系列

  • LocalDateTime:yyyy-MM-dd HH:mm:ss
  • LocalDate:yyyy-MM-dd HH:mm:ss 时间为00:00:00
  • LocalTime:yyyy-MM-dd HH:mm:ss 年为:1970-01-01

入参格式化

注意:param传递接收时间参数时:使用@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") 匹配前端传参可能匹配更多,但不能匹配更少,否则会报404;

例:@DateTimeFormat(pattern = "yyyy-MM-dd") 前台传参为2021-12-31 12:21:21会报错;@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")前台传参为2021-12-31不会报错

java
1//form表单方式传值
2@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
3private Date create_time;
  1. 使用param传递接收时间参数时,不管什么格式,后台必须使用@DateTimeFormat注解才可以接收
  2. 使用body传递接收时间参数时,后台默认接收yyyy-MM-dd HH:mm:ss格式的参数,并转换为date对象,其他格式时需要使用@JsonFormat注解才可以接收
使用滚轮缩放
按住拖动