tl;博士
ZoneId z = ZoneId.of( "America/Montreal" ) ;
ZonedDateTime zdt = ZonedDateTime.now( z ) ;
long minutesIntoTheDay = ChronoUnit.MINUTES.between(
zdt.toLocalDate().atStartOfDay( z ) ,
zdt
);
时区
其他答案不正确,因为它们没有考虑时区。如果你想要从一天开始的分钟数,哪一天?从加尔各答、巴黎或蒙特利尔开始的一天? 23 小时、24 小时、25 小时或其他长度的一天?
指定proper time zone name。切勿使用 3-4 个字母的缩写,例如 EST 或 IST,因为它们不是真正的时区,不是标准化的,甚至不是唯一的(!)。
使用 java.time
通过指定ZoneId,获取所需/预期时区的当前时刻ZonedDateTime。
ZoneId zoneId = ZoneId.of( "America/Montreal" );
ZonedDateTime now = ZonedDateTime.now( zoneId );
要获取一天中的分钟数,请获取当天的第一个时刻,然后计算经过的时间。
ZonedDateTime startOfDay = now.toLocalDate().atStartOfDay( z );
以Duration 或ChronoUnit 枚举的形式计算经过的时间。
Duration duration = Duration.between( startOfDay , now );
long minutesIntoTheDay = duration.toMinutes();
……或者……
long minutesIntoTheDay = ChronoUnit.MINUTES.between( startOfDay , now );
示例:Europe/Amsterdam
以下示例显示了 2017 年 3 月 26 日凌晨 2 点在时区 Europe/Amsterdam 中的 DST 转换(“Spring forward”)for the Netherlands。
LocalDate march26 = LocalDate.of ( 2017, Month.MARCH, 26 );
LocalTime twoAm = LocalTime.of ( 2, 0 );
ZoneId z = ZoneId.of ( "Europe/Amsterdam" );
ZonedDateTime start = march26.atStartOfDay ( z );
ZonedDateTime stop = ZonedDateTime.of ( march26, twoAm, z );
long minutes = ChronoUnit.MINUTES.between ( start, stop );
Duration duration = Duration.between ( start, stop );
long durationAsMinutes = duration.toMinutes ( );
int minuteOfDay = stop.get ( ChronoField.MINUTE_OF_DAY );
转储到控制台。
System.out.println ( "start: " + start );
System.out.println ( "stop: " + stop );
System.out.println ( "minutes: " + minutes );
System.out.println ( "FYI: 4 * 60 = " + ( 4 * 60 ) + " | 3 * 60 = " + ( 3 * 60 ) + " | 2 * 60 = " + ( 2 * 60 ) );
System.out.println ( "duration.toString(): " + duration + " | durationAsMinutes: " + durationAsMinutes );
System.out.println ( "minuteOfDay: " + minuteOfDay );
你可以看到这个code run live at IdeOne.com。
开始:2017-03-26T00:00+01:00[欧洲/阿姆斯特丹]
停止:2017-03-26T03:00+02:00[欧洲/阿姆斯特丹]
分钟:120
仅供参考:4 * 60 = 240 | 3 * 60 = 180 | 2 * 60 = 120
duration.toString(): PT2H |持续时间:120
minuteOfDay: 180
输出中的注释:
-
offset-from-UTC 变化一个小时,从
+01:00 变为 +02:00。
- 我们请求的时间是凌晨 2 点,但该日期没有这样的时间。由于时钟提前了一个小时,所以在那个日期根本不存在凌晨两点。当然,时空没有弯曲也没有扭曲。从午夜到凌晨 3 点,实际时间只有 两个 小时,而不是三个。 java.time 类的设计者选择通过将时间值提前调整为有效时间来解决问题。阅读文档以确保您理解并同意此类行为。
-
ChronoField.MINUTE_OF_DAY 的结果不正确/不精确,因为该功能仅考虑一般的 24 小时天数,而不是实际的异常日期,例如具有 DST 转换的日期。我们看到 180 分钟,而实际只过去了 120 分钟。
更正:此答案以前建议使用ChronoField.MINUTE_OF_DAY。这是一个糟糕的建议,因为该功能使用通用的 24 小时工作日。夏令时 (DST) 等异常情况将被忽略。因此,对于某些时区的特定日期,结果可能不准确/正确。这种行为有明确的记录:
ChronoField MINUTE_OF_DAY
公共静态最终 ChronoField MINUTE_OF_DAY
一天中的每一分钟。
这计算一天中的分钟,从 0 到 (24 * 60) - 1。此字段对于所有日历系统具有相同的含义。
解析此字段时,它的行为等同于以下内容:该值在严格和智能模式下验证,但在宽松模式下不验证。该值被拆分为 MINUTE_OF_HOUR 和 HOUR_OF_DAY 字段。
关于java.time
java.time 框架内置于 Java 8 及更高版本中。这些类取代了麻烦的旧 legacy 日期时间类,例如 java.util.Date、Calendar 和 SimpleDateFormat。
Joda-Time 项目现在位于maintenance mode,建议迁移到java.time 类。
要了解更多信息,请参阅Oracle Tutorial。并在 Stack Overflow 上搜索许多示例和解释。规格为JSR 310。
从哪里获得 java.time 类?