为夏令时分配java.sql.Timestamp

问题描述 投票:2回答:3

我在理解java.sql.timestamp时遇到问题。

如果我运行不赞成使用的Java构造函数:

java.sql.Timestamp(106,2,26,1,0,0,0)
java.sql.Timestamp(106,2,26,2,0,0,0)
java.sql.Timestamp(106,2,26,3,0,0,0)   //<-- Separated by one hour

我得到:

2006-03-26 01:00:00.0
2006-03-26 03:00:00.0     
2006-03-26 03:00:00.0   //<--These last two are the same

大约在这些时间发生夏令时(至少在我的国家/地区)。但是时间之前和之后的日期不会移动。为什么两个小时分开返回同一时间?

我想像输入一样获得时间戳,我该如何强制呢?

java sql timestamp dst
3个回答
1
投票

请勿使用此不推荐使用的构造函数,因为它使用默认时区,因此不推荐使用此构造函数。

使用具有适当时区(CET)的日历(或DateFormat),设置日历的字段(或解析包含您要插入的日期的字符串),从日历/日期获取毫秒,然后构造时间戳(以毫秒为单位)。


0
投票

使用System.currentTimeMillis();为您提供格林威治标准时间,不受夏令时,savings秒和其他意外调整日期的影响。

long now = System.currentTimeMillis();

或手动指定时区:

long ms = Calendar.getInstance(TimeZone.getTimeZone("GMT")).getTimeInMillis();

来源:Get GMT Time in Java


0
投票

tl; dr

夏时制(DST)转换意味着2 AM小时不存在] >>。因此,您输入的内容无效。

ZonedDateTime类尝试通过调整您的时间输入来帮助您,该时间跳到凌晨3点,就像凌晨02:00时时钟比早晨跳一个小时。

ZonedDateTime
.of( 2006 , 3 , 26 , 2 , 0 , 0 , 0 , ZoneId.of( "Africa/Tunis" ) )
.toString()

2006-03-26T03:00 + 02:00 [非洲/突尼斯]

避免使用旧的日期时间类

java.sql.Timestampterrible类,及其同级类,例如java.util.DateCalendar / GregorianCalendar。在其许多设计问题中,是时区的混乱处理。

相反,仅使用现代的[[java.time

类。java.time

对于时刻(日期,日期,时区或UTC偏移量,请使用以下类别之一:

    [Instant —时刻在UTC中。
  • [OffsetDateTime —距UTC偏移(时分分钟数),但时区未知的时刻]>
  • ZonedDateTime —具有指定时区的时刻。
  • 听起来您打算在自己的区域中使用日期时间。
  • ZoneId

proper time zone name的格式指定Continent/Region,例如America/MontrealAfrica/CasablancaPacific/Auckland。切勿使用2-4个字母的缩写,例如ESTIST,因为它们是

not

真实时区,不是标准化的,甚至不是唯一(!)。 ZoneId z = ZoneId.of( "America/Montreal" ) ;
如果要使用JVM的当前默认时区,请提出要求并作为参数传递。如果省略,代码将变得难以理解,因为我们不确定您是否打算使用默认值,或者您是否像许多程序员一样不知道该问题。

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

ZonedDateTime

指定在特定区域(时区)的人们使用的挂钟时间中看到的时间和日期。

ZoneId z = ZoneId.of( "Africa/Tunis" ) ; ZonedDateTime zdt_1 = ZonedDateTime.of( 2006, 3 , 26 , 1 , 0 , 0 , 0 , z ) ; ZonedDateTime zdt_2 = ZonedDateTime.of( 2006, 3 , 26 , 2 , 0 , 0 , 0 , z ) ; ZonedDateTime zdt_3 = ZonedDateTime.of( 2006, 3 , 26 , 3 , 0 , 0 , 0 , z ) ; System.out.println("zdt_1.toString(): " + zdt_1); System.out.println("zdt_2.toString(): " + zdt_2); System.out.println("zdt_3.toString(): " + zdt_3);

zdt_1.toString():2006-03-26T01:00 + 01:00 [非洲/突尼斯]

zdt_2.toString():2006-03-26T03:00 + 02:00 [非洲/突尼斯]

zdt_3.toString():2006-03-26T03:00 + 02:00 [非洲/突尼斯]

夏令时(DST)

我们在第三项上看到一个惊喜,我们要求2 AM,但要3 AM。这是可以理解的,因为有一个Daylight Saving Time (DST)转换或“ Spring Spring”。从2005年开始,Tunisia adopted DST。在2009年下半年,他们恢复了意识,仅回到标准时间。

不存在凌晨2点

因此,突尼斯当天没有凌晨2点。当时钟敲到凌晨2点时,它跳到凌晨3点。

从来没有凌晨2点。

那天是只有23小时长,而不是通常的24小时长。因此,我们上面的代码要求输入无效的日期时间。 ZonedDateTime类而不是抛出Exception,而是尝试通过调整为有效的时间来帮助我们。 JavaDoc for ZonedDateTime.of的拼写是:
从年,月,日,小时,分钟,秒,纳秒和时区中获取ZonedDateTime的实例。

这将创建一个与七个指定字段的本地日期时间尽可能紧密匹配的分区日期时间。夏时制等时区规则意味着,并非每个本地日期时间都对指定时区有效,因此可以调整本地日期时间。

本地日期时间在时间​​轴上解析为单个时刻。这是通过根据区域ID规则定义的本地日期时间找到UTC /格林威治标准有效偏移量来实现的。

在大多数情况下,本地日期时间只有一个有效的偏移量。在重叠的情况下,当时钟调回时,有两个有效的偏移量。此方法使用通常对应于“夏季”的更早偏移量。

在间隙的情况下,当时钟向前跳时,没有有效的偏移量。取而代之的是,将本地日期时间调整为晚一些间隔时间。对于典型的一小时夏令时更改,本地日期时间将在一小时后移入通常对应于“夏季”的偏移量中。

所以行为是功能,而不是错误。


ZonedDateTime.of


关于

java.timeTable of date-time types in Java (both legacy and modern) and in standard SQL框架内置于Java 8及更高版本中。这些类取代了麻烦的旧java.time日期时间类,例如legacyjava.util.Datejava.util.Date

Calendar项目现在位于Calendar中,建议迁移到SimpleDateFormat类。

要了解更多信息,请参见SimpleDateFormat。并在Stack Overflow中搜索许多示例和说明。规格为Joda-Time

您可以直接与数据库交换

java.time

对象。使用兼容maintenance mode或更高版本的java.time。不需要字符串,不需要Oracle Tutorial类。从哪里获取java.time类?

  • Java SE 11
    • java.time
  • 类的Android捆绑包实现的最新版本。
  • 对于较早的Android(<26),Java SE 6项目改编为Java SE 7(如上所述)。参见ThreeTen-Backport
  • Android项目使用其他类扩展了java.time。该项目是将来可能向java.time添加内容的试验场。您可能会在这里找到一些有用的类,例如ThreeTenABPThreeTen-BackportHow to use ThreeTenABP…ThreeTen-Extra
    © www.soinside.com 2019 - 2024. All rights reserved.