一篇文章带你学完Java所有的时间与日期类

目录

一、传统时间与日期类

1.Date类

构造方法

获取日期和时间信息的方法

 设置日期和时间信息的方法

2.Calendar类

主要特点和功能

 常用方法

1. 获取当前日历对象

2. 获取日历中的某个信息

3. 获取日期对象

4. 获取时间毫秒值

5. 修改日历的某个信息

6. 为某个信息增加或者减少值

3.SimpleDateFormat类

主要用途

构造函数

模式字符串

将日期格式化成日期与时间字符串

将时间毫秒值格式化成字符串

解析日期

示例

要点

注意事项

二、新旧替换

一、新增的时间与日期类及其替代的旧类

二、具体变化

三、总结

三、JDK8后新时间与日期类 

LocalDate

LocalTime

LocalDateTime

ZoneId

ZonedDateTime

Instant

Instant 的主要特点

Instant 的常见方法

代码示例

DateTimeFormatter

主要特点

常见用法

代码示例

Period

示例代码

Duration

示例代码


一、传统时间与日期类

    在JDK8之前,Java语言自带的日期时间类主要有java.util.Datejava.util.Calendarjava.text.SimpleDateFormat。这些类存在一系列问题,使得在编写代码时需要做出许多不必要的努力:

  1. java.util.Date:除了表示当前日期时间以外,其余所有方法都被视为已过时(deprecated),且不支持时区信息,也不是线程安全的。
  2. java.util.Calendar:虽然是一个比较全面的日期时间处理类,并且可以进行一些精度更高的计算,但由于设计不够合理,使得代码变得冗长和难以维护,同时也不是线程安全的。
  3. java.text.SimpleDateFormat:虽然可以将日期时间格式化为字符串,但它同样也不是线程安全的。

  如今仍有部分公司在使用这些时间与日期类部分内容,所以我们也有必要去了解一下。有的完全过时的内容这里就不在讲解。

1.Date类

    Java中的Date类是一个用于表示特定瞬间(精确到毫秒)的日期和时间的类。尽管从Java 9开始,Date类被标记为过时(deprecated),并且推荐使用新的日期时间API(如java.time包下的类),但了解Date类的常见方法仍然是有价值的。以下是Date类的一些常见方法:

构造方法

1.Date():创建一个表示当前日期和时间的Date对象(使用系统默认的时区和毫秒计时器)。

import java.util.Date;  
  
public class DateExample {  
    public static void main(String[] args) {  
        // 创建一个表示当前日期和时间的Date对象  
        Date now = new Date();  
          
        // 打印当前日期和时间(注意:输出格式依赖于JVM的实现)  
        System.out.println("当前日期和时间(默认格式):" + now.toString());  
    }  
}

2.Date(long date):根据指定的毫秒数(自1970年1月1日00:00:00 GMT以来的毫秒数)创建一个Date对象。

import java.util.Date;  
  
public class DateExample {  
    public static void main(String[] args) {  
        // 定义一个表示特定时间点的毫秒数(例如,2023年1月1日00:00:00 GMT的毫秒数)  
        // 注意:这里只是一个示例值,实际值需要根据具体日期计算  
        long specificTimeMillis = 1672483200000L; // 假设这是正确的毫秒数  
          
        // 根据指定的毫秒数创建一个Date对象  
        Date specificDate = new Date(specificTimeMillis);  
          
        // 打印特定日期和时间(注意:输出格式依赖于JVM的实现)  
        System.out.println("特定日期和时间(默认格式):" + specificDate.toString());  
    }  
}
获取日期和时间信息的方法

getTime():返回自1970年1月1日00:00:00 GMT以来的毫秒数(即时间戳)。

import java.util.Date;  
  
public class DateExample {  
    public static void main(String[] args) {  
        // 创建一个表示当前日期和时间的Date对象  
        Date now = new Date();  
          
        // 获取当前日期和时间的毫秒数(时间戳)  
        long timestamp = now.getTime();  
          
        // 打印时间戳  
        System.out.println("当前时间戳(毫秒):" + timestamp);  
    }  
}
 设置日期和时间信息的方法

setTime(long time):设置Date对象表示的日期和时间,使用自1970年1月1日00:00:00 GMT以来的毫秒数。

import java.util.Date;  
  
public class DateExample {  
    public static void main(String[] args) {  
        // 创建一个Date对象  
        Date date = new Date();  
          
        // 打印原始日期和时间(默认格式)  
        System.out.println("原始日期和时间:" + date.toString());  
          
        // 定义一个新的时间戳(例如,某个特定时间点的毫秒数)  
        long newTimeMillis = 1672483200000L; // 假设这是另一个日期的毫秒数  
          
        // 设置Date对象表示的新日期和时间  
        date.setTime(newTimeMillis);  
          
        // 打印修改后的日期和时间(默认格式)  
        System.out.println("修改后的日期和时间:" + date.toString());  
    }  
}

2.Calendar类

Java中的Calendar类是一个抽象类,用于封装日历信息,如年、月、日、时、分、秒等,并提供操作这些字段的方法。

由于Calendar是抽象类,因此你不能直接实例化它。相反,你需要使用Calendar类的一个子类实例,通常是通过调用Calendar类的getInstance()静态方法获得的,该方法会返回一个Calendar对象,该对象是根据默认时区和语言环境初始化的。

主要特点和功能
  1. 抽象性Calendar是一个抽象类,不能直接实例化。
  2. 时区和语言环境Calendar提供了操作日历字段的方法,这些字段值基于特定的时区和语言环境。
  3. 字段值Calendar类使用整数来表示日历字段,如YEARMONTHDAY_OF_MONTHHOUR_OF_DAY等。注意,MONTH字段是从0开始的(0表示1月,11表示12月)。
  4. 字段操作:提供了获取(get)、设置(set)、增加(add)和滚动(roll)日历字段值的方法。
  5. 不可变性(某种程度上):虽然Calendar对象本身是可变的(即,你可以修改其字段值),但一旦你通过getTime()方法获得了一个Date对象,那么该Date对象是不可变的。
 常用方法
1. 获取当前日历对象

Calendar类是一个抽象类,不能直接实例化。通常,我们使用Calendar.getInstance()方法来获取一个当前日期和时间的Calendar实例,该实例使用了默认的时区和语言环境。

import java.util.Calendar;  
  
public class CalendarDemo {  
    public static void main(String[] args) {  
        // 获取当前日历对象  
        Calendar calendar = Calendar.getInstance();  
        System.out.println("当前日历对象:" + calendar.toString()); // 注意:toString()输出可能不直观  
    }  
}
2. 获取日历中的某个信息

你可以使用get(int field)方法来获取Calendar对象中的某个字段的值。字段常量(如YEARMONTHDAY_OF_MONTH等)定义在Calendar类中。

import java.util.Calendar;  
  
public class CalendarDemo {  
    public static void main(String[] args) {  
        Calendar calendar = Calendar.getInstance();  
          
        // 获取当前年份  
        int year = calendar.get(Calendar.YEAR);  
        System.out.println("当前年份:" + year);  
          
        // 获取当前月份(注意:月份是从0开始的)  
        int month = calendar.get(Calendar.MONTH) + 1;  
        System.out.println("当前月份:" + month);  
          
        // 获取当前日期  
        int day = calendar.get(Calendar.DAY_OF_MONTH);  
        System.out.println("当前日期:" + day);  
    }  
}
3. 获取日期对象

你可以使用getTime()方法从Calendar对象中获取一个Date对象,该对象表示Calendar的时间值。

import java.util.Calendar;  
import java.util.Date;  
  
public class CalendarDemo {  
    public static void main(String[] args) {  
        Calendar calendar = Calendar.getInstance();  
          
        // 获取Date对象  
        Date date = calendar.getTime();  
        System.out.println("当前日期和时间:" + date.toString());  
    }  
}
4. 获取时间毫秒值

Calendar类提供了getTimeInMillis()方法来获取当前时间相对于“纪元”(即1970年1月1日00:00:00.000 GMT)的毫秒数。

import java.util.Calendar;  
  
public class CalendarDemo {  
    public static void main(String[] args) {  
        Calendar calendar = Calendar.getInstance();  
          
        // 获取时间毫秒值  
        long timeInMillis = calendar.getTimeInMillis();  
        System.out.println("当前时间毫秒值:" + timeInMillis);  
    }  
}
5. 修改日历的某个信息

你可以使用set(int field, int value)方法来修改Calendar对象中的某个字段的值。

import java.util.Calendar;  
  
public class CalendarDemo {  
    public static void main(String[] args) {  
        Calendar calendar = Calendar.getInstance();  
          
        // 修改年份  
        calendar.set(Calendar.YEAR, 2024);  
          
        // 验证修改  
        System.out.println("修改后的年份:" + calendar.get(Calendar.YEAR));  
    }  
}
6. 为某个信息增加或者减少值

你可以使用add(int field, int amount)方法来给Calendar对象中的某个字段增加或减少指定的值。

import java.util.Calendar;  
  
public class CalendarDemo {  
    public static void main(String[] args) {  
        Calendar calendar = Calendar.getInstance();  
          
        // 给当前日期增加10天  
        calendar.add(Calendar.DAY_OF_MONTH, 10);  
          
        // 验证增加  
        System.out.println("10天后的日期:" + calendar.getTime().toString());  
          
        // 给当前年份减少1年  
        calendar.add(Calendar.YEAR, -1);  
          
        // 验证减少  
        System.out.println("减少1年后的年份:" + calendar.get(Calendar.YEAR));  
    }  
}

3.SimpleDateFormat类

SimpleDateFormat 类是 Java 中用于格式化和解析日期的一个非常强大的类。它允许你进行用户自定义的日期-时间格式。这个类继承自 DateFormat 抽象类,并实现了 Serializable 接口,这意呀着它可以被序列化以便在网络中传输或存储到文件系统中。

主要用途
  1. 格式化日期:将 Date 对象转换成符合特定模式的字符串。
  2. 解析日期:将符合特定模式的字符串转换成 Date 对象。
构造函数

SimpleDateFormat 类提供了多个构造函数,但最常用的一个接受一个模式字符串作为参数,这个字符串定义了日期的格式。

SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
模式字符串

模式字符串由字母和数字组成,每个字母代表日期或时间的一部分。以下是一些常用的模式字母:

  • y:年
  • M:月
  • d:日
  • H:小时(0-23)
  • m:分钟
  • s:秒
  • S:毫秒

例如,"yyyy-MM-dd HH:mm:ss" 是一个常见的日期时间模式,它表示格式为“年-月-日 时:分:秒”的字符串。

将日期格式化成日期与时间字符串

当你有一个 Date 对象,并希望将其格式化为包含日期和时间的字符串时,你可以这样做:

import java.text.SimpleDateFormat;  
import java.util.Date;  
  
public class SimpleDateFormatExample {  
    public static void main(String[] args) {  
        // 创建一个Date对象,这里以当前日期时间为例  
        Date date = new Date();  
  
        // 创建一个SimpleDateFormat实例,并指定日期时间格式为"yyyy-MM-dd HH:mm:ss"  
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");  
  
        // 使用format方法将Date对象格式化为字符串  
        String formattedDateTime = sdf.format(date);  
  
        // 输出格式化后的日期时间字符串  
        System.out.println(formattedDateTime); // 输出类似:2023-04-01 15:30:00  
    }  
}
将时间毫秒值格式化成字符串

时间毫秒值是自1970年1月1日00:00:00 UTC(协调世界时间)以来的毫秒数。要将这个时间毫秒值格式化为字符串,你首先需要将其转换为 Date 对象,然后使用 SimpleDateFormat 进行格式化。但实际上,SimpleDateFormat 的 format 方法也接受一个 long 类型的参数(即时间毫秒值),不过更常见的做法是先转换为 Date 对象,因为这样可以更清晰地表达你的意图。

不过,为了直接展示如何使用毫秒值,这里给出一个简化的例子:

import java.text.SimpleDateFormat;  
  
public class SimpleDateFormatMillisExample {  
    public static void main(String[] args) {  
        // 获取当前时间的毫秒值  
        long millis = System.currentTimeMillis();  
  
        // 创建一个SimpleDateFormat实例,并指定日期时间格式为"yyyy-MM-dd HH:mm:ss"  
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");  
  
        // 直接使用format方法和毫秒值来格式化时间(虽然不常见,但技术上可行)  
        // 注意:这里实际上是在内部将long类型的毫秒值转换为了Date对象,然后进行了格式化  
        String formattedDateTime = sdf.format(new Date(millis));  
  
        // 输出格式化后的日期时间字符串  
        System.out.println(formattedDateTime); // 输出类似:2023-04-01 15:30:00  
  
        // 或者,更直接地(如果你确定只需要毫秒值),但这样不会进行格式化  
        // System.out.println(millis); // 这将输出一个长整型数字,不是格式化的日期时间字符串  
    }  
}

在这个例子中,我们首先获取了当前时间的毫秒值,然后创建了一个 SimpleDateFormat 实例来指定我们想要的日期时间格式。尽管 format 方法直接接受一个 long 类型的参数在技术上不是直接可行的(因为 format 方法的重载版本接受的是 Object 类型,但实际上是期望一个 Date 或其子类的实例),但上面的代码通过 new Date(millis) 将毫秒值转换为了 Date 对象,然后进行了格式化。这是处理时间毫秒值时更常见和推荐的做法。

解析日期

解析日期是指将符合特定格式的字符串转换成 Date 对象的过程。在 SimpleDateFormat 中,你可以通过定义日期时间的模式(pattern)来指定这个字符串的格式。

示例

假设你有一个日期字符串 "2023-04-01",并且你知道这个字符串是以 "yyyy-MM-dd" 格式表示的(即年-月-日)。你可以使用 SimpleDateFormat 来解析这个字符串到 Date 对象。

import java.text.ParseException;  
import java.text.SimpleDateFormat;  
import java.util.Date;  
  
public class SimpleDateFormatExample {  
    public static void main(String[] args) {  
        // 定义日期字符串和日期格式  
        String dateString = "2023-04-01";  
        String dateFormat = "yyyy-MM-dd";  
  
        // 创建 SimpleDateFormat 实例  
        SimpleDateFormat sdf = new SimpleDateFormat(dateFormat);  
  
        try {  
            // 解析字符串到 Date 对象  
            Date date = sdf.parse(dateString);  
              
            // 输出 Date 对象(注意:直接输出 Date 对象可能不是很直观,因为 Date.toString() 使用的是默认格式)  
            System.out.println(date); // 输出类似于 Sat Apr 01 00:00:00 GMT 2023  
  
            // 如果需要按照特定格式输出,可以再次使用 SimpleDateFormat  
            System.out.println(sdf.format(date)); // 输出 2023-04-01  
  
        } catch (ParseException e) {  
            e.printStackTrace();  
            // 处理解析异常  
        }  
    }  
}
要点
  • 当使用 parse 方法时,如果字符串与指定的模式不匹配,会抛出 ParseException。因此,你需要处理这个异常。
  • 默认的 SimpleDateFormat 是不线程安全的。如果你在多线程环境中使用同一个 SimpleDateFormat 实例,可能会遇到并发问题。解决方法是为每个线程创建单独的 SimpleDateFormat 实例,或者使用 ThreadLocal 来管理它们。
  • 当你使用 SimpleDateFormat 格式化或解析日期时,请确保你的模式和字符串或 Date 对象相匹配,以避免意外错误。
  • Java 8 引入了新的日期和时间 API(位于 java.time 包中),这些API提供了更强大、灵活且线程安全的日期和时间处理能力。如果你正在使用 Java 8 或更高版本,建议考虑使用这些新的API。
注意事项
  • 线程安全性SimpleDateFormat 不是线程安全的。如果在多线程环境中使用相同的 SimpleDateFormat 实例,可能会出现并发问题。一个常见的解决方案是为每个线程创建单独的 SimpleDateFormat 实例,或者使用 ThreadLocal 来管理实例。
  • 时区:默认情况下,SimpleDateFormat 使用默认的时区和语言环境来格式化或解析日期。如果需要,可以使用 setTimeZone(TimeZone zone) 方法来设置时区。
  • 模式字符大小写:在模式中,某些字符的大小写是有意义的。例如,MM 表示月份,而 mm 表示分钟。

二、新旧替换

JDK8新增的时间与日期类相比以前的类,带来了显著的变化和改进。以下是对这些新增类及其替代的旧类以及具体变化的详细说明:

一、新增的时间与日期类及其替代的旧类

新增类替代的旧类(或功能)
LocalDatejava.util.Calendar(部分功能)
LocalTimejava.util.Calendar(部分功能)
LocalDateTimejava.util.Calendarjava.util.Date(部分功能)
Instant

java.util.Date(时间戳功能)

ZonedDateTimejava.util.Calendar(带时区功能)
DateTimeFormatterjava.text.SimpleDateFormat
Durationjava.util.concurrent.TimeUnit(部分功能)
Period

无直接替代,提供新的时间间隔表示

二、具体变化

  1. LocalDate
    • 替代了java.util.Calendar中处理日期的部分功能,但更加简洁和直观。
    • 表示一个具体的日期,如“2024-07-27”,不包含时间信息。
    • 提供了丰富的API来处理日期,如加减天数、月份、年份,以及比较日期等。
  2. LocalTime
    • 替代了java.util.Calendar中处理时间的部分功能。
    • 表示一个具体的时间,如“10:29:18”,不包含日期信息。
    • 提供了API来处理时间,如加减小时、分钟、秒等。
  3. LocalDateTime
    • 整合了LocalDateLocalTime的功能,表示一个具体的日期和时间,如“2024-07-27T10:29:18”。
    • 提供了更全面的API来处理日期和时间,包括加减日期、时间,以及比较等。
  4. Instant
    • 替代了java.util.Date中时间戳的功能,但更加精确(到纳秒)。
    • 表示一个具体的时间点,即时间线上的一个瞬时。
    • 提供了与ZonedDateTime等类进行转换的API,便于时区处理。
  5. ZonedDateTime
    • 替代了java.util.Calendar中处理带时区日期时间的部分功能,但更加完善。
    • 表示一个具体的带时区的日期时间,如“2024-07-27T10:29:18+08:00[Asia/Shanghai]”。
    • 提供了时区转换、加减日期时间等API。
  6. DateTimeFormatter
    • 替代了java.text.SimpleDateFormat,提供了更加强大和灵活的日期时间格式化功能。
    • 可以通过模式字符串来自定义日期时间的格式,也可以解析符合特定格式的字符串为日期时间对象。
  7. DurationPeriod
    • 这两个类提供了新的时间间隔表示方式。
    • Duration用于表示时间间隔,如“PT1H30M”(1小时30分钟)。
    • Period用于表示日期间隔,如“P2Y6M”(2年6个月)。

三、总结

JDK8新增的时间与日期类相比以前的类,在以下几个方面有了显著的变化:

  • 线程安全性:新类都是不可变的,因此它们是线程安全的。
  • 不可变性:一旦创建,新类的对象就不能被修改,这有助于防止意外的修改和并发问题。
  • 更清晰的API设计:新类提供了更直观、更易于理解的API,使得日期时间的处理更加简单和方便。
  • 更好的国际化支持:新类支持时区处理,并且遵循ISO 8601标准,使得日期时间的表示更加国际化。
  • 更精确的时间表示Instant类提供了纳秒级的时间精度,比旧的java.util.Date类更加精确。

三、JDK8后新时间与日期类 

LocalDate

LocalDate代表没有时区的日期,如年月日。

常见方法:

  • now(): 获取当前日期。
  • of(int year, int month, int dayOfMonth): 从年月日创建一个LocalDate
  • getYear(): 获取年份。
  • getMonth(): 获取月份,返回一个Month枚举。
  • getDayOfMonth(): 获取月份中的日。
  • plusDays(long days): 添加天数。
  • minusDays(long days): 减去天数。 
import java.time.LocalDate;  
  
public class LocalDateExample {  
    public static void main(String[] args) {  
        // 获取当前日期  
        LocalDate today = LocalDate.now();  
        System.out.println("Today's date: " + today);  
  
        // 通过年、月、日创建LocalDate实例  
        LocalDate specificDate = LocalDate.of(2023, 4, 1);  
        System.out.println("Specific date: " + specificDate);  
  
        // 加上天数  
        LocalDate nextWeek = specificDate.plusDays(7);  
        System.out.println("Next week: " + nextWeek);  
  
        // 减去月份  
        LocalDate previousMonth = specificDate.minusMonths(1);  
        System.out.println("Previous month: " + previousMonth);  
  
        // 获取年份、月份和月份中的天数  
        int year = specificDate.getYear();  
        int month = specificDate.getMonthValue();  
        int dayOfMonth = specificDate.getDayOfMonth();  
        System.out.println("Year: " + year + ", Month: " + month + ", Day: " + dayOfMonth);  
  
        // 格式化日期  
        String formattedDate = specificDate.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));  
        System.out.println("Formatted date: " + formattedDate);  
    }  
}

LocalTime

LocalTime代表没有日期的时间,如时分秒。

常见方法:

  • now(): 获取当前时间。
  • of(int hour, int minute, int second): 从时分秒创建一个LocalTime
  • getHour(): 获取小时。
  • getMinute(): 获取分钟。
  • getSecond(): 获取秒。
import java.time.LocalTime;  
  
public class LocalTimeExample {  
    public static void main(String[] args) {  
        // 获取当前时间  
        LocalTime now = LocalTime.now();  
        System.out.println("Current time: " + now);  
  
        // 通过小时、分钟、秒创建LocalTime实例  
        LocalTime specificTime = LocalTime.of(14, 30, 45);  
        System.out.println("Specific time: " + specificTime);  
  
        // 加上小时  
        LocalTime later = specificTime.plusHours(2);  
        System.out.println("Later time: " + later);  
  
        // 减去分钟  
        LocalTime earlier = later.minusMinutes(30);  
        System.out.println("Earlier time: " + earlier);  
  
        // 获取小时、分钟和秒  
        int hour = specificTime.getHour();  
        int minute = specificTime.getMinute();  
        int second = specificTime.getSecond();  
        System.out.println("Hour: " + hour + ", Minute: " + minute + ", Second: " + second);  
  
        // 格式化时间  
        String formattedTime = specificTime.format(DateTimeFormatter.ofPattern("HH:mm:ss"));  
        System.out.println("Formatted time: " + formattedTime);  
    }  
}

LocalDateTime

LocalDateTime代表没有时区的日期和时间。

常见方法:

  • now(): 获取当前的日期和时间。
  • of(LocalDate date, LocalTime time): 从LocalDateLocalTime创建一个LocalDateTime
  • getYear()getMonth()getDayOfMonth()getHour()getMinute()getSecond(): 获取日期和时间的各个部分。
import java.time.LocalDateTime;
import java.time.LocalDate;
import java.time.LocalTime;

public class LocalDateTimeExample {
    public static void main(String[] args) {
        LocalDateTime now = LocalDateTime.now();
        System.out.println("Current date and time: " + now);
        
        LocalDateTime specificDateTime = LocalDateTime.of(LocalDate.of(2024, 7, 27), LocalTime.of(13, 45, 20));
        System.out.println("Specific date and time: " + specificDateTime);
        
        int year = now.getYear();
        System.out.println("Year: " + year);
        
        int hour = now.getHour();
        System.out.println("Hour: " + hour);
    }
}

ZoneId

ZoneId是时区的标识符,它可以是诸如"Europe/Paris"的地理区域标识符,或者是像"UTC"这样的固定偏移量。

常见方法:

  • systemDefault(): 获取系统默认时区。
  • of(String zoneId): 从字符串创建一个ZoneId
  • getRules(): 获取与此ZoneId关联的时区规则。
  • normalized(): 返回规范化形式的ZoneId

示例代码:

import java.time.ZoneId;

public class ZoneIdExample {
    public static void main(String[] args) {
        // 获取系统默认时区
        ZoneId systemDefaultZoneId = ZoneId.systemDefault();
        System.out.println("System Default ZoneId: " + systemDefaultZoneId);
        
        // 从字符串创建一个ZoneId
        ZoneId zoneId = ZoneId.of("Europe/Paris");
        System.out.println("ZoneId of Europe/Paris: " + zoneId);
        
        // 获取时区规则
        ZoneId zoneRules = zoneId.getRules();
        System.out.println("Zone Rules: " + zoneRules);
        
        // 返回规范化形式的ZoneId
        ZoneId normalizedZoneId = zoneId.normalized();
        System.out.println("Normalized ZoneId: " + normalizedZoneId);
    }
}

ZonedDateTime

ZonedDateTime是一个包含日期和时间的类,同时关联了时区信息。

常见方法:

  • now(): 获取当前日期和时间,并附加系统默认时区。
  • now(ZoneId zone): 获取指定时区的当前日期和时间。
  • of(LocalDateTime dateTime, ZoneId zone): 从LocalDateTimeZoneId创建一个ZonedDateTime
  • withZoneSameLocal(ZoneId zone): 更改时区,保留本地日期和时间。
  • withZoneSameInstant(ZoneId zone): 更改时区,保留瞬间。
  • plusDays(long days): 添加天数。
  • minusDays(long days): 减去天数。
  • toLocalDate(): 获取本地日期。
  • toLocalTime(): 获取本地时间。
  • getZone(): 获取时区。
import java.time.ZonedDateTime;
import java.time.LocalDateTime;
import java.time.ZoneId;

public class ZonedDateTimeExample {
    public static void main(String[] args) {
        // 获取系统默认时区的当前日期和时间
        ZonedDateTime now = ZonedDateTime.now();
        System.out.println("Current date and time with system default timezone: " + now);
        
        // 获取指定时区的当前日期和时间
        ZonedDateTime nowInParis = ZonedDateTime.now(ZoneId.of("Europe/Paris"));
        System.out.println("Current date and time in Europe/Paris: " + nowInParis);
        
        // 从LocalDateTime和ZoneId创建一个ZonedDateTime
        LocalDateTime localDateTime = LocalDateTime.of(2024, 7, 27, 13, 45, 20);
        ZonedDateTime specificDateTime = ZonedDateTime.of(localDateTime, ZoneId.systemDefault());
        System.out.println("Specific date and time: " + specificDateTime);
        
        // 更改时区,保留本地日期和时间
        ZonedDateTime zonedDateTimeWithLocalTime = specificDateTime.withZoneSameLocal(ZoneId.of("Europe/Paris"));
        System.out.println("Specific date and time in Europe/Paris (same local time): " + zonedDateTimeWithLocalTime);
        
        // 更改时区,保留瞬间
        ZonedDateTime zonedDateTimeWithSameInstant = specificDateTime.withZoneSameInstant(ZoneId.of("Europe/Paris"));
        System.out.println("Specific date and time in Europe/Paris (same instant): " + zonedDateTimeWithSameInstant);
        
        // 添加天数
        ZonedDateTime plusDays = specificDateTime.plusDays(1);
        System.out.println("Specific date and time plus one day: " + plusDays);
        
        // 减去天数
        ZonedDateTime minusDays = specificDateTime.minusDays(1);
        System.out.println("Specific date and time minus one day: " + minusDays);
        
        // 获取本地日期
        LocalDate localDate = specificDateTime.toLocalDate();
        System.out.println("Local date: " + localDate);
        
        // 获取本地时间
        LocalTime localTime = specificDateTime.toLocalTime();
        System.out.println("Local time: " + localTime);
        
        // 获取时区
        ZoneId zone = specificDateTime.getZone();
        System.out.println("ZoneId: " + zone);
    }
}

Instant

Instant 类在 Java 中表示一个时间线上的一个瞬时点,它是以 Unix 时间戳(即自1970年1月1日UTC以来的秒数)为基础的,但精度更高,可以达到纳秒级别。Instant 是不带时区的,它表示的是全球统一的时间线上的一个点。

Instant 的主要特点
  • 精确到纳秒。
  • 不带时区信息,仅表示时间线上的一个点。
  • 可以用来表示时间戳,非常适合用于系统间的时间交互,因为它消除了时区带来的复杂性。
Instant 的常见方法
  • now(): 获取当前时间的 Instant 实例。
  • plus(TemporalQuery<? extends Temporal> query, long amount): 在 Instant 上加上指定的时间量。
  • minus(TemporalQuery<? extends Temporal> query, long amount): 从 Instant 上减去指定的时间量。
  • atZone(ZoneId zone): 将 Instant 转换为特定时区的 ZonedDateTime
  • toEpochMilli(): 将 Instant 转换为自1970年1月1日UTC以来的毫秒数(与 Unix 时间戳相似,但精度稍低)。
  • toEpochSecond(): 将 Instant 转换为自1970年1月1日UTC以来的秒数。
代码示例
import java.time.Instant;  
import java.time.ZoneId;  
import java.time.ZonedDateTime;  
  
public class InstantExample {  
    public static void main(String[] args) {  
        // 获取当前时间的 Instant 实例  
        Instant now = Instant.now();  
        System.out.println("Current instant: " + now);  
  
        // 将 Instant 转换为自1970年1月1日UTC以来的毫秒数  
        long epochMilli = now.toEpochMilli();  
        System.out.println("Epoch milli: " + epochMilli);  
  
        // 将 Instant 转换为自1970年1月1日UTC以来的秒数  
        long epochSecond = now.toEpochSecond();  
        System.out.println("Epoch second: " + epochSecond);  
  
        // 加上10秒  
        Instant tenSecondsLater = now.plusSeconds(10);  
        System.out.println("Ten seconds later: " + tenSecondsLater);  
  
        // 减去5分钟  
        Instant fiveMinutesEarlier = now.minusMinutes(5);  
        System.out.println("Five minutes earlier: " + fiveMinutesEarlier);  
  
        // 将 Instant 转换为特定时区的 ZonedDateTime  
        ZonedDateTime zdt = now.atZone(ZoneId.of("Asia/Shanghai"));  
        System.out.println("Shanghai time: " + zdt);  
    }  
}

DateTimeFormatter

主要特点
  • 自定义格式:可以定义几乎任何所需的日期时间格式。
  • 解析:将文本(通常是字符串)解析为日期时间对象。
  • 格式化:将日期时间对象格式化为文本(字符串)。
  • 本地化:支持使用不同的语言环境和地区设置来格式化日期时间。
常见用法
  1. 预定义格式DateTimeFormatter 提供了一些预定义的格式,如 ISO_LOCAL_DATEISO_LOCAL_TIMEISO_LOCAL_DATE_TIME 等。

  2. 自定义格式:使用 DateTimeFormatter.ofPattern(String pattern) 方法可以根据指定的模式字符串创建自定义格式化程序。

  3. 解析和格式化:使用 parse(CharSequence text) 方法将文本解析为日期时间对象,使用 format(TemporalQuery<?> query) 方法将日期时间对象格式化为文本。

代码示例
import java.time.LocalDateTime;  
import java.time.format.DateTimeFormatter;  
  
public class DateTimeFormatterExample {  
    public static void main(String[] args) {  
        // 定义自定义的日期时间格式  
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");  
  
        // 使用 LocalDateTime 和 formatter 格式化日期时间  
        LocalDateTime now = LocalDateTime.now();  
        String formattedDateTime = now.format(formatter);  
        System.out.println("Formatted DateTime: " + formattedDateTime);  
  
        // 解析字符串为 LocalDateTime  
        String dateTimeStr = "2023-10-01 15:30:45";  
        LocalDateTime parsedDateTime = LocalDateTime.parse(dateTimeStr, formatter);  
        System.out.println("Parsed DateTime: " + parsedDateTime);  
  
        // 使用预定义的 ISO 格式  
        DateTimeFormatter isoFormatter = DateTimeFormatter.ISO_LOCAL_DATE_TIME;  
        String isoDateTimeStr = now.format(isoFormatter);  
        System.out.println("ISO Formatted DateTime: " + isoDateTimeStr);  
  
        // 解析 ISO 格式的字符串  
        LocalDateTime parsedIsoDateTime = LocalDateTime.parse(isoDateTimeStr, isoFormatter);  
        System.out.println("Parsed ISO DateTime: " + parsedIsoDateTime);  
    }  
}

在这个例子中,我们首先创建了一个自定义的 DateTimeFormatter 实例,用于将 LocalDateTime 对象格式化为 "yyyy-MM-dd HH:mm:ss" 格式的字符串,并展示了如何将这个格式的字符串解析回 LocalDateTime 对象。接着,我们使用了一个预定义的 ISO 格式的 DateTimeFormatter 来演示如何以 ISO 标准格式进行日期时间的格式化和解析。

DateTimeFormatter 是处理日期时间文本表示的强大工具,它支持灵活的格式定义和本地化,相比于SimpleDateFormat,它的线程更安全。

Period

Period 类用于表示基于日历的日期(年、月、日)之间的间隔。它主要用于处理那些与时间无关,仅与日期相关的间隔,比如两个生日之间的年数差异。Period 的字段包括年(years)、月(months)和日(days)。

示例代码
import java.time.LocalDate;  
import java.time.Period;  
  
public class PeriodExample {  
    public static void main(String[] args) {  
        LocalDate startDate = LocalDate.of(2020, 1, 15);  
        LocalDate endDate = LocalDate.of(2023, 4, 20);  
  
        // 计算两个日期之间的Period  
        Period period = Period.between(startDate, endDate);  
  
        // 输出结果  
        System.out.println("Years: " + period.getYears());  
        System.out.println("Months: " + period.getMonths());  
        System.out.println("Days: " + period.getDays());  
  
        // 也可以通过toTotalMonths()获取总月份数  
        long totalMonths = period.toTotalMonths();  
        System.out.println("Total Months: " + totalMonths);  
    }  
}

Duration

Duration 类用于表示基于时间的持续时间,精确到纳秒。它主要用于处理那些与时间相关的间隔,比如两个时间点之间的时长。Duration 的内部实现是基于秒和纳秒的,但它提供了方便的方法来以天、小时、分钟、秒等为单位进行操作。

示例代码
import java.time.Duration;  
import java.time.Instant;  
  
public class DurationExample {  
    public static void main(String[] args) {  
        Instant startTime = Instant.now();  
  
        // 模拟一些操作...  
        try {  
            Thread.sleep(5000); // 休眠5秒  
        } catch (InterruptedException e) {  
            e.printStackTrace();  
        }  
  
        Instant endTime = Instant.now();  
  
        // 计算两个时间点之间的Duration  
        Duration duration = Duration.between(startTime, endTime);  
  
        // 输出结果  
        System.out.println("Seconds: " + duration.getSeconds());  
        // 获取剩余的纳秒部分  
        long nano = duration.getNano();  
        System.out.println("Nano seconds: " + nano);  
  
        // 也可以以其他单位输出  
        System.out.println("Duration in millis: " + duration.toMillis());  
  
        // 转换为以天为单位的近似值(注意:这只是一个近似值,因为天的小数部分被忽略了)  
        long days = duration.toDays();  
        System.out.println("Approximate days: " + days);  
    }  
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值