时区转换

发布于 2024-11-18 11:21:04 字数 212 浏览 2 评论 0 原文

我需要在我的项目中从一个时区转换为另一个时区。

我可以从当前时区转换为另一个时区,但不能从不同时区转换为另一个时区。

例如,我在印度,我可以使用 Date d=new Date(); 从印度转换为美国,并将其分配给日历对象并设置时区。

但是,我无法从不同时区到另一个时区执行此操作。例如,我在印度,但在将时区从美国转换为英国时遇到问题。

I need to convert from one timezone to another timezone in my project.

I am able to convert from my current timezone to another but not from a different timezone to another.

For example I am in India, and I am able to convert from India to US using Date d=new Date(); and assigning it to a calendar object and setting the time zone.

However, I cannot do this from different timezone to another timezone. For example, I am in India, but I am having trouble converting timezones from the US to the UK.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(13

放我走吧 2024-11-25 11:21:04

tl;dr

ZonedDateTime.now( ZoneId.of( "Pacific/Auckland" ))              // Current moment in a particular time zone.
             .withZoneSameInstant( ZoneId.of( "Asia/Kolkata" ))  // Same moment adjusted into another time zone. 

详细信息

java.util.Date 类没有分配时区,但它的 toString 实现却混淆地应用了 JVM 当前的默认时区。

避免 java.util.Date & .Calendar

这是避免与 Java 捆绑在一起的众所周知的麻烦的 java.util.Date、.Calendar 和 SimpleDateFormat 类的众多原因之一。避开他们。而是使用:

java.time

Java 8 及更高版本具有 java.time 包 内置。这个包的灵感来自 Joda-Time。虽然它们有一些相似之处和类名,但它们是不同的;每个都有另一个所缺乏的功能。一个显着的区别是 java.time 避免使用构造函数,而是使用静态实例化方法。这两个框架均由同一个人 Stephen Colbourne 领导。

许多 java.time 功能已向后移植到 Java 6 和 Java 6。 ThreeTen-Backport 项目中的 7 号。在ThreeTenABP项目中进一步适配Android。

就这个问题而言,它们以相同的方式工作。指定时区,并调用 now 方法获取当前时刻,然后基于旧的不可变实例创建一个新实例以调整时区。

请注意两个不同的时区类别。一个是指定时区,包括夏令时和其他此类异常的所有规则以及与 UTC 的偏移量,而另一个只是偏移量。

ZoneId zoneMontréal = ZoneId.of("America/Montreal"); 
ZonedDateTime nowMontréal = ZonedDateTime.now ( zoneMontréal );

ZoneId zoneTokyo = ZoneId.of("Asia/Tokyo"); 
ZonedDateTime nowTokyo = nowMontréal.withZoneSameInstant( zoneTokyo );

ZonedDateTime nowUtc = nowMontréal.withZoneSameInstant( ZoneOffset.UTC );

Joda-Time

Joda-Time 2.3 中的一些示例代码如下。在 StackOveflow 中搜索更多示例和讨论。

DateTimeZone timeZoneLondon = DateTimeZone.forID( "Europe/London" );
DateTimeZone timeZoneKolkata = DateTimeZone.forID( "Asia/Kolkata" );
DateTimeZone timeZoneNewYork = DateTimeZone.forID( "America/New_York" );

DateTime nowLondon = DateTime.now( timeZoneLondon ); // Assign a time zone rather than rely on implicit default time zone.
DateTime nowKolkata = nowLondon.withZone( timeZoneKolkata );
DateTime nowNewYork = nowLondon.withZone( timeZoneNewYork );
DateTime nowUtc = nowLondon.withZone( DateTimeZone.UTC );  // Built-in constant for UTC.

我们对宇宙时间线上的同一时刻有四种表示。


实际上,java.util.Date确实有一个时区隐藏在其源代码。但出于大多数实际目的,该类会忽略该时区。因此,作为简写,人们常说 juDate 没有指定时区。令人困惑?是的。避免 juDate 的混乱,并使用 Joda-Time 和/或 java.time。

tl;dr

ZonedDateTime.now( ZoneId.of( "Pacific/Auckland" ))              // Current moment in a particular time zone.
             .withZoneSameInstant( ZoneId.of( "Asia/Kolkata" ))  // Same moment adjusted into another time zone. 

Details

The java.util.Date class has no time zone assigned, yet it's toString implementation confusingly applies the JVM's current default time zone.

Avoid java.util.Date & .Calendar

This is one of many reasons to avoid the notoriously troublesome java.util.Date, .Calendar, and SimpleDateFormat classes bundled with Java. Avoid them. Instead use either:

java.time

Java 8 and later has the java.time package built-in. This package was inspired by Joda-Time. While they share some similarities and class names, they are different; each has features the other lacks. One notable difference is that java.time avoids constructors, instead uses static instantiation methods. Both frameworks are led by the same man, Stephen Colbourne.

Much of the java.time functionality has been back-ported to Java 6 & 7 in the ThreeTen-Backport project. Further adapted to Android in the ThreeTenABP project.

In the case of this Question, they work in the same fashion. Specify a time zone, and call a now method to get current moment, then create a new instance based on the old immutable instance to adjust for time zone.

Note the two different time zone classes. One is a named time zone including all the rules for Daylight Saving Time and other such anomalies plus an offset from UTC while the other is only the offset.

ZoneId zoneMontréal = ZoneId.of("America/Montreal"); 
ZonedDateTime nowMontréal = ZonedDateTime.now ( zoneMontréal );

ZoneId zoneTokyo = ZoneId.of("Asia/Tokyo"); 
ZonedDateTime nowTokyo = nowMontréal.withZoneSameInstant( zoneTokyo );

ZonedDateTime nowUtc = nowMontréal.withZoneSameInstant( ZoneOffset.UTC );

Joda-Time

Some example code in Joda-Time 2.3 follows. Search StackOveflow for many more examples and much discussion.

DateTimeZone timeZoneLondon = DateTimeZone.forID( "Europe/London" );
DateTimeZone timeZoneKolkata = DateTimeZone.forID( "Asia/Kolkata" );
DateTimeZone timeZoneNewYork = DateTimeZone.forID( "America/New_York" );

DateTime nowLondon = DateTime.now( timeZoneLondon ); // Assign a time zone rather than rely on implicit default time zone.
DateTime nowKolkata = nowLondon.withZone( timeZoneKolkata );
DateTime nowNewYork = nowLondon.withZone( timeZoneNewYork );
DateTime nowUtc = nowLondon.withZone( DateTimeZone.UTC );  // Built-in constant for UTC.

We have four representations of the same moment in the timeline of the Universe.


Actually the java.util.Date class does have a time zone buried within its source code. But the class ignores that time zone for most practical purposes. So, as shorthand, it’s often said that j.u.Date has no time zone assigned. Confusing? Yes. Avoid the mess that is j.u.Date and go with Joda-Time and/or java.time.

櫻之舞 2024-11-25 11:21:04

一些示例

在时区之间转换时间

时区之间的时间转换

import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.TimeZone;

public class TimeZoneExample {
    public static void main(String[] args) {
        // Create a calendar object and set it time based on the local
        // time zone
        Calendar localTime = Calendar.getInstance();
        localTime.set(Calendar.HOUR, 17);
        localTime.set(Calendar.MINUTE, 15);
        localTime.set(Calendar.SECOND, 20);

        int hour = localTime.get(Calendar.HOUR);
        int minute = localTime.get(Calendar.MINUTE);
        int second = localTime.get(Calendar.SECOND);


        // Print the local time
        System.out.printf("Local time  : %02d:%02d:%02d\n", hour, minute, second);


        // Create a calendar object for representing a Germany time zone. Then we
        // wet the time of the calendar with the value of the local time

        Calendar germanyTime = new GregorianCalendar(TimeZone.getTimeZone("Europe/Berlin"));
        germanyTime.setTimeInMillis(localTime.getTimeInMillis());
        hour = germanyTime.get(Calendar.HOUR);
        minute = germanyTime.get(Calendar.MINUTE);
        second = germanyTime.get(Calendar.SECOND);


        // Print the local time in Germany time zone
        System.out.printf("Germany time: %02d:%02d:%02d\n", hour, minute, second);
    }
}

Some examples

Convert time between timezone

Converting Times Between Time Zones

import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.TimeZone;

public class TimeZoneExample {
    public static void main(String[] args) {
        // Create a calendar object and set it time based on the local
        // time zone
        Calendar localTime = Calendar.getInstance();
        localTime.set(Calendar.HOUR, 17);
        localTime.set(Calendar.MINUTE, 15);
        localTime.set(Calendar.SECOND, 20);

        int hour = localTime.get(Calendar.HOUR);
        int minute = localTime.get(Calendar.MINUTE);
        int second = localTime.get(Calendar.SECOND);


        // Print the local time
        System.out.printf("Local time  : %02d:%02d:%02d\n", hour, minute, second);


        // Create a calendar object for representing a Germany time zone. Then we
        // wet the time of the calendar with the value of the local time

        Calendar germanyTime = new GregorianCalendar(TimeZone.getTimeZone("Europe/Berlin"));
        germanyTime.setTimeInMillis(localTime.getTimeInMillis());
        hour = germanyTime.get(Calendar.HOUR);
        minute = germanyTime.get(Calendar.MINUTE);
        second = germanyTime.get(Calendar.SECOND);


        // Print the local time in Germany time zone
        System.out.printf("Germany time: %02d:%02d:%02d\n", hour, minute, second);
    }
}
初懵 2024-11-25 11:21:04
    Date date = new Date();
    String formatPattern = ....;
    SimpleDateFormat sdf = new SimpleDateFormat(formatPattern);

    TimeZone T1;
    TimeZone T2;

    // set the Calendar of sdf to timezone T1
    sdf.setTimeZone(T1);
    System.out.println(sdf.format(date));

    // set the Calendar of sdf to timezone T2
    sdf.setTimeZone(T2);
    System.out.println(sdf.format(date));

    // Use the 'calOfT2' instance-methods to get specific info
    // about the time-of-day for date 'date' in timezone T2.
    Calendar calOfT2 = sdf.getCalendar();
    Date date = new Date();
    String formatPattern = ....;
    SimpleDateFormat sdf = new SimpleDateFormat(formatPattern);

    TimeZone T1;
    TimeZone T2;

    // set the Calendar of sdf to timezone T1
    sdf.setTimeZone(T1);
    System.out.println(sdf.format(date));

    // set the Calendar of sdf to timezone T2
    sdf.setTimeZone(T2);
    System.out.println(sdf.format(date));

    // Use the 'calOfT2' instance-methods to get specific info
    // about the time-of-day for date 'date' in timezone T2.
    Calendar calOfT2 = sdf.getCalendar();
放肆 2024-11-25 11:21:04

只需为 Calendar 对象设置适当的时区即可完全避免“默认”时区。不过,我个人建议您使用 Joda Time 作为 Java 中日期和时间操作的高级 API 。除此之外,时区转换在 Joda 中非常简单。

目前尚不清楚您当前的代码是什么样的,以及为什么您只能通过默认时区进行转换,但在 Joda Time 中,您只需在创建(例如)DateTime 对象,然后使用 withZone(日期时区区)

如果您能告诉我们更多有关如何获取输入数据的信息,我们可以给出更完整的示例。

The "default" time zone can be avoided entirely by just setting the time zone appropriately for the Calendar object. However, I would personally suggest that you use Joda Time as a far superior API for date and time operations in Java. Amongst other things, time zone conversion is very simple in Joda.

It's not clear what your current code looks like and why you're only able to convert via the default time zone, but in Joda Time you'd just specify the time zone explicitly when creating (say) a DateTime object, and then use withZone(DateTimeZone zone).

If you could tell us more about how you're getting input data, we could give a fuller example.

來不及說愛妳 2024-11-25 11:21:04

您可以使用以下代码片段

String dateString = "14 Jul 2014 00:11:04 CEST";
date = formatter.parse(dateString);
System.out.println(formatter.format(date));

// Set the formatter to use a different timezone - Indochina Time
formatter.setTimeZone(TimeZone.getTimeZone("Asia/Bangkok"));
System.out.println("ICT time : "+formatter.format(date));

You can use the following code snippet

String dateString = "14 Jul 2014 00:11:04 CEST";
date = formatter.parse(dateString);
System.out.println(formatter.format(date));

// Set the formatter to use a different timezone - Indochina Time
formatter.setTimeZone(TimeZone.getTimeZone("Asia/Bangkok"));
System.out.println("ICT time : "+formatter.format(date));
吃素的狼 2024-11-25 11:21:04

如果您不想使用 Joda,这里有一种使用内置库的确定性方法。

首先,我建议您强制 JVM 默认为时区。这解决了当您将 JVM 从一台机器移动到另一台设置为不同时区的机器时可能遇到的问题,但源数据始终是特定时区。例如,假设您的数据始终为 PDT/PST 时区,但您在设置为 UTC 时区的机器上运行。

以下代码片段在我的 JVM 中设置默认时区:

 //You can either pass the JVM a parameter that 
 //enforces a TZ: java -Duser.timezone=UTC or you can do it
 //programatically like this
 TimeZone tz = TimeZone.getTimeZone("America/Los_Angeles");
 TimeZone.setDefault(tz);

现在假设您的源日期以 PDT/PST 形式输入,但您需要将其转换为 UTC。这些是步骤:

    DateFormat dateFormatUtc = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    dateFormatUtc.setTimeZone(TimeZone.getTimeZone("UTC"));

    String dateStrInPDT = "2016-05-19 10:00:00";
    Date dateInPDT = dateFormat.parse(dateStrInPDT);


    String dateInUtc = dateFormatUtc.format(dateInPDT);

    System.out.println("Date In UTC is " + dateInUtc);

输出将是:

Date In UTC is 2016-05-19 17:00:00

If you don't want to use Joda, here is a deterministic way using the built in libraries.

First off I recommend that you force your JVM to default to a timezone. This addresses the issues you might run into as you move your JVM from one machine to another that are set to different timezones but your source data is always a particular timezone. For example, lets say your data is always PDT/PST time zone, but you run on a box that is set to UTC timezone.

The following code snippet sets the default timezone in my JVM:

 //You can either pass the JVM a parameter that 
 //enforces a TZ: java -Duser.timezone=UTC or you can do it
 //programatically like this
 TimeZone tz = TimeZone.getTimeZone("America/Los_Angeles");
 TimeZone.setDefault(tz);

Now lets say your source date is coming in as PDT/PST but you need to convert it to UTC. These are the steps:

    DateFormat dateFormatUtc = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    dateFormatUtc.setTimeZone(TimeZone.getTimeZone("UTC"));

    String dateStrInPDT = "2016-05-19 10:00:00";
    Date dateInPDT = dateFormat.parse(dateStrInPDT);


    String dateInUtc = dateFormatUtc.format(dateInPDT);

    System.out.println("Date In UTC is " + dateInUtc);

The output would be:

Date In UTC is 2016-05-19 17:00:00
策马西风 2024-11-25 11:21:04

java.time

java.util Date-Time API 及其格式化 API SimpleDateFormat 已过时且容易出错。建议完全停止使用它们并切换到 现代日期时间 API*

另外,下面引用的是 Joda-Time 主页上的通知:

请注意,从 Java SE 8 开始,用户被要求迁移到 java.time (JSR-310) - JDK 的核心部分,它将取代该项目。

如何切换到现代 API?

使用 Date#toInstant 例如,

Date date = new Date();
Instant instant = date.toInstant();
System.out.println(instant); // 2021-05-30T13:10:01.890Z

Instant 与我的要求有什么关系?

即时 代表 UTC 时间线上的瞬时点。示例输出中的 Z时区指示符零时区偏移。它代表 Zulu,指定 Etc/UTC 时区(时区偏移量为 +00:00 小时)。它的零时区偏移使其独立于时区,即世界上每个地方的瞬间都是相同的。它类似于物质世界中的水。

您可以通过调用 ZoneId)与 Instant 混合使用/java/time/Instant.html#atZone-java.time.ZoneId-" rel="nofollow noreferrer">Instant.atZone 获取该时区相应的日期时间( IE ZonedDateTime)。

同样,您可以通过调用 Instant#atOffset 获取相应的日期时间该时区偏移量(即 OffsetDateTime)。

相反的方式,您还可以通过在 ZonedDateTimetoInstant 来获取 Instant code> 或 OffsetDateTime

import java.time.Instant;
import java.time.OffsetDateTime;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
import java.util.Date;

public class Main {
    public static void main(String[] args) {
        Date date = new Date();
        Instant instant = date.toInstant();
        System.out.println(instant);

        // The corresponding Date-Time in Chicago
        ZonedDateTime zdtChicago = instant.atZone(ZoneId.of("America/Chicago"));
        System.out.println(zdtChicago);

        // The corresponding Date-Time in Kolkata
        ZonedDateTime zdtKolkata = instant.atZone(ZoneId.of("Asia/Kolkata"));
        System.out.println(zdtKolkata);

        // The corresponding Date-Time at timezone offset of -05:00 hours
        OffsetDateTime odtAtOffsetMinus0500 = instant.atOffset(ZoneOffset.of("-05:00"));
        System.out.println(odtAtOffsetMinus0500);

        // The corresponding Date-Time at timezone offset of +05:30 hours
        OffsetDateTime odtAtOffset0530 = instant.atOffset(ZoneOffset.of("+05:30"));
        System.out.println(odtAtOffset0530);
    }
}

输出:

2021-05-30T13:44:26.599Z
2021-05-30T08:44:26.599-05:00[America/Chicago]
2021-05-30T19:14:26.599+05:30[Asia/Kolkata]
2021-05-30T08:44:26.599-05:00
2021-05-30T19:14:26.599+05:30

到目前为止,您已经学会了一种简单的方法来转换Instant(您直接创建或获得从 java.util.DateZonedDateTimeOffsetDateTime)到任何时区或任何时区偏移的日期时间。

或者,

还有另一种方法ZonedDateTime从一个时区转换为另一个时区。同样,有一种类似的方法可以将 OffsetDateTime 从一个时区偏移量转换为另一个时区偏移量。

import java.time.OffsetDateTime;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;

public class Main {
    public static void main(String[] args) {
        // Current Date-Time in Chicago
        ZonedDateTime zdtChicago = ZonedDateTime.now(ZoneId.of("America/Chicago"));
        System.out.println(zdtChicago);

        // The corresponding Date-Time in Kolkata
        ZonedDateTime zdtKolkata = zdtChicago.withZoneSameInstant(ZoneId.of("Asia/Kolkata"));
        System.out.println(zdtKolkata);

        // Current Date-Time at a timezone offset of -05:00 hours
        OffsetDateTime odtAtOffsetMinus0500 = OffsetDateTime.now(ZoneOffset.of("-05:00"));
        System.out.println(odtAtOffsetMinus0500);

        // The corresponding Date-Time at timezone offset of +05:30 hours
        OffsetDateTime odtAtOffset0530 = odtAtOffsetMinus0500.withOffsetSameInstant(ZoneOffset.of("+05:30"));
        System.out.println(odtAtOffset0530);
    }
}

输出:

2021-05-30T10:03:59.895923-05:00[America/Chicago]
2021-05-30T20:33:59.895923+05:30[Asia/Kolkata]
2021-05-30T10:03:59.897782-05:00
2021-05-30T20:33:59.897782+05:30

何时使用ZonedDateTime以及何时使用OffsetDateTime

  • 如果您正在处理固定时区偏移值,例如 02:00 小时,请使用 OffsetDateTime。所有 JDBC 驱动程序也都支持它。查看此答案以了解更多信息。
  • 如果您希望时区偏移量根据 DST 自动更改,请使用 ZonedDateTime.不幸的是,JDBC 不支持 ZonedDateTime

了解有关 java.time 的更多信息,现代日期时间 API* 来自 跟踪:日期时间


* 无论出于何种原因,如果您必须坚持使用 Java 6 或 Java 7,您可以使用 ThreeTen-Backport 将大部分 java.time 功能向后移植到 Java 6 和 Java 6 7. 如果您正在处理 Android 项目,并且您的 Android API 级别仍然不符合 Java-8,请检查 通过脱糖提供 Java 8+ API如何在Android项目中使用ThreeTenABP

java.time

The java.util Date-Time API and their formatting API, SimpleDateFormat are outdated and error-prone. It is recommended to stop using them completely and switch to the modern Date-Time API*.

Also, quoted below is a notice at the Home Page of Joda-Time:

Note that from Java SE 8 onwards, users are asked to migrate to java.time (JSR-310) - a core part of the JDK which replaces this project.

How to switch to the modern API?

Convert java.util.Date to Instant using Date#toInstant e.g.

Date date = new Date();
Instant instant = date.toInstant();
System.out.println(instant); // 2021-05-30T13:10:01.890Z

What's Instant got to do with my requirement?

An Instant represents an instantaneous point on the timeline in UTC. The Z in the sample output is the timezone designator for a zero-timezone offset. It stands for Zulu and specifies the Etc/UTC timezone (which has the timezone offset of +00:00 hours). Its zero-timezone offset makes it independent of timezones i.e. an instant is the same at every place in the world. It's analogous to water in the physical world.

You can mix a timezone (i.e. ZoneId) with an Instant by calling Instant.atZone to get the corresponding Date-Time in that timezone (i.e. ZonedDateTime).

Similarly, you can mix a timezone offset (i.e. ZoneOffset) with an Instant by calling Instant#atOffset to get the corresponding Date-Time with that timezone offset (i.e. OffsetDateTime).

In the reverse way, you can also get an Instant by calling toInstant on the ZonedDateTime or OffsetDateTime.

import java.time.Instant;
import java.time.OffsetDateTime;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
import java.util.Date;

public class Main {
    public static void main(String[] args) {
        Date date = new Date();
        Instant instant = date.toInstant();
        System.out.println(instant);

        // The corresponding Date-Time in Chicago
        ZonedDateTime zdtChicago = instant.atZone(ZoneId.of("America/Chicago"));
        System.out.println(zdtChicago);

        // The corresponding Date-Time in Kolkata
        ZonedDateTime zdtKolkata = instant.atZone(ZoneId.of("Asia/Kolkata"));
        System.out.println(zdtKolkata);

        // The corresponding Date-Time at timezone offset of -05:00 hours
        OffsetDateTime odtAtOffsetMinus0500 = instant.atOffset(ZoneOffset.of("-05:00"));
        System.out.println(odtAtOffsetMinus0500);

        // The corresponding Date-Time at timezone offset of +05:30 hours
        OffsetDateTime odtAtOffset0530 = instant.atOffset(ZoneOffset.of("+05:30"));
        System.out.println(odtAtOffset0530);
    }
}

Output:

2021-05-30T13:44:26.599Z
2021-05-30T08:44:26.599-05:00[America/Chicago]
2021-05-30T19:14:26.599+05:30[Asia/Kolkata]
2021-05-30T08:44:26.599-05:00
2021-05-30T19:14:26.599+05:30

So far you have learnt a simple way to convert an Instant (which you have created directly or obtained from a java.util.Date or a ZonedDateTime or an OffsetDateTime) to a Date-Time in any timezone or at any timezone offset.

Alternatively

There is another way to convert a ZonedDateTime from one timezone to another. Again, there is a similar method to convert an OffsetDateTime from one timezone offset to another.

import java.time.OffsetDateTime;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;

public class Main {
    public static void main(String[] args) {
        // Current Date-Time in Chicago
        ZonedDateTime zdtChicago = ZonedDateTime.now(ZoneId.of("America/Chicago"));
        System.out.println(zdtChicago);

        // The corresponding Date-Time in Kolkata
        ZonedDateTime zdtKolkata = zdtChicago.withZoneSameInstant(ZoneId.of("Asia/Kolkata"));
        System.out.println(zdtKolkata);

        // Current Date-Time at a timezone offset of -05:00 hours
        OffsetDateTime odtAtOffsetMinus0500 = OffsetDateTime.now(ZoneOffset.of("-05:00"));
        System.out.println(odtAtOffsetMinus0500);

        // The corresponding Date-Time at timezone offset of +05:30 hours
        OffsetDateTime odtAtOffset0530 = odtAtOffsetMinus0500.withOffsetSameInstant(ZoneOffset.of("+05:30"));
        System.out.println(odtAtOffset0530);
    }
}

Output:

2021-05-30T10:03:59.895923-05:00[America/Chicago]
2021-05-30T20:33:59.895923+05:30[Asia/Kolkata]
2021-05-30T10:03:59.897782-05:00
2021-05-30T20:33:59.897782+05:30

When to use ZonedDateTime and when to use OffsetDateTime?

  • If you are dealing with a fixed timezone offset value e.g. 02:00 hours, use OffsetDateTime. It is also supported by all JDBC drivers. Check this answer to learn more about it.
  • If you want the timezone offset to change automatically based on DST, use ZonedDateTime. Unfortunately, ZonedDateTime is not supported by JDBC.

Learn more about java.time, the modern Date-Time API* from Trail: Date Time.


* For any reason, if you have to stick to Java 6 or Java 7, you can use ThreeTen-Backport which backports most of the java.time functionality to Java 6 & 7. If you are working for an Android project and your Android API level is still not compliant with Java-8, check Java 8+ APIs available through desugaring and How to use ThreeTenABP in Android Project.

一桥轻雨一伞开 2024-11-25 11:21:04

您可以使用 java.time.ZoneDateTime#ofInstant() 方法:

import java.time.*;

public class TimeZonesConversion {
    static ZonedDateTime convert(ZonedDateTime time, ZoneId newTimeZone) {
        return ZonedDateTime.ofInstant(
                time.toInstant(),
                newTimeZone);
    };

    public static void main(String... args) {
        ZonedDateTime mstTime = ZonedDateTime.of(LocalDateTime.now(), ZoneId.of("-07")); 
        ZonedDateTime localTime = convert(mstTime, Clock.systemDefaultZone().getZone());
        System.out.println("MST(" + mstTime + ") = " + localTime);
    }
}

You could use the java.time.ZoneDateTime#ofInstant() method:

import java.time.*;

public class TimeZonesConversion {
    static ZonedDateTime convert(ZonedDateTime time, ZoneId newTimeZone) {
        return ZonedDateTime.ofInstant(
                time.toInstant(),
                newTimeZone);
    };

    public static void main(String... args) {
        ZonedDateTime mstTime = ZonedDateTime.of(LocalDateTime.now(), ZoneId.of("-07")); 
        ZonedDateTime localTime = convert(mstTime, Clock.systemDefaultZone().getZone());
        System.out.println("MST(" + mstTime + ") = " + localTime);
    }
}
故笙诉离歌 2024-11-25 11:21:04

取决于“转换”的真正含义。

它可能就像在格式化程序中设置时区一样简单,并且根本不与日历混淆。

Calendar cal = Calendar.getInstance();

TimeZone tzUTC = TimeZone.getTimeZone( "UTC" );
TimeZone tzPST = TimeZone.getTimeZone( "PST8PDT" );

DateFormat dtfmt = new SimpleDateFormat( "EEE, yyyy-MM-dd KK:mm a z" );

dtfmt.setTimeZone( tzUTC );
System.out.println( "UTC: " + dtfmt.format( cal.getTime() ));

dtfmt.setTimeZone( tzPST );
System.out.println( "PST: " + dtfmt.format( cal.getTime() ));

Depends on what you really mean by "converting".

It MAY be as simple as setting the time zone in the FORMATTER, and not mucking with Calendar at all.

Calendar cal = Calendar.getInstance();

TimeZone tzUTC = TimeZone.getTimeZone( "UTC" );
TimeZone tzPST = TimeZone.getTimeZone( "PST8PDT" );

DateFormat dtfmt = new SimpleDateFormat( "EEE, yyyy-MM-dd KK:mm a z" );

dtfmt.setTimeZone( tzUTC );
System.out.println( "UTC: " + dtfmt.format( cal.getTime() ));

dtfmt.setTimeZone( tzPST );
System.out.println( "PST: " + dtfmt.format( cal.getTime() ));
话少心凉 2024-11-25 11:21:04

这不是答案,但可以帮助尝试生成具有相同时区的日期并应用另一个时区偏移量的人。
当您的应用程序服务器在一个时区运行而数据库在另一个时区运行时,它非常有用。

public static Date toGreekTimezone (Date date) {
  ZoneId greek = ZoneId.of(EUROPE_ATHENS);
  ZonedDateTime greekDate = ZonedDateTime.ofInstant(date.toInstant(), greek);

  ZoneId def = ZoneId.systemDefault();
  ZonedDateTime defDate = greekDate.withZoneSameLocal(def);

  return Date.from(defDate.toInstant());
}

This is not the answer, but could help someone trying to generate dates with same timezone and apply another timezone's offset.
It is useful when your application server is running in one timezone and your database in another.

public static Date toGreekTimezone (Date date) {
  ZoneId greek = ZoneId.of(EUROPE_ATHENS);
  ZonedDateTime greekDate = ZonedDateTime.ofInstant(date.toInstant(), greek);

  ZoneId def = ZoneId.systemDefault();
  ZonedDateTime defDate = greekDate.withZoneSameLocal(def);

  return Date.from(defDate.toInstant());
}
つ低調成傷 2024-11-25 11:21:04

您可以执行类似的操作来获取另一个时区的当前时间。

Calendar japanCal = new GregorianCalendar(TimeZone.getTimeZone("Japan"));
japanCal.setTimeInMillis(local.getTimeInMillis());

You can do something like this to get the current time in another time zone.

Calendar japanCal = new GregorianCalendar(TimeZone.getTimeZone("Japan"));
japanCal.setTimeInMillis(local.getTimeInMillis());
谈情不如逗狗 2024-11-25 11:21:04

这里有一个故事:
我在美国的用户在网页中输入日期。我的服务器将其作为 java.util.Date 对象获取。 Date 对象没有时区的概念。

假设用户输入晚上 11 点(== 伦敦时间凌晨 4 点)。对她来说,现在是美国时间晚上 11 点。
您的服务器收到此消息并将其解释为 JVM 时区的晚上 11 点。
但您需要的是一个代表凌晨 4 点的 Date 对象。

SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String timeStringInUS =  sdf.format("2020-05-04 23:00:00");

SimpleDateFormat dateFormatInUS = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
SimpleDateFormat dateFormatInUK = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

dateFormatInUS.setTimeZone(TimeZone.getTimeZone("America/New_York"));
dateFormatInUK.setTimeZone(TimeZone.getTimeZone("Europe/London"));

Date dateInUS = dateFormatInUS.parse(timeStringInUS);
Date dateInUK = sdf.parse(dateFormatInUK.format(dateInUS));

here a story:
my user in US enters a date in a web page. My server gets this as a java.util.Date object. Date objects have no notion of time zone.

so let's say user entered 11PM(== 4AM london time). For her this was 11PM US time.
Your server gets this and interprets this as 11PM of JVM's timezone.
but what you need is a Date object that represents 4AM.

SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String timeStringInUS =  sdf.format("2020-05-04 23:00:00");

SimpleDateFormat dateFormatInUS = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
SimpleDateFormat dateFormatInUK = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

dateFormatInUS.setTimeZone(TimeZone.getTimeZone("America/New_York"));
dateFormatInUK.setTimeZone(TimeZone.getTimeZone("Europe/London"));

Date dateInUS = dateFormatInUS.parse(timeStringInUS);
Date dateInUK = sdf.parse(dateFormatInUK.format(dateInUS));
内心旳酸楚 2024-11-25 11:21:04
public static String convertTimeBasedOnTimeZoneAndTimePattern(String dateTime,
  String fromTimeZone, String toTimeZone, String originalTimePattern, String timePattern) {

  DateTimeFormatter formatterNew = DateTimeFormatter.ofPattern(timePattern);

  DateTimeFormatter formatter = DateTimeFormatter.ofPattern(originalTimePattern);

  TemporalAccessor temporalAccessor = formatter.parse(dateTime);
  ZoneId z = ZoneId.of(fromTimeZone);
  LocalDateTime localDateTime = LocalDateTime.from(temporalAccessor);
  ZonedDateTime zonedDateTime = ZonedDateTime.of(localDateTime, z);
  Instant instant = Instant.from(zonedDateTime);

  ZonedDateTime fromZonedDateTime = instant.atZone(ZoneId.of(toTimeZone));

  String fromZoneDateTime = fromZonedDateTime.format(formatterNew);

return fromZoneDateTime;}

要将任何时间转换为具有任何时间模式的特定时区(例如:UTC -> 本地时区,反之亦然),您可以使用 java.time 库。

此方法将采用时间模式(原始格式和所需格式)和时区(原始时区和所需时区)将给出字符串作为输出。您可以使用 SimpleDateFormatter 将 String 转换为日期,也可以使用 ZoneDateTime/Instant 类的 parse 方法。

将字符串转换为日期:

public static final DATE_FORMAT="yyyy-MM-dd HH:mm:ss.SSSSS";
public static Date convertStringToDate(String date) {
    SimpleDateFormat formatter = new SimpleDateFormat(DATE_FORMAT);

    Date parsedDate = null;

    try {
      parsedDate = formatter.parse(date);
    } catch (Exception e) {
      throw new DateTimeParseException("Please provide date time in proper format", null, 0, null);
    }
    return parsedDate;
  }

将日期转换为字符串:

public String convertTextDateToDate(Date textDate) {
    // SimpleDateFormat sdf = new SimpleDateFormat("EE MMM dd HH:mm:ss z yyyy", //Locale.ENGLISH);

    SimpleDateFormat date = new SimpleDateFormat(DATE_FORMAT);
    String dateFormatted = date.format(textDate);
    return dateFormatted;
  }
public static String convertTimeBasedOnTimeZoneAndTimePattern(String dateTime,
  String fromTimeZone, String toTimeZone, String originalTimePattern, String timePattern) {

  DateTimeFormatter formatterNew = DateTimeFormatter.ofPattern(timePattern);

  DateTimeFormatter formatter = DateTimeFormatter.ofPattern(originalTimePattern);

  TemporalAccessor temporalAccessor = formatter.parse(dateTime);
  ZoneId z = ZoneId.of(fromTimeZone);
  LocalDateTime localDateTime = LocalDateTime.from(temporalAccessor);
  ZonedDateTime zonedDateTime = ZonedDateTime.of(localDateTime, z);
  Instant instant = Instant.from(zonedDateTime);

  ZonedDateTime fromZonedDateTime = instant.atZone(ZoneId.of(toTimeZone));

  String fromZoneDateTime = fromZonedDateTime.format(formatterNew);

return fromZoneDateTime;}

To convert any time to the specific timezone (for example: UTC -> local timezone and vise versa) with any time pattern you can use java.time library.

This method will take time patterns (original and required format) and timezone (original time zone and required timezone) will give String as output. you can convert String to date by using SimpleDateFormatter or also use parse method of the ZoneDateTime/Instant class.

To convert String to date:

public static final DATE_FORMAT="yyyy-MM-dd HH:mm:ss.SSSSS";
public static Date convertStringToDate(String date) {
    SimpleDateFormat formatter = new SimpleDateFormat(DATE_FORMAT);

    Date parsedDate = null;

    try {
      parsedDate = formatter.parse(date);
    } catch (Exception e) {
      throw new DateTimeParseException("Please provide date time in proper format", null, 0, null);
    }
    return parsedDate;
  }

To convert date to String:

public String convertTextDateToDate(Date textDate) {
    // SimpleDateFormat sdf = new SimpleDateFormat("EE MMM dd HH:mm:ss z yyyy", //Locale.ENGLISH);

    SimpleDateFormat date = new SimpleDateFormat(DATE_FORMAT);
    String dateFormatted = date.format(textDate);
    return dateFormatted;
  }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文