英文:
TimeZone Date Conversion [Convert a Date object to a specified timeZone Date Object]
问题
我的方法:
// 初始化日期对象
Date date = new Date();
// 获取时区
ZoneId zoneId = ZoneId.of("Asia/Dubai");
// 创建ZonedDateTime对象
ZonedDateTime zdt = ZonedDateTime.ofInstant(date.toInstant(), zoneId);
// ZonedDateTime的实例
Instant instant = zdt.toInstant();
// 将Instant转换为指定时区
instant.atZone(zoneId);
// 获取本地日期时间对象
LocalDateTime ldt = LocalDateTime.ofInstant(instant, zoneId);
// 将其转换回Date对象
Date dateFinal = java.util.Date.from(Instant.from(ldt.atZone(zoneId)));
英文:
My approach :
// initailize date object
Date date = new Date();
// get time zone
ZoneId zoneId = ZoneId.of("Asia/Dubai");
// create zonedDateTime object
ZonedDateTime zdt = ZonedDateTime.ofInstant(date.toInstant(), zoneId);
// instant of zonedDateTime
Instant instant = zdt.toInstant();
// convert instant to specified zone
instant.atZone(zoneId);
// Get Local Date Time Object
LocalDateTime ldt = LocalDateTime.ofInstant(instant,zoneId);
//Convert it back to Date Object
Date dateFinal = java.util.Date.from(Instant.from(ldt.atZone(zoneId)));
Can anyone help me with conversion of timeZone Date object in Java 8
Date date = Fri Mar 31 16:10:13 IST
.
Now I need to convert this Date to any given timeZone Date object
Desired result:
> Date resultDate = Fri Mar 31 14:40:13 GST
Basically here I used (Asia/Dubai) Time Zone
But my result is: 2023-03-31T16:10:13.854+0530
. I am getting the result in IST only. It’s not getting converted to (Asia/Dubai).
I have mentioned all the ways I have tried.
答案1
得分: 1
核心概念:java.util.Date
没有时区。Date#toString
方法欺骗了你。
如果有一个旧的 java.util.Date
对象,立即转换为 java.time.Instant
。
Instant instant = myJavaUtilDate.toInstant();
然后应用你所需的时区。
ZonedDateTime zdt = instant.atZone(ZoneId.of("Asia/Dubai"));
仅使用 java.time
你的日期时间处理应该 仅涉及 java.time 类。
日期时间类在该包之外的类现在是遗留的,设计非常糟糕。遗留类在Java 8+中由 java.time 在JSR 310中取代。
你说:
// 初始化日期对象
Date date = new Date();
你是指 java.util.Date
还是 java.sql.Date
?两者都是遗留的。
- 第一个被
java.time.Instant
取代。遗留和现代类都表示与UTC的偏移量为零时分秒的瞬间。 - 第二个被
java.time.LocalDate
取代。遗留类 假装 表示仅日期,但由于设计缺陷,它实际上包含了一天中的时间和偏移为零的假设。相比之下,现代类真正表示仅日期,不带时间和时区或偏移。
替代使用这段代码:
Instant instant = Instant.now(); // 捕获当前以UTC为基准的瞬间。
你说:
// 获取时区
ZoneId zoneId = ZoneId.of("Asia/Dubai");
很好。ZoneId
是表示时区的现代方式。Asia/Dubai
在 Continent/Region
中是真实时区的正确命名。
你说:
// 创建 ZonedDateTime 对象
ZonedDateTime zdt = ZonedDateTime.ofInstant(date.toInstant(), zoneId);
使用上面看到的我们的 Instant
对象,使用这段代码:
ZonedDateTime zdt = instant.atZone(zoneId);
这里的 instant
和 zdt
代表相同的瞬间,时间轴上的相同点。但后者是通过特定区域的人们使用的挂钟时间查看的。
你说:
// ZonedDateTime 的瞬间
Instant instant = zdt.toInstant();
是的,你可以从 ZonedDateTime
中提取 Instant
。但这里的代码是不必要的,因为我们已经实例化了一个 Instant
对象来捕获当前时刻。
你说:
// 将瞬间转换为指定时区
instant.atZone(zoneId);
这里的问题是 Instant
对象,像所有 java.time 对象一样,是不可变的。你无法在创建后更改(“突变”) Instant
对象的内容。那一刻永远被冻结。
此外,调用 Instant#atZone
返回一个全新的 ZonedDateTime
对象。我们在上面的代码中已经看到了这一点。你上面展示的代码忽略了 atZone
返回的新的 ZonedDateTime
对象。
你说:
// 获取本地日期时间对象
LocalDateTime ldt = LocalDateTime.ofInstant(instant, zoneId);
这里有两个问题:
- 你可以更容易地从上面实例化的
ZonedDateTime
中获得LocalDateTime
。LocalDateTime ldt = zdt.toLocalDateTime();
- 你可能没有意识到,在创建
LocalDateTime
时,你 丢失了有价值的信息:时区。所以你只剩下一个日期和一天中的时间。但这样的值本质上是模棱两可的。例如,如果今年1月23日中午,我们不知道你是指东京日本的中午,图卢兹法国的中午还是美国俄亥俄州托莱多的中午——这是几个小时的不同时刻。
提示:如果你还没有完全理解日期时间处理,请避免使用 LocalDateTime
。在大多数业务情况下,我们通常关心的是一个时刻,时间轴上的特定点。LocalDateTime
不适用于这种情况。
你说:
//将其转换回 Date 对象
Date dateFinal = java.util.Date.from(Instant.from(ldt.atZone(zoneId)));
这里有两个问题:
- 你可以更容易地写成
java.util.Date.from( instant )
,因为我们已经有了一个Instant
。或者,如果我们只有上面看到的ZonedDateTime
,java.util.Date.from( zdt.toInstant() )
。 - 通常情况下,你不会在新代码中写这个。仅在必要时与尚未更新为 java.time 的旧代码进行交互时才转换为旧代码。否则,尽量避免使用
Date
类,如同避免使用Calendar
、SimpleDateFormat
等。
你的标题问:
>[将 Date 对象转换为指定时区的 Date 对象]
我不明白你的意思。java.util.Date
类表示UTC中的时刻。它没有时区。
(实际上 有 一个时区被埋在它的代码中,但这个代码几乎是无关紧要的,表示遗留日期时间类中发现的另一种可怕的设计决策。)
你说:
>在 JAVA 8 中的时区 Date 对象是 Fri Mar 31 16:10:13 IST
不要被 java.util.Date#toString
方法愚弄。不幸的是,该方法在生成文本时不断注入JVM的当前默认时区。虽然出于善意,
英文:
tl;dr
Core Concept: java.util.Date
does not have a time zone. The Date#toString
method lies to you.
If handed a legacy java.util.Date
object, immediately convert to java.time.Instant
.
Instant instant = myJavaUtilDate.toInstant() ;
Then apply your desired time zone.
ZonedDateTime zdt = instant.atZone( ZoneId.of( "Asia/Dubai" ) ) ;
Use only java.time
Your date-time handling should involve only the java.time classes.
The date-time classes outside that package are now legacy, terribly flawed in poor design. The legacy classes were supplanted by java.time in JSR 310, implemented in Java 8+.
You said:
// initailize date object
Date date = new Date();
Did you mean java.util.Date
or java.sql.Date
? Both are legacy.
- The first was replaced by
java.time.Instant
. Both the legacy and modern classes represent a moment as seen with an offset from UTC of zero hours-minutes-seconds. - The second was replaced by
java.time.LocalDate
. The legacy class pretends to represent a date-only, but because of faulty design it actually contains a time-of-day and an assumption of an offset of zero. In contrast, the modern class truly represents a date-only, without time-of-day, and without time zone or offset.
Instead use this code:
Instant instant = Instant.now() ; // Capture the current moment as seen in UTC (zero offset).
You said:
// get time zone
ZoneId zoneId = ZoneId.of("Asia/Dubai");
Good. A ZoneId
is the modern way to represent a time zone. And Asia/Dubai
, in Continent/Region
is the correct naming for real time zones.
You said:
// create zonedDateTime object
ZonedDateTime zdt = ZonedDateTime.ofInstant(date.toInstant(), zoneId);
Using our Instant
object seen above, use this code:
ZonedDateTime zdt = instant.atZone( zoneId ) ;
Both instant
& zdt
here represent the same simultaneous moment, the same point on the timeline. But the latter is viewed through the wall-clock time used by people in a particular region.
You said:
// instant of zonedDateTime
Instant instant = zdt.toInstant();
Yes, you can extract an Instant
from a ZonedDateTime
. But this code in unnecessary here as we already instantiate a Instant
object to capture the current moment.
You said:
// convert instant to specified zone
instant.atZone(zoneId);
The problem here is that an Instant
object, like all the java.time objects, is immutable. You can alter (“mutate”) the content of an Instant
object after its creation. That moment is frozen forever.
Furthermore, calling Instant#atZone
returns a fresh new ZonedDateTime
object. We saw just that in our code earlier above. Your code shown above ignores the new ZonedDateTime
object returned by atZone
.
You said:
// Get Local Date Time Object
LocalDateTime ldt = LocalDateTime.ofInstant(instant,zoneId);
Two problem here:
- You can more easily obtain a
LocalDateTime
from theZonedDateTime
instantiated above.LocalDateTime ldt = zdt.toLocalDateTime() ;
- You may not be aware that in creating the
LocalDateTime
, you are discarding valuable information: the time zone. So you are left with merely a date and a time-of-day. But such a value is inherently ambiguous. For example, if noon on January 23 this year, we do not know if you meant in noon in Tokyo Japan, noon in Toulouse France, or noon in Toledo Ohio US — three very different moments several hours apart.
Tip: If you do not yet fully grok date-time handling, avoid using LocalDateTime
. In most business situations, we generally care about a moment, a specific point on the timeline. LocalDateTime
does not fit that case.
You said:
//Convert it back to Date Object
Date dateFinal = java.util.Date.from(Instant.from(ldt.atZone(zoneId)));
Two problems here:
- You can more easily write
java.util.Date.from( instant )
as we already have anInstant
in hand. Or, if we had just theZonedDateTime
seen above,java.util.Date.from( zdt.toInstant() )
. - You would usually never write this in new code. Convert to the legacy code only where necessary to interoperate with old code not yet updated to java.time. Otherwise, avoid both
Date
classes like the plague. Ditto forCalendar
,SimpleDateFormat
, etc.
Your title asks:
>[Convert a Date object to a specified timeZone Date Object]
I do not understand what you mean. The java.util.Date
class represents a moment in UTC. It has no time zone.
(Actually there is a time zone buried with its code, but this code is practically irrelevant, and represents another of those terrible design decisions found in the legacy date-time classes.)
You said:
> timeZone Date object in JAVA 8 Date date = Fri Mar 31 16:10:13 IST
Do not be fooled by the java.util.Date#toString
method. That method unfortunately injects the JVM’s current default time zone while generating text. While well-intentioned, this creates the false illusion that Date
includes a time zone in its meaning when in fact it is "in UTC" (has an offset from UTC of zero).
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论