JDK8之前的日期、时间 Date 代表日期和时间
代码案例 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 public static void main(String[] args) { // 创建一个Date对象,代表当前时间 Date date = new Date(); System.out.println(date); // 获取当前时间的毫秒值 long time = date.getTime(); System.out.println(time); // 创建一个Date对象,指定该对象代表的时间 time += 3 * 1000; Date date2 = new Date(time); System.out.println(date2); // 通过setTime指定Date对象的时间 Date date3 = new Date(); date3.setTime(time); System.out.println(date3); }
代码运行的结果如下
SimpleDateFormat类不是线程安全的:通过查看SimpleDateFormat类的源码,我们得知:SimpleDateFormat是继承自DateFormat类,DateFormat类中维护了一个全局的Calendar变量。*DateFormat类中的Calendar对象被多线程共享,而Calendar对象本身不支持线程安全。*
代表简单日期格式化,可以用来把日期对象、时间毫秒值格式化成我们想要的形式
将Date对象格式化成字符串 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 public static void main(String[] args) { // 创建一个Date对象,代表当前时间 Date date = new Date(); System.out.println(date); // 获取当前时间的毫秒值 long time = date.getTime(); System.out.println(time); // 创建SimpleDateFormat对象 SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss EEE a"); String ds1 = sdf.format(date); String ds2 = sdf.format(time); System.out.println(ds1); System.out.println(ds2); }
将字符串反序列化成Date对象 1 2 3 4 5 6 7 8 9 public static void main(String[] args) throws ParseException { // 定义一个日期字符串 String dateStr = "2024-10-11 15:22:22"; // 创建一个SimpleDateFormat对象 SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); Date date = sdf.parse(dateStr); System.out.println(date); }
Calendar 代表的是系统此刻时间对应的日历。
通过它可以单独获取、修改时间中的年、月、日、时、分、秒等。
Calendar的常用方法
代码示例 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 public static void main(String[] args) throws ParseException { // 得到当前系统时间的日历对象 Calendar now = Calendar.getInstance(); System.out.println(now); /** * 打印出来的信息如下 * java.util.GregorianCalendar * [time=1737430543014,areFieldsSet=true,areAllFieldsSet=true,lenient=true, * zone=sun.util.calendar.ZoneInfo[id="Asia/Shanghai",offset=28800000,dstSavings=0,useDaylight=false, * transitions=31,lastRule=null],firstDayOfWeek=1,minimalDaysInFirstWeek=1,ERA=1, * YEAR=2025,MONTH=0,WEEK_OF_YEAR=4,WEEK_OF_MONTH=4,DAY_OF_MONTH=21,DAY_OF_YEAR=21, * DAY_OF_WEEK=3,DAY_OF_WEEK_IN_MONTH=3,AM_PM=0,HOUR=11,HOUR_OF_DAY=11,MINUTE=35, * SECOND=43,MILLISECOND=14,ZONE_OFFSET=28800000,DST_OFFSET=0] */ // 获取日历中的某个信息 int year = now.get(Calendar.YEAR); int month = now.get(Calendar.MONTH); System.out.println(year); System.out.println(month); // 获取日历中的Date对象 Date time = now.getTime(); System.out.println(time); // 获取日期毫秒值 long timeInMillis = now.getTimeInMillis(); System.out.println(timeInMillis); // 修改日历中的某个信息 now.set(Calendar.YEAR, 2022); System.out.println(now); // 为某个信息增加或者减少多少 now.add(Calendar.YEAR, 10); System.out.println(now); now.add(Calendar.YEAR, -20); System.out.println(now); }
如果参数field不知道怎么填,可以将Calendar对象打印出来,参考其中的字段
注意:Calendar是一个可变对象,修改后对象本身表示的时间将发生变化
JDK8新增的日期、时间 LocalDate 代表本地日期:年、月、日、星期
获取日期相关的信息 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 public static void main(String[] args) { // 获取LocalDate对象 LocalDate ld = LocalDate.now(); // 获取对象中的信息 int year = ld.getYear(); // 年 int month = ld.getMonthValue(); // 月 int day = ld.getDayOfMonth(); // 日 int dayOfWeek = ld.getDayOfWeek().getValue();// 星期几 int dayOfYear = ld.getDayOfYear();// 一年中的第几天 System.out.println(year); System.out.println(month); System.out.println(day); System.out.println(dayOfWeek); System.out.println(dayOfYear); }
直接修改某个信息 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 public static void main(String[] args) { // 获取LocalDate对象 LocalDate ld = LocalDate.now(); // 直接修改某个信息 LocalDate ld2 = ld.withYear(2098); LocalDate ld3 = ld2.withMonth(12); LocalDate ld4 = ld3.withDayOfMonth(31); LocalDate ld5 = ld4.withDayOfYear(1); // 可以看到是一个不可变对象,修改信息原对象的值没有改变 System.out.println(ld); System.out.println(ld2); System.out.println(ld3); System.out.println(ld4); System.out.println(ld5); }
把某个信息增加多少 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 public static void main(String[] args) { // 获取LocalDate对象 LocalDate ld = LocalDate.now(); // 把某个信息增加多少 LocalDate ld2 = ld.plusYears(2); System.out.println(ld2); LocalDate ld3 = ld2.plusMonths(2); System.out.println(ld3); LocalDate ld4 = ld3.plusDays(2); System.out.println(ld4); LocalDate ld5 = ld4.plusWeeks(10); System.out.println(ld5); }
把某个信息减少多少 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 public static void main(String[] args) { // 获取LocalDate对象 LocalDate ld = LocalDate.now(); // 把某个信息增加多少 LocalDate ld2 = ld.minusYears(2); System.out.println(ld2); LocalDate ld3 = ld2.minusMonths(2); System.out.println(ld3); LocalDate ld4 = ld3.minusDays(2); System.out.println(ld4); LocalDate ld5 = ld4.minusWeeks(10); System.out.println(ld5); }
获取指定日期的LocalDate对象 1 2 3 4 5 6 7 8 public static void main(String[] args) { // 获取指定日期的LocalDate对象 LocalDate ld1 = LocalDate.of(2020, 12, 21); System.out.println(ld1); LocalDate ld2 = LocalDate.of(2020, Month.FEBRUARY, 21); System.out.println(ld2); }
判断两个日期是否相等,在前还是在后 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 public static void main(String[] args) { // 获取指定日期的LocalDate对象 LocalDate ld1 = LocalDate.of(2020, 12, 21); System.out.println(ld1); LocalDate ld2 = LocalDate.of(2020, Month.FEBRUARY, 21); System.out.println(ld2); boolean f1 = ld1.equals(ld2); System.out.println(f1); boolean f2 = ld1.isAfter(ld2); System.out.println(f2); boolean f3 = ld1.isBefore(ld2); System.out.println(f3); }
LocalTime 代表本地时间:时、分、秒、纳秒
获取时间相关的信息 1 2 3 4 5 6 7 8 9 10 11 12 13 14 public static void main(String[] args) { LocalTime now = LocalTime.now(); System.out.println(now); // 获取时间相关的信息 int hour = now.getHour();// 小时 int minute = now.getMinute();// 分钟 int second = now.getSecond();// 秒 int nano = now.getNano();// 纳秒 System.out.println(hour); System.out.println(minute); System.out.println(second); System.out.println(nano); }
直接修改某个信息 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 public static void main(String[] args) { LocalTime now = LocalTime.now(); System.out.println(now); // 直接修改某个信息 LocalTime lt1 = now.withHour(1); System.out.println(lt1); LocalTime lt2 = lt1.withMinute(1); System.out.println(lt2); LocalTime lt3 = lt2.withSecond(1); System.out.println(lt3); LocalTime lt4 = lt3.withNano(1); System.out.println(lt4); }
把某个信息增加多少 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 public static void main(String[] args) { LocalTime now = LocalTime.now(); System.out.println(now); // 把某个信息增加多少 LocalTime lt1 = now.plusHours(1); System.out.println(lt1); LocalTime lt2 = now.plusMinutes(20); System.out.println(lt2); LocalTime lt3 = now.plusSeconds(200); System.out.println(lt3); }
把某个信息减少多少 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 public static void main(String[] args) { LocalTime now = LocalTime.now(); System.out.println(now); // 把某个信息减少多少 LocalTime lt1 = now.minusHours(1); System.out.println(lt1); LocalTime lt2 = now.minusMinutes(20); System.out.println(lt2); LocalTime lt3 = now.minusSeconds(200); System.out.println(lt3); }
获取指定时间的LocalTime对象 1 2 3 4 5 6 7 8 9 10 public static void main(String[] args) { LocalTime lt1 = LocalTime.of(10, 10, 10); System.out.println(lt1); LocalTime lt2 = LocalTime.of(20, 20, 20); System.out.println(lt2); LocalTime lt3 = LocalTime.of(20, 20, 20); System.out.println(lt3); }
判断两个时间是否相等,在前还是在后 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 public static void main(String[] args) { LocalTime lt1 = LocalTime.of(10, 10, 10); System.out.println(lt1); LocalTime lt2 = LocalTime.of(20, 20, 20); System.out.println(lt2); LocalTime lt3 = LocalTime.of(20, 20, 20); System.out.println(lt3); boolean f1 = lt2.equals(lt3); System.out.println(f1); boolean f2 = lt2.isAfter(lt1); System.out.println(f2); boolean f3 = lt2.isBefore(lt1); System.out.println(f3); }
LocalDateTime 代表本地日期、时间:年、月、日、星期、时、分、秒、纳秒
LocalDateTime大多数API与前面LocalDate,LocalTime一致
1 2 3 4 5 6 7 8 9 10 11 12 public static void main(String[] args) { // LocalDateTime与LocalDate,LocalTime的相互转换 LocalDateTime now = LocalDateTime.now(); LocalDate ld = now.toLocalDate(); LocalTime lt = now.toLocalTime(); System.out.println(ld); System.out.println(lt); LocalDateTime ldt = LocalDateTime.of(ld, lt); System.out.println(ldt); }
ZoneId 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 public static void main(String[] args) { // 获取当前的时区 ZoneId zoneId = ZoneId.systemDefault(); System.out.println(zoneId); // 获取Java支持的全部时区 Set<String> set = ZoneId.getAvailableZoneIds(); System.out.println(set); // 把某个时区ID封装成ZoneId对象 ZoneId zoneId1 = ZoneId.of("America/Los_Angeles"); System.out.println(zoneId1); // 获取某个时区的ZoneDateTime对象 ZonedDateTime now = ZonedDateTime.now(zoneId1); System.out.println(now); // 获取系统默认时区的ZoneDateTime对象 ZonedDateTime systemNow = ZonedDateTime.now(); System.out.println(systemNow); }
Instant 时间线上的某个时刻/时间戳 通过获取instant的对象可以拿到此刻的时间,该时间由两部分组成:从1970-01-01 00:00:00开始走到此刻的总秒数+不够1秒的纳秒数
1 2 3 4 5 6 7 8 9 10 11 12 13 public static void main(String[] args) { // 获取当前时间的Instant对象 Instant now = Instant.now(); System.out.println(now); // 获取当前时间的从1970-1-1到现在的总秒数 long epochSecond = now.getEpochSecond(); System.out.println(epochSecond); // 获取不到一秒的纳秒 int nano = now.getNano(); System.out.println(nano); }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 public static void main(String[] args) { // 得到DateTimeFormatter对象 DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); LocalDateTime now = LocalDateTime.now(); // 第一种写法 String rs = formatter.format(now); System.out.println(rs); // 第二种写法 String rs2 = now.format(formatter); System.out.println(rs2); // 解析时间字符串 String dateStr = "2024-11-23 10:10:10"; LocalDateTime date = LocalDateTime.parse(dateStr, formatter); System.out.println(date); }
Period 计算日期间隔
可以用于计算两个LocalDate对象相差的年数、月数、天数。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 public static void main(String[] args) { // 得到两个日期 LocalDate ld1 = LocalDate.of(2024, 1, 1); LocalDate ld2 = LocalDate.of(2024, 6, 11); // 得到Period对象 Period p = Period.between(ld1, ld2); // 计算相隔几年 int years = p.getYears(); System.out.println(years); // 计算相隔几月 int months = p.getMonths(); System.out.println(months); // 计算相隔几日 int days = p.getDays(); System.out.println(days); }
Duration 计算时间间隔
可以用于计算两个时间对象相差的天数、小时数、分数、秒数、纳秒数;支持LocalTime、LocalDateTime、Instant等时间
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 public static void main(String[] args) { // 得到两个LocalDateTime对象 LocalDateTime ldt1 = LocalDateTime.of(2024, 11, 12, 1, 2, 3); LocalDateTime ldt2 = LocalDateTime.of(2024, 12, 1, 8, 12, 55); // 得到Duration对象 Duration duration = Duration.between(ldt1, ldt2); // 计算相隔多少天 long days = duration.toDays(); System.out.println(days); // 计算相隔多少小时 long hours = duration.toHours(); System.out.println(hours); // 计算相隔多少分 long minutes = duration.toMinutes(); System.out.println(minutes); // 计算相隔多少秒 long seconds = duration.getSeconds(); System.out.println(seconds); // 计算相隔多少毫秒 long millis = duration.toMillis(); System.out.println(millis); // 计算相隔多少纳秒 long nanos = duration.toNanos(); System.out.println(nanos); }
时间单位 ChronoUnit JDK 8引入了java.time.temporal.ChronoUnit
枚举类来表示时间单位,这个类定义了一组用于日期和时间计算的标准单位。这些单位可以用来加减时间、计算两个日期或时间之间的差异等。以下是ChronoUnit
中一些常见的枚举值:
NANOS
:表示纳秒(十亿分之一秒)。
MICROS
:表示微秒(百万分之一秒)。
MILLIS
:表示毫秒(千分之一秒)。
SECONDS
:表示秒。
MINUTES
:表示分钟。
HOURS
:表示小时。
HALF_DAYS
:表示半天(12小时)。
DAYS
:表示天。
WEEKS
:表示周。
MONTHS
:表示月。
YEARS
:表示年。
DECADES
:表示十年。
CENTURIES
:表示世纪。
MILLENNIA
:表示千年。
ERAS
:表示纪元。
TimeUnit TimeUnit
是 Java 并发包 java.util.concurrent
中的一个枚举类,它提供了一种表示和操作时间单位的标准化方式。TimeUnit
枚举类中的每个实例都代表一种时间单位,如纳秒、微秒、毫秒、秒、分钟、小时和天等。这种设计不仅使代码更加清晰易读,还能够避免手动进行时间单位转换时可能出现的错误。
以下是 TimeUnit
中包含的一些常用的时间单位:
NANOSECONDS
:纳秒
MICROSECONDS
:微秒
MILLISECONDS
:毫秒
SECONDS
:秒
MINUTES
:分钟
HOURS
:小时
DAYS
:天
TimeUnit
提供了一些非常有用的方法来处理时间值,包括但不限于:
***\*convert(long sourceDuration, TimeUnit sourceUnit)\****
:将指定的时间量从一个时间单位转换为当前时间单位。
***\*toNanos(long duration)\****
, ***\*toMicros(long duration)\****
, ***\*toMillis(long duration)\****
, ***\*toSeconds(long duration)\****
, ***\*toMinutes(long duration)\****
, ***\*toHours(long duration)\****
, ***\*toDays(long duration)\****
:将给定时间单位的数量转换为相应的时间单位值(例如,将小时数转换为秒数)。
***\*sleep(long timeout)\****
:让当前正在执行的线程停留(“睡眠”)指定的时间量。这是对 Thread.sleep
方法的一种更可读的替代方案。
使用 TimeUnit
可以让你的代码更加直观地表达时间的概念,并且减少了由于手工计算时间单位转换而导致的错误。例如,如果你想让一个线程休眠2秒钟,可以使用 TimeUnit.SECONDS.sleep(2);
这样的代码,这比直接使用 Thread.sleep(2000);
更加明确和易于理解。