Java Clock类
最后修改时间:2025 年 4 月 16 日
java.time.Clock
类提供了使用时区访问当前瞬间、日期和时间的功能。它被设计用作基于时间的服务的依赖注入点。Clock可以代替System.currentTimeMillis()
使用。
Clock
是抽象类并且是不可变的。它支持多种时间源,包括用于测试的固定时钟。该类通过允许在单元测试中控制时间来帮助使代码更易于测试。
Clock类概述
Clock
提供了获取各种格式的当前时间的方法。关键操作包括获取瞬间、毫秒和时区感知日期。该类支持系统和自定义时间源。
public abstract class Clock { public static Clock systemUTC(); public static Clock systemDefaultZone(); public static Clock system(ZoneId zone); public static Clock fixed(Instant fixedInstant, ZoneId zone); public static Clock offset(Clock baseClock, Duration offsetDuration); public abstract ZoneId getZone(); public abstract Clock withZone(ZoneId zone); public long millis(); public abstract Instant instant(); public boolean equals(Object obj); public int hashCode(); public String toString(); }
上面的代码展示了Clock
提供的关键方法。这些方法允许创建不同的时钟实现并访问时间值。该类专为在对时间敏感的应用程序中提供灵活性而设计。
创建Clock对象
Clock对象可以使用各种工厂方法创建。最常见的是用于不同时区的系统时钟和用于测试的固定时钟。每种时钟类型都服务于不同的用例。
package com.zetcode; import java.time.Clock; import java.time.Instant; import java.time.ZoneId; public class Main { public static void main(String[] args) { // System clock in UTC Clock utcClock = Clock.systemUTC(); System.out.println("UTC time: " + utcClock.instant()); // System clock in default timezone Clock defaultClock = Clock.systemDefaultZone(); System.out.println("Default zone time: " + defaultClock.instant()); // System clock in specific timezone Clock parisClock = Clock.system(ZoneId.of("Europe/Paris")); System.out.println("Paris time: " + parisClock.instant()); // Fixed clock for testing Clock fixedClock = Clock.fixed(Instant.now(), ZoneId.systemDefault()); System.out.println("Fixed time: " + fixedClock.instant()); } }
此示例演示了创建Clock对象的不同方法。输出显示了每种时钟类型如何提供时间值。固定时钟对于测试时间敏感的代码特别有用。
获取当前时间
Clock提供了几种访问当前时间值的方法。这些包括获取瞬间、毫秒或特定于时区的日期。这些方法提供了根据所需精度的灵活性。
package com.zetcode; import java.time.Clock; import java.time.Instant; import java.time.ZoneId; import java.time.ZonedDateTime; public class Main { public static void main(String[] args) { Clock clock = Clock.systemDefaultZone(); // Get current instant Instant instant = clock.instant(); System.out.println("Current instant: " + instant); // Get milliseconds since epoch long millis = clock.millis(); System.out.println("Milliseconds: " + millis); // Get zoned date time ZonedDateTime zdt = ZonedDateTime.now(clock); System.out.println("Zoned date time: " + zdt); // Get time zone ZoneId zone = clock.getZone(); System.out.println("Time zone: " + zone); } }
此示例演示了如何从Clock提取各种时间值。instant()
方法提供了最精确的时间测量。其他方法为不同的用例提供了便利。
使用固定时钟进行测试
固定时钟对于测试依赖于时间的代码非常宝贵。它们允许模拟特定的时间点,使测试可预测且可重复。这对于可靠的单元测试至关重要。
package com.zetcode; import java.time.Clock; import java.time.Instant; import java.time.ZoneId; import java.time.Duration; public class Main { public static void main(String[] args) { // Create fixed clock for testing Instant testTime = Instant.parse("2025-01-01T00:00:00Z"); Clock fixedClock = Clock.fixed(testTime, ZoneId.of("UTC")); System.out.println("Fixed time: " + fixedClock.instant()); // Simulate time passing (won't actually change) System.out.println("After waiting: " + fixedClock.instant()); // Create offset clock Clock offsetClock = Clock.offset(fixedClock, Duration.ofHours(2)); System.out.println("Offset time: " + offsetClock.instant()); } }
此示例演示了使用固定时钟和偏移时钟进行测试场景。固定时钟始终返回相同的瞬间,而偏移时钟提供一致的时间差。两者都对测试用例有用。
具有不同时区的Clock
Clock可以配置不同的时区以提供本地化时间值。这对于需要在多个区域显示或处理时间的应用程序很有用。
package com.zetcode; import java.time.Clock; import java.time.ZoneId; import java.time.ZonedDateTime; public class Main { public static void main(String[] args) { // Clocks with different time zones Clock newYorkClock = Clock.system(ZoneId.of("America/New_York")); Clock tokyoClock = Clock.system(ZoneId.of("Asia/Tokyo")); Clock londonClock = Clock.system(ZoneId.of("Europe/London")); // Get zoned date times ZonedDateTime nyTime = ZonedDateTime.now(newYorkClock); ZonedDateTime tokyoTime = ZonedDateTime.now(tokyoClock); ZonedDateTime londonTime = ZonedDateTime.now(londonClock); System.out.println("New York: " + nyTime); System.out.println("Tokyo: " + tokyoTime); System.out.println("London: " + londonTime); // Change time zone of existing clock Clock adjustedClock = londonClock.withZone(ZoneId.of("Australia/Sydney")); System.out.println("Sydney: " + ZonedDateTime.now(adjustedClock)); } }
此示例展示了Clock如何为不同的时区提供时间值。withZone
方法使用不同的时区创建一个新的时钟。这允许在应用程序中灵活地处理时区。
比较Clocks
可以根据其配置来比较时钟是否相等。这在验证时钟设置或确保在整个应用程序中使用一致的时间源时很有用。
package com.zetcode; import java.time.Clock; import java.time.Instant; import java.time.ZoneId; public class Main { public static void main(String[] args) { Clock clock1 = Clock.systemUTC(); Clock clock2 = Clock.system(ZoneId.of("UTC")); Clock clock3 = Clock.systemDefaultZone(); Clock fixedClock = Clock.fixed(Instant.now(), ZoneId.of("UTC")); System.out.println("UTC clocks equal: " + clock1.equals(clock2)); System.out.println("UTC vs default: " + clock1.equals(clock3)); System.out.println("System vs fixed: " + clock1.equals(fixedClock)); // Hash code comparison System.out.println("UTC clock hash: " + clock1.hashCode()); System.out.println("Default clock hash: " + clock3.hashCode()); } }
此示例演示了时钟比较操作。请注意,仅当两个时钟具有相同的配置时,才认为它们相等。具有不同时区的系统时钟不相等,即使它们表示相同的瞬间也是如此。
在时间敏感代码中使用Clock
Clock被设计为注入到时间敏感的类中,使其更易于测试。此模式允许在测试期间用固定时钟替换系统时钟。
package com.zetcode; import java.time.Clock; import java.time.Instant; import java.time.ZoneId; import java.time.Duration; class EventLogger { private final Clock clock; public EventLogger(Clock clock) { this.clock = clock; } public void logEvent(String message) { System.out.println(clock.instant() + ": " + message); } public boolean isEventRecent(Instant eventTime) { return Duration.between(eventTime, clock.instant()) .compareTo(Duration.ofMinutes(5)) <= 0; } } public class Main { public static void main(String[] args) { // Production use with system clock EventLogger productionLogger = new EventLogger(Clock.systemUTC()); productionLogger.logEvent("System started"); // Test use with fixed clock Instant testTime = Instant.parse("2025-01-01T12:00:00Z"); Clock testClock = Clock.fixed(testTime, ZoneId.of("UTC")); EventLogger testLogger = new EventLogger(testClock); testLogger.logEvent("Test event"); Instant recentEvent = Instant.parse("2025-01-01T11:55:00Z"); System.out.println("Is event recent? " + testLogger.isEventRecent(recentEvent)); } }
此示例展示了如何使用Clock使时间敏感的代码可测试。EventLogger类在其构造函数中接受一个Clock,允许测试使用固定时钟。建议在生产代码中使用此模式。
来源
在本文中,我们介绍了Java Clock类的基本方法和功能。理解这些概念对于在Java应用程序中编写可测试的、时间敏感的代码至关重要。
作者
列出所有Java教程。