Java中日期 ¶
Java中日期 ¶
概念 ¶
本地时间
不同的时区,在同一时刻,本地时间是不同的。全球一共分为24个时区,伦敦所在的时区称为标准时区,其他时区按东/西偏移的小时区分,北京所在的时区是东八区。
时区
通过本地时间无法确定一个准确的时刻,所以需要添加时区
时区表示方式:
GMT或者UTC加时区偏移表示,基本等价,UTC使用了更加精确的原子钟计时;例:GMT+08:00或者UTC+08:00表示东八区- 缩写,缩写容易产生混淆,一般不使用;例如:
CST表示中国标准时间China Standard Time,也可以表示美国中部时间Central Standard Time USA - 洲/城市;例如:
Asia/Shanghai表示上海所在地的时区。特别注意城市名称不是任意的城市,而是由国际标准组织规定的城市
夏令时
夏令时,就是夏天开始的时候,把时间往后拨1小时,夏天结束的时候,再把时间往前拨1小时
涉及到夏令时,相同的时区如果表达方式不同,转换出来的时间是不同的,例如:
对于2019-11-20和2019-6-20两个日期来说,假设北京人在纽约:
- 如果以
GMT或者UTC作为时区,无论日期是多少,时间都是19:00; - 如果以国家/城市表示,例如
America/NewYork,虽然纽约也在西五区,但是,因为夏令时的存在,在不同的日期,GMT时间和纽约时间可能是不一样的

在程序中应统一配置:数据库服务器,JVM,JSON转化工具的时区为GMT+8,忽略夏令时的使用
注意:JSON转化工具和链接数据库设置的时区一定需要一致,否则可能出现多一个小时或者少一个小时的奇怪问题
本地化
计算机通过Locale来针对当地用户习惯格式化日期、时间、数字、货币等
Java.lang.Locale代表特定的地理、政治和文化。需要Locale来执行其任务的操作叫语言环境敏感的操作
构造一个系统默认的Locale:Locale defaultLocale = Locale.getDefault();
GMT+8 和 Asia/Shanghai 的区别 ¶
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:日历
- 生成时间 new Date ();格式化时间 (new SimpleDateFoamat).format (new Date ());
- 获取当前时间戳,System.currentTimeMillis ()
- Date–>String,日期格式化,SimpleDateFormat.format (日期对象);String–>Date,SimpleDateFormat.parse (“日期字符串”)
示例代码
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(时间) ¶
构造方法
- 无参构造:获取当前时间
- 有参构造:传入时间戳(毫秒),获取时间戳的时间
- 其余构造方法已经弃用
常用方法
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 返回 1Calendar(日历) ¶
创建对象
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()可以列出所有有效时区
常用方法
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小时时间工具类 ¶
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新引入 ¶
- 本地日期和时间:
LocalDateTime,LocalDate,LocalTime - 带时区的日期和时间:
ZonedDateTime - 时刻:
Instant - 时区:
ZoneId,ZoneOffset - 时间间隔:
Duration - 以及一套新的用于取代
SimpleDateFormat的格式化类型DateTimeFormatter
LocalDate和LocalTime ¶
基本使用
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相关转换
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理解成LocalDateTime加ZoneId。ZoneId是Java.time引入的新的时区类,注意和旧的Java.util.TimeZone区别。
基本使用
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]打印的时间不同,但是属于同一时刻
转换
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);时间工具类 ¶
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,全局生效
java1@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}字段添加注解
java1@JsonFormat(pattern = "yyyy-MM-dd",timezone = "GMT+8") 2private LocalDateTime createTime; 3@JsonFormat(pattern = "yyyy-MM-dd",timezone = "GMT+8") 4private Date ontDate;配置文件配置,注意 不会针对
LocalDateTime不会生效properties1spring.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出参格式化(序列化) ¶
格式化配置
全局配置
java1fastJsonConfig.setDateFormat("yyy-MM-dd HH:ss");字段添加注解
java1// 字段注解两个都可以 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不会报错
1//form表单方式传值
2@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
3private Date create_time;- 使用
param传递接收时间参数时,不管什么格式,后台必须使用@DateTimeFormat注解才可以接收 - 使用
body传递接收时间参数时,后台默认接收yyyy-MM-dd HH:mm:ss格式的参数,并转换为date对象,其他格式时需要使用@JsonFormat注解才可以接收