如何在Java中向时间戳添加/减去TimeZone偏移? [英] How to add/subtract TimeZone Offset to a Timestamp in Java?

查看:398
本文介绍了如何在Java中向时间戳添加/减去TimeZone偏移?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用JDK 8,并且经常玩 ZonedDateTime Timestamp 。但是我仍然无法解决所面临的问题。

I am using JDK 8 and I played with ZonedDateTime and Timestamp a lot. But still I am not able to get a solution for the problem I am facing.

让我说我得到了格式化的 Timestamp 在GMT(UTC)中,我的服务器位于某处。可以说它设置为 Asia / Calcutta TimeZone(其ZoneOffset为 +05:30 )。

Lets say I get a formatted Timestamp in GMT (UTC) and my server is located somewhere. Lets say it's set to Asia/Calcutta TimeZone (whose ZoneOffset is +05:30).

如何基本将我的时区偏移量添加到时间戳中?

How to basically add/subtract my time zone offset to the Timestamp?

Input : 2017-09-13 13:10:30.333
Output: 2017-09-13 18:40:30.333

说明:在输入中,已将时区偏移量5hrs 30mts添加到输入中。同样,输入的类型是时间戳,输出的类型也是。

Explanation : In the input, the timezone offset which is 5hrs 30mts has been added to the input. Also, the input is of type Timestamp and so is the output.

我使用 ZoneID.systemDefault()函数检索JVM已知的TimeZone。就我而言,时区竟然是 Asia / Calcutta

I use ZoneID.systemDefault() function to retrieve the TimeZone known to JVM. In my case, the TimeZone turned out to be Asia/Calcutta.

推荐答案

java.sql.Timestamp 没有任何时区信息。它只有一个值*:Unix纪元以来的纳秒数( 1970-01-01T00:00Z 1月1日 st 1970年UTC午夜。 您不会将此值转换为时区,因为此数字未附加到任何特定时区。

A java.sql.Timestamp doesn't have any timezone information. It just has one value*: the number of nanoseconds since unix epoch (1970-01-01T00:00Z or "January 1st 1970 at midnight in UTC"). You don't convert this value to a timezone because this number is not attached to any specific timezone.

打印<$ c $时c> Timestamp ,它调用 toString()方法,并在JVM默认时区中打印相应的日期和时间。但是时间戳本身没有附加时区。

When printing the Timestamp, it calls the toString() method, and this prints the corresponding date and time in the JVM default timezone. But the Timestamp itself doesn't have a timezone attached to it.

看看本文以获取更多信息。它讨论了 java.util.Date ,但是概念是相同的:这些对象不携带任何格式或时区信息,因此您不能在时区之间进行转换。您可以更改的是这些值在不同区域中的表示形式

Take a look at this article for more info. It talks about java.util.Date, but the concept is the same: these objects don't carry any format or timezone information, so you can't convert them between timezones. What you can change is the representation of those values in different zones.

示例:如果我采用 1505308230333000000 作为自历元以来的纳秒数。此数字代表UTC的13:10,圣保罗的10:10,伦敦的14:10,东京的22:10,加尔各答的18:40,依此类推。

Example: if I take the 1505308230333000000 as the number of nanoseconds since epoch. This same number represents 13:10 in UTC, 10:10 in São Paulo, 14:10 in London, 22:10 in Tokyo, 18:40 in Calcutta, and so on.

Timestamp 类仅保留大数值*。这个相同的值对应每个时区中不同的日期/时间,但每个人的值始终相同

The Timestamp class just keeps the big number value*. This same value corresponds to a different date/time in each timezone, but its value is always the same for everyone.

这就是为什么转换不同区域之间的 Timestamp 没有任何意义:您的 Timestamp 对象已经代表两者 13:10在UTC和在加尔各答的18:40中(它包含对应于各个时区中这些日期/时间的大数值-更改此值将更改所有时区的各自本地日期/时间。)

That's why converting the Timestamp between different zones makes no sense: your Timestamp object already represents both 13:10 in UTC and 18:40 in Calcutta (it contains the big number value that corresponds to these date/times in the respective timezones - changing this value will change the respective local date/times for all timezones).

您可以更改的是此大数字值(指定时区中的相应本地日期/时间)的 String 表示形式。

What you can change is the String representation of this big number value (the corresponding local date/time in a specified timezone).

如果要获取 String 以及相应的日期和时间,请输入不过,您可以使用 java.time 类。

If you want to get a String with the corresponding date and time in another timezone, though, you can use the java.time classes.

首先,您需要转换 java.sql.Timestamp java.time.Instan t ,然后将其转换为时区,从而生成 java.time.ZonedDateTime 。最后,使用 java.time.format.DateTimeFormatter

First you need to convert the java.sql.Timestamp to a java.time.Instant, then convert it to a timezone, resulting in a java.time.ZonedDateTime. Finally, I format it to a String, using a java.time.format.DateTimeFormatter:

DateTimeFormatter fmt = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS");
// convert the timestamp to a zoneddatetime
ZonedDateTime z = timestamp.toInstant().atZone(ZoneId.of("Asia/Calcutta"));
// format it
System.out.println(z.format(fmt)); // 2017-09-13 18:40:30.333

输出为:


2017-09-13 18:40:30.333

2017-09-13 18:40:30.333






如果您已经知道要使用的时区(在这种情况下为 Asia / Calcutta ),请不要使用默认时区( ZoneID.systemDefault())-当然,您可以根据需要使用它,请记住它即使在运行时也可以在不通知的情况下进行更改,因此最好始终明确说明您正在使用哪个。


If you already know what timezone to use (in this case, Asia/Calcutta), don't use the default timezone (ZoneID.systemDefault()) - of course you can use it if you want, just keep in mind that it can be changed without notice, even at runtime, so it's better to always make it explicit which one you're using.

*实际上, Timestamp 将大数值保留在两个字段中:一个为秒,另一个为纳秒值。但这是一个实现细节,不会改变此值未附加到任何时区的概念,因此在区域之间转换 Timestamp 毫无意义

*Actually, the Timestamp keeps the big number value in two fields: one for the seconds and another for the nanoseconds value. But that's an implementation detail, that doesn't change the concept that this value is not attached to any timezone and so there's no point in converting the Timestamp between zones

这篇关于如何在Java中向时间戳添加/减去TimeZone偏移?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆