01-date

1. mysql

1. date_format()

select now();

-- 24小时制 (2024-03-22 07:49:47)
select date_format(now(), '%Y-%m-%d %T');

-- 24小时制 (2024-03-22 07:49:47)
select date_format(now(), '%Y-%m-%d %H:%i:%s');

-- 05:06:07 (24小时制)
select date_format('2000-05-07 13:06:07', '%H:%i:%s');

-- 05:06:07 (12小时制)
select date_format('2000-05-07 13:06:07', '%h:%i:%s');



 









格式描述格式描述
%a缩写星期名%pAM 或 PM
%b缩写月名%r时间,12-小时(hh:mm:ss AM 或 PM)
%c月,数值%S秒(00-59)
%D带有英文前缀的月中的天%s秒(00-59)
%d月的天,数值(00-31)%T时间, 24-小时 (hh:mm:ss)
%e月的天,数值(0-31)%U周 (00-53) 星期日是一周的第一天
%f微秒%u周 (00-53) 星期一是一周的第一天
%H小时 (00-23)%V周 (01-53) 星期日是一周的第一天,与 %X 使用
%h小时 (01-12)%v周 (01-53) 星期一是一周的第一天,与 %x 使用
%I小时 (01-12)%W星期名
%i分钟,数值(00-59)%w周的天 (0=星期日, 6=星期六)
%j年的天 (001-366)%X年,其中的星期日是周的第一天,4 位,与 %V 使用
%k小时 (0-23)%x年,其中的星期一是周的第一天,4 位,与 %v 使用
%l小时 (1-12)%Y年,4 位
%M月名%y年,2 位
%m月,数值(00-12)

2. between_and

# between_and 包含边界 (b <= x <= a)

# 1. '2024-04-09' 默认是 '2024-04-09 00:00:00'

# 2. (date, datetime, timestamp) 最大处理精度为(年-月-日)

# 3. 当月
select *
from tmp
where updtime like '2024-04-08%';

select *
from tmp
where date_format(updtime, '%Y-%m') like '2024-04';

# 4. 月末日期
select last_day(now()); # 2024-04-30

# 5. 月初日期
select date_format(now(), '%Y-%m-01');

# 6. 区间范围 updtime = 2024-04-08 01:16:42

# 查不到
select *
from tmp
where updtime between '2024-04-07 01:16:42' and '2024-04-08';

# 精确范围
select *
from tmp
where updtime between '2024-04-07 01:16:42' and '2024-04-08 23:59:59';

# 只查日期
select *
from tmp
where date(updtime) between '2024-04-07' and '2024-04-08';
















 


 











 




 

2. java

1. 当前日期、时间

// 当前时间
Date date = DateUtil.date();
// 当前时间
Date date2 = DateUtil.date(Calendar.getInstance());
// 当前时间
Date date3 = DateUtil.date(System.currentTimeMillis());

// 当前时间字符串。yyyy-MM-dd HH:mm:ss
String now = DateUtil.now();
// 当前日期字符串。yyyy-MM-dd
String today = DateUtil.today();








 

 

2. 字符串转日期

DateUtil.parse()会自动识别一些常用格式:

  • yyyy-MM-dd HH:mm:ss
  • yyyy/MM/dd HH:mm:ss
  • yyyy.MM.dd HH:mm:ss
  • yyyy年MM月dd日 HH时mm分ss秒
  • yyyy-MM-dd
  • yyyy/MM/dd
  • yyyy.MM.dd
  • HH:mm:ss
  • HH时mm分ss秒
  • yyyy-MM-dd HH:mm
  • yyyy-MM-dd HH:mm:ss.SSS
  • yyyyMMddHHmmss
  • yyyyMMddHHmmssSSS
  • yyyyMMdd
  • EEE, dd MMM yyyy HH:mm:ss z
  • EEE MMM dd HH:mm:ss zzz yyyy
  • yyyy-MM-dd'T'HH:mm:ss'Z'
  • yyyy-MM-dd'T'HH:mm:ss.SSS'Z'
  • yyyy-MM-dd'T'HH:mm:ssZ
  • yyyy-MM-dd'T'HH:mm:ss.SSSZ
image-20230911100408180
String dateStr = "2017-03-01";
Date date = DateUtil.parse(dateStr);

// 自定义日期格式转化
String dateStr = "2017-03-01";
Date date = DateUtil.parse(dateStr, "yyyy-MM-dd");





 

3. 日期转字符串

// 2017/03/01
String format = DateUtil.format(new Date(), "yyyy/MM/dd");

String format = DateUtil.format(new Date(), "yyyy-MM-ddHH:mm:ss");

// yyyy-MM-dd
String format = DateUtil.format(new Date(), DatePattern.NORM_DATE_PATTERN);

// ------------------------------------------------------------------

// 2017-03-01 00:00:00
String formatDateTime = DateUtil.formatDateTime(date);

// 2017-03-01
String formatDate = DateUtil.formatDate(date);

// 00:00:00
String formatTime = DateUtil.formatTime(date);











 


 



4. Date对象的某个部分

Date date = DateUtil.date();

// 年
DateUtil.year(date);

// 月份,从0开始计数
DateUtil.month(date);

// 月份枚举
DateUtil.monthEnum(date);

// 年中第几天
int x = DateUtil.dayOfYear(date);

// 月中第几天
int y = DateUtil.dayOfMonth(date);

// 星期中第几天,星期日是第一天
int z = DateUtil.dayOfWeek(date);



 


 








 



5. 开始、结束时间

String dateStr = "2017-03-22 22:33:23";
Date date = DateUtil.parse(dateStr);

// 一天的开始 (2017-03-22 00:00:00)
Date beginOfDay = DateUtil.beginOfDay(date);
// 一天的结束 (2017-03-22 23:59:59)
Date endOfDay = DateUtil.endOfDay(date);

// 月初 (2017-03-01 00:00:00)
DateTime beginOfMonth = DateUtil.beginOfMonth(date);
// 月末 (2017-03-31 23:59:59)
DateTime endOfMonth = DateUtil.endOfMonth(date);

// 年初 (2017-01-01 00:00:00)
DateTime beginOfYear = DateUtil.beginOfYear(date);
// 年末 (2017-12-31 23:59:59)
DateTime endOfYear = DateUtil.endOfYear(date);




 




 




 


6. 日期时间偏移

  • 日期、时间的偏移指针,对某个日期 (+、-) 分、小时、天等等,进行日期变更
String dateStr = "2017-03-01 22:33:23";
Date date = DateUtil.parse(dateStr);

// 日期:2017-03-03 22:33:23
Date newDate = DateUtil.offset(date, DateField.DAY_OF_MONTH, 2);

// 日期:2017-03-04 22:33:23
DateTime newDate2 = DateUtil.offsetDay(date, 3);

// 小时:2017-03-01 19:33:23
DateTime newDate3 = DateUtil.offsetHour(date, -3);




 


 


 
  • 针对当前时间,提供了简化的偏移方法
// 昨天
DateUtil.yesterday()
// 明天
DateUtil.tomorrow()
// 上周
DateUtil.lastWeek()
// 下周
DateUtil.nextWeek()
// 上个月
DateUtil.lastMonth()
// 下个月
DateUtil.nextMonth()

7. 日期时间差

  • 相差天数、相差小时数
String dateStr1 = "2017-03-01 22:33:23";
Date date1 = DateUtil.parse(dateStr1);

String dateStr2 = "2017-04-01 23:33:23";
Date date2 = DateUtil.parse(dateStr2);

// 相差一个月,31天。相差24h是一天
long betweenDay = DateUtil.between(date1, date2, DateUnit.DAY);







 

8. 格式化时间差

  • 易读的时间差,eg:XX天XX小时XX分XX秒,此时使用DateUtil.formatBetween方法:
Date startDate = DateUtil.parse("2021-04-20 02:00:00");
Date endDate = DateUtil.parse("2021-04-21 05:10:25");

// Level.SECOND表示精确到秒
String formatBetween = DateUtil.formatBetween(startDate, endDate, BetweenFormatter.Level.SECOND);

// formatBetween: 1天3小时10分25秒
System.out.println("formatBetween = " + formatBetween);

// betweenMS:毫秒
String formatBetween = DateUtil.formatBetween(betweenMS, BetweenFormatter.Level.SECOND);




 





 

9. 星座和属相

// "摩羯座"
String zodiac = DateUtil.getZodiac(Month.JANUARY.getValue(), 19);

// "狗"
String chineseZodiac = DateUtil.getChineseZodiac(1994);

 


 

10. 日期范围

// 创建日期范围生成器
DateTime start = DateUtil.parse("2021-01-31 13:29:29");
DateTime end = DateUtil.parse("2021-05-31 13:29:10");
DateRange range = DateUtil.range(start, end, DateField.MONTH);
range.forEach(System.out::println);

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

// 区间 [2021-01-31 13:29:29, 2021-03-31 13:29:29]
List<DateTime> dateTimes = DateUtil.rangeToList(start, end, DateField.MONTH, 2);
System.out.println("dateTimes = " + dateTimes);

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

// 开始时间
DateRange startRange = DateUtil.range(DateUtil.parse("2017-01-01"), DateUtil.parse("2017-01-31"), DateField.DAY_OF_YEAR);
// 结束时间
DateRange endRange = DateUtil.range(DateUtil.parse("2017-01-31"), DateUtil.parse("2017-02-02"), DateField.DAY_OF_YEAR);

// 交集 [2017-01-31 00:00:00]
List<DateTime> rangeContains = DateUtil.rangeContains(startRange, endRange);
System.out.println("rangeContains = " + rangeContains);

System.out.println("----------------------- DateRange上一步影响了游标 ---------------------------");

// 差集 [2017-02-01 00:00:00, 2017-02-02 00:00:00]
List<DateTime> rangeNotContains = DateUtil.rangeNotContains(startRange, endRange);
System.out.println("rangeNotContains = " + rangeNotContains);



 





 










 





 

2021-01-31 13:29:29
2021-02-28 13:29:29
2021-03-31 13:29:29
2021-04-30 13:29:29
--------------------------------------------------
dateTimes = [2021-01-31 13:29:29, 2021-03-31 13:29:29]
--------------------------------------------------
rangeContains = [2017-01-31 00:00:00]
----------------------- DateRange上一步影响了游标 ---------------------------
rangeNotContains = []

11. 其它

// 年龄
int age = DateUtil.ageOfNow("1994-10-18");

// 是否闰年
boolean leapYear = DateUtil.isLeapYear(2017);

 


 

3. 常见问题

1. YYYY、yyyy区别

  • YYYY:当天所在的周属于的年份。一周从周日开始,周六结束,只要本周跨年,那么这周就算进入下一年
  • yyyy:四位年份
Calendar calendar = Calendar.getInstance();
calendar.set(2019, Calendar.DECEMBER, 31);
Date testDate = calendar.getTime();
SimpleDateFormat dtf = new SimpleDateFormat("YYYY-MM-dd");
// 2019-12-31 转`YYYY-MM-dd`格式后: 2020-12-31
System.out.println("2019-12-31 转`YYYY-MM-dd`格式后: " + dtf.format(testDate));

2. HH、hh区别

  • HH:24小时制
  • hh:12小时制。当时间为12点,处理为0点
String str = "2020-03-18 12:00";
SimpleDateFormat dtf = new SimpleDateFormat("yyyy-MM-dd hh:mm");
Date newDate = dtf.parse(str);
// Wed Mar 18 00:00:00 CST 2020
System.out.println("newDate = " + newDate);

3. SimleDateFormat

1. format初始化问题

  • 用format格式化日期是,要输入的是一个Date日期,而不是整型、字符串
SimpleDateFormat dtf = new SimpleDateFormat("yyyy-MM-dd");
String format = dtf.format(20200323);
// format = 1970-01-01
System.out.println("format = " + format);
Calendar calendar = Calendar.getInstance();
calendar.set(2020, Calendar.MARCH, 23);
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
String format = sdf.format(calendar.getTime());
System.out.println("format = " + format);



 

2. 线程不安全

  1. SimpleDateFormat定义为局部变量
  2. 使用ThreadLocal
  3. 方法加同步锁synchronized
  4. 直接使用DateTimeFromatter
public class SimpleDateFormatTest {

    private static final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

    public static void main(String[] args) {
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(10, 100, 1, TimeUnit.MINUTES, new LinkedBlockingQueue<>(1_000));

        while (true) {
            threadPoolExecutor.execute(() -> {
                String dateString = sdf.format(new Date());
                try {
                    Date parseDate = sdf.parse(dateString);
                    String dateString2 = sdf.format(parseDate);
                    System.out.println(dateString.equals(dateString2));
                } catch (ParseException e) {
                    e.printStackTrace();
                }
            });
        }

    }

}
Exception in thread "pool-1-thread-49" java.lang.NumberFormatException: For input string: "5151."
 at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
 at java.lang.Long.parseLong(Long.java:589)
 at java.lang.Long.parseLong(Long.java:631)
 at java.text.DigitList.getLong(DigitList.java:195)
 at java.text.DecimalFormat.parse(DecimalFormat.java:2051)
 at java.text.SimpleDateFormat.subParse(SimpleDateFormat.java:2162)
 at java.text.SimpleDateFormat.parse(SimpleDateFormat.java:1514)
 at java.text.DateFormat.parse(DateFormat.java:364)
 at com.example.demo.SimpleDateFormatTest.lambda$main$0(SimpleDateFormatTest.java:19)
 at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
 at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
 at java.lang.Thread.run(Thread.java:748)
Exception in thread "pool-1-thread-47" java.lang.NumberFormatException: For input string: "5151."
 at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
 at java.lang.Long.parseLong(Long.java:589)
 at java.lang.Long.parseLong(Long.java:631)
 at java.text.DigitList.getLong(DigitList.java:195)
 at java.text.DecimalFormat.parse(DecimalFormat.java:2051)
 at java.text.SimpleDateFormat.subParse(SimpleDateFormat.java:2162)
 at java.text.SimpleDateFormat.parse(SimpleDateFormat.java:1514)
 at java.text.DateFormat.parse(DateFormat.java:364)
 at com.example.demo.SimpleDateFormatTest.lambda$main$0(SimpleDateFormatTest.java:19)
 at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
 at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
 at java.lang.Thread.run(Thread.java:748)

4. DateTimeFormatter

DateTimeFormatter 这个类默认进行本地化设置,如果默认是中文,解析英文字符串就会报异常。可以传入一个本地化参数(Locale.US)解决

String dateStr = "Wed Mar 18 10:00:00 2020";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("EEE MMM dd HH:mm:ss yyyy", Locale.CHINA);
// DateTimeFormatter formatter = DateTimeFormatter.ofPattern("EEE MMM dd HH:mm:ss yyyy", Locale.US);
LocalDateTime dateTime = LocalDateTime.parse(dateStr, formatter);
System.out.println("dateTime = " + dateTime);

5. Calendar设置时间

Calendar.HOUR 默认是按12小时制处理

Calendar.HOUR_OF_DAY,才是按24小时处理

Calendar c = Calendar.getInstance();
c.set(Calendar.HOUR, 10);
// c.set(Calendar.HOUR_OF_DAY, 10);
// c.getTime() = Sun Mar 24 22:52:58 CST 2024
System.out.println("c.getTime() = " + c.getTime());

6. 日期计算

得到的日期居然比当前日期还要早,根本不是晚 30 天的时间。因为发生了int发生了溢出

Date today = new Date();
// int溢出
Date nextMonth = new Date(today.getTime() + 30 * 1_000 * 60 * 60 * 24);
System.out.println("nextMonth = " + nextMonth);
LocalDateTime now = LocalDateTime.now();
LocalDateTime localDateTime = now.plusDays(30);
System.out.println("localDateTime = " + localDateTime);

 

7. 夏令时问题

  • 夏令时,表示为了节约能源,人为规定时间的意思
  • 一般在天亮早的夏季人为将时间调快一小时,可以使人早起早睡,减少照明量,以充分利用光照资源,从而节约照明用电
  • 各个采纳夏时制的国家具体规定不同。目前全世界有近110个国家每年要实行夏令时
  • 1986年4月,中国中央有关部门发出“在全国范围内实行夏时制的通知”,具体作法是:每年从四月中旬第一个星期日的凌晨2时整(北京时间),将时钟拨快一小时。(1992年起,夏令时暂停实行)
  • 夏时令这几个时间可以注意一下:1986-05-04, 1987-04-12, 1988-04-10, 1989-04-16, 1990-04-15, 1991-04-14
TimeZone.setDefault(TimeZone.getTimeZone("Asia/Shanghai"));

SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

// Sun May 04 01:30:00 CDT 1986
System.out.println(sdf.parse("1986-05-04 00:30:00"));
  • 中国在1986-05-04当天还在使用夏令时,时间被拨快了1个小时。所以0点30分打印成了1点30分。修改时区为东8区
TimeZone.setDefault(TimeZone.getTimeZone("GMT+8"));

SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
System.out.println(sdf.parse("1986-05-04 00:30:00"));