gpt4 book ai didi

java - 公历错误时间

转载 作者:行者123 更新时间:2023-12-02 01:49:59 25 4
gpt4 key购买 nike

因此,我开始用Java-GregorianCalendar类进行了一些测试,并注意到以毫秒为单位初始化Object时发生了奇怪的行为。使我困扰的是,尽管我将毫秒设置为0,但时间显示为1点。

在浏览了StackOverflow之后,我注意到Java有时会与夏季和冬季混淆。所以我的问题是,尽管尽管今年已经进行了时间更改并且我们又生活在冬天,但是这种奇怪的行为来自冬天和夏天。

这是我正在测试的代码:

import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.GregorianCalendar;

public class TestCalendar {

public static void main(String[] args) {
GregorianCalendar c = new GregorianCalendar();
c.setTimeInMillis(-3600000);
System.out.println(c.getTimeInMillis());
System.out.println(c.get(Calendar.HOUR));
String format = "mm:ss";
if (c.get(Calendar.HOUR_OF_DAY) > 0) format = "HH:mm:ss";
System.out.println(new SimpleDateFormat(format).format(c.getTime()));
}

}


这给了我输出

-3600000
0
0


最好的办法是找到一个独立于减法-3600000的解决方案,好像在其他计算机上不存在此“ bug”我不想拥有23:00:00 :)

编辑:

经过多做一些尝试,并感谢“反馈”,我可以通过在初始化Calendar之后添加以下行来解决我的小问题:

c.setTimeZone(TimeZone.getTimeZone("GMT"));

最佳答案

tl; dr

问题:您错误地更改了日期,而不仅仅是日期。最重要的是,隐式地应用了时区。

解决方案:而是使用现代的java.time类。

LocalDate
.now() // Better to explicitly pass the desired/expected time zone as a `ZoneId` object.
.atStartOfDay() // Again, better to explicitly pass the desired/expected time zone as a `ZoneId` object.


返回 LocalDateTime(注意:不是片刻,不是时间轴上的一点)。


  2018-11-01T00:00


指定时区更好。

LocalDate
.now(
ZoneId.of( "Pacific/Auckland" )
)
.atStartOfDay(
ZoneId.of( "Pacific/Auckland" )
)


返回 ZonedDateTime。这是片刻,是时间线上的一点。


  2018-11-02T00:00 + 13:00 [太平洋/奥克兰]


GregorianCalendar::setTimeInMillis未设置时间

显然,您错误地认为 GregorianCalendar::setTimeInMillis会设置日期时间而不影响日期。这些旧的日期时间类的许多缺陷中,有一些在命名类和方法上的选择很差。

但是,不,该方法将时刻重新定义为自1970-01-01T00:00Z的纪元参考日期以来的毫秒数。

加上隐式分配给 GregorianCalendar的时区,您会得到意想不到的结果。


  我开始使用Java-GregorianCalendar进行一些测试


别。

与Java的早期版本捆绑在一起的那些旧的日期时间类非常糟糕。几年前,它们被 JSR 310中定义的java.time类所取代。

具体来说,要使用UTC跟踪时刻,请使用 Instant


  用毫秒初始化对象


别。

跟踪时间作为从纪元开始计数的参考容易出错。行业中正在使用 many different epoch reference dates。行业中使用的粒度不同(整秒,毫秒,微秒,纳秒)。

因此,从时代算起是模棱两可的。由于人类无法读取值的含义,因此还容易造成混淆和遗漏错误。

交换日期时间值时,请改用标准ISO 8601格式的字符串。

从UTC的1970年第一刻的Unix纪元开始算起毫秒数时,解析为 Instant

Instant instant = Instant.ofEpochMilli( … ) ;


java.time

现代解决方案改为使用java.time类。

得到你的约会。

LocalDate

LocalDate类表示没有日期,没有 time zoneoffset-from-UTC的仅日期值。

时区对于确定日期至关重要。在任何给定时刻,日期都会在全球范围内变化。例如,在 Paris France中午夜之后的几分钟是新的一天,而在 Montréal Québec中仍是“昨天”。

如果未指定时区,则JVM隐式应用其当前的默认时区。该默认值可能会在运行时(!)期间 change at any moment,因此您的结果可能会有所不同。最好明确指定 desired/expected time zone作为参数。

continent/region的格式指定 proper time zone name,例如 America/MontrealAfrica/CasablancaPacific/Auckland。切勿使用2-4个字母的缩写,例如 ESTIST,因为它们不是真实的时区,不是标准化的,甚至不是唯一的(!)。

ZoneId z = ZoneId.of( "America/Montreal" ) ;  
LocalDate today = LocalDate.now( z ) ;


如果要使用JVM的当前默认时区,请提出要求并作为参数传递。如果省略,则会隐式应用JVM的当前默认值。最好明确一点,因为默认值可以在运行时随时通过JVM中任何应用程序的任何线程中的任何代码进行更改。

ZoneId z = ZoneId.systemDefault() ;  // Get JVM’s current default time zone.


或指定一个日期。您可以用数字设置月份,一月至十二月的理智编号为1-12。

LocalDate ld = LocalDate.of( 1986 , 2 , 23 ) ;  // Years use sane direct numbering (1986 means year 1986). Months use sane numbering, 1-12 for January-December.


或者,最好使用预定义的 Month枚举对象,一年中的每个月使用一个。提示:在整个代码库中使用这些 Month对象,而不仅仅是一个整数,可以使您的代码更具自记录性,确保有效值并提供 type-safety

LocalDate ld = LocalDate.of( 1986 , Month.FEBRUARY , 23 ) ;


ZonedDateTime

显然,您想要一天的第一时刻。顺便说一句,不要认为这是“午夜”,因为该术语是模棱两可的。

一天的第一时刻可能不是00:00。诸如夏令时(DST)之类的异常意味着某些区域中某些日期的第一时刻可能是另一个时间,例如01:00。让java.time确定第一时刻。

指定时区。

ZoneId z = ZoneId.of( "Africa/Tunis" ) ;
ZonedDateTime zdt = localDate.atStartOfDay( z ) ;


如果要在UTC中看到同一时刻,请提取 Instant

Instant instant = zdt.toInstant() ;




关于java.time

java.time框架内置于Java 8及更高版本中。这些类取代了麻烦的旧 legacy日期时间类,例如 java.util.DateCalendarSimpleDateFormat

现在位于 Joda-Time中的 maintenance mode项目建议迁移到 java.time类。

要了解更多信息,请参见 Oracle Tutorial。并在Stack Overflow中搜索许多示例和说明。规格为 JSR 310

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

在哪里获取java.time类?


Java SE 8Java SE 9Java SE 10Java SE 11和更高版本-具有捆绑实现的标准Java API的一部分。


Java 9添加了一些次要功能和修复。

Java SE 6Java SE 7


大多数java.time功能都被反向移植到 ThreeTen-Backport中的Java 6和7。

Android


更高版本的Android捆绑了java.time类的实现。
对于较早的Android(<26), ThreeTenABP项目改编为 ThreeTen-Backport(如上所述)。请参见 How to use ThreeTenABP…



ThreeTen-Extra项目使用其他类扩展了java.time。该项目是将来可能向java.time添加内容的试验场。您可能会在这里找到一些有用的类,例如 IntervalYearWeekYearQuartermore

关于java - 公历错误时间,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53109353/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com