在 Java 构建没有时区的日历

Construct Calendar without time zone in Java

我想在Java中构造没有时区的日期。我试过这个来忽略时区:

Calendar time = Calendar.getInstance();
time.clear(Calendar.ZONE_OFFSET);

System.out.println("time = " + time.getTime());

但这对我不起作用。它 returns "2018-07-11 03:00:00" 而不是 "2018-07- 10 15:00:00".

有什么想法吗

tl;博士

LocalDateTime.now( 
    ZoneId.of( "America/Montreal" ) 
) 
.toString()

2018-01-23T12:34:56.123456

如果要删除分钟和秒,请截断。

LocalDateTime.now( 
    ZoneId.of( "America/Montreal" ) 
)
.truncatedTo( ChronoUnit.HOURS ) 
.toString()

2018-01-23T12:00:00

详情

Calendar class 现在是遗留的,被现代 java.time class 取代。另外,Calendar总是带有时区,所以不能满足你的需要。

java.time中,以“Local...”命名的三个classes故意缺少任何时区或与UTC的偏移量的概念。 local 一词的意思是 any 地区或 every 地区,而不是特定地区。

LocalDate

只有日期的值,缺少时间和时区。

LocalTime

一天中的时间值,缺少日期和时区。限于单个 24 小时期间。

LocalDateTime

带有时间的日期,没有时区。

不是代表一个时刻,是不是时间轴上的一个点。表示大约 26-27 小时范围内的 潜在 时刻(各个时区使用的各种偏移量)。 LocalDateTime 没有实际意义,直到您应用时区或与 UTC 的偏移量来确定特定时刻。

当前时刻

使用 Instant class 以 UTC 格式捕获当前时刻。此 class 使用纳秒分辨率,但当前时刻可能不是那么好,这取决于您的 JVM 实现、主机 OS 和主机计算机硬件时钟的限制。

Instant instant = Instant.now() ; // Capture current moment in UTC. 

如果您想通过特定区域的人们使用的墙壁点击时间的镜头来查看当前时刻,请应用时区。应用 ZoneId 得到 ZonedDateTime.

ZoneId z = ZoneId.of( "Pacific/Auckland" ) ;
ZonedDateTime zdt = instant.atZone( z ) ;

要仅使用 ZonedDateTime 中的日期和时间,但丢弃时区,请生成一个 LocalDateTime 对象。

LocalDateTime ldt = zdt.toLocalDateTime() ;  // Extract the date and time-of-day but omit the time zone. 

作为快捷方式,您可以跳过分区对象 InstantZonedDateTime。您仍然需要一个时区,一个 ZoneId,因为对于任何给定的时刻,日期和时间在全球范围内都因时区而异。 ZoneId 用于确定当前时刻,如该地区人们使用的挂钟时间所示。一旦捕获,ZoneId 就会被生成的 LocalDateTime 对象遗忘。如果您想保留该区域,请记住该区域,您将使用 ZonedDateTime 而不是 LocalDateTime

LocalDateTime ldt = LocalDateTime.now( z ) ;

如果您想要 JVM 在运行时的当前默认时区,请传递调用 ZoneId.systemDefault 返回的 ZoneId。请注意,该 JVM 中任何应用程序的任何线程中的任何代码都可以随时更改默认值。

如果您想要 UTC 而不是某个时区,请从 ZoneIdZoneOffset.UTCZoneOffset subclass 传递常量。

LocalDateTime.now( ZoneOffset.UTC )  // Capture the current date and time of day as seen in UTC (an offset of zero), and then discard that offset/zone info. 

关于java.time

java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.

Joda-Time project, now in maintenance mode, advises migration to the java.time classes.

要了解更多信息,请参阅 Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310

您可以直接与数据库交换 java.time 对象。使用 JDBC driver compliant with JDBC 4.2 或更高版本。不需要字符串,不需要 java.sql.* classes.

从哪里获得java.time classes?

ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.

cricket_007 mentioned you want to look at the LocalDateclass。这是一个没有时区的日期。

它具有获取当前时间并将其转换为分区日期或日期时间的方法。这是 Java 中 'new' 时间 API 的一部分,其设计理念是要求您思考数据的含义,因为时间和日期是 incredibly hard to get right.

我们是在谈论持续时间吗?使用 Duration.

是否要向使用 ZonedDateTime 的用户显示时间,但不要指望那里的值是连续的,因为夏时制等。

我们是在谈论给定时间只有一个值的线性时间吗?你想要一个 Instant.

我们的想法是设计 API 以便您在不考虑这些事情的情况下无法使用不同的数据类型。如果您想阅读更多内容,可以从 Joda Time which is the precursor to today's java.time

开始