java 时区转换

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java 时区转换相关的知识,希望对你有一定的参考价值。

我现在有一个字符串“2012-12-25 08:00:00” 我希望将其转换成为GWT时间,但是现在转换出来的是 “Tue Dec 25 08:00:00 CST 2012”(Date类型) 如何将这个字符串直接转换成为 “Tue Dec 25 08:00:00 GMT 2012”(Date类型)的呢

参考技术A public Date getCST(String strGMT) throws ParseException
DateFormat df = new SimpleDateFormat("EEE, d-MMM-yyyy HH:mm:ss z", Locale.ENGLISH);
return df.parse(strGMT);


public String getGMT(Date dateCST)
DateFormat df = new SimpleDateFormat("EEE, d-MMM-yyyy HH:mm:ss z", Locale.ENGLISH);
df.setTimeZone(TimeZone.getTimeZone("GMT")); // modify Time Zone.
return(df.format(dateCST));

2种方法仅供参考,希望 采纳。
参考技术B Date now = new Date();

SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
sdf.setTimeZone(TimeZone.getTimeZone("GMT+2"));
String snow = sdf.format(now);
System.out.println(snow);
参考技术C String s = "2012-12-25 08:00:00";
SimpleDateFormat sd1 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
SimpleDateFormat sd2 = new SimpleDateFormat("EEE MMM dd HH:mm:ss z yyyy",Locale.ENGLISH);
Date d;
try
d = sd1.parse(s);
sd2.setTimeZone(new SimpleTimeZone(28800000, "GMT"));
System.out.println(sd2.format(d));
catch (ParseException e)
e.printStackTrace();
本回答被提问者采纳
参考技术D 学习了

转换给定时区的日期/时间 - java

【中文标题】转换给定时区的日期/时间 - java【英文标题】:Convert Date/Time for given Timezone - java 【发布时间】:2011-12-01 23:46:58 【问题描述】:

我想将此 GMT 时间戳转换为 GMT+13:

2011-10-06 03:35:05

我尝试了大约 100 种不同的 DateFormat、TimeZone、Date、GregorianCalendar 等组合来尝试完成这项非常基本的任务。

此代码在当前时间执行我想要的操作:

Calendar calendar = new GregorianCalendar(TimeZone.getTimeZone("GMT"));

DateFormat formatter = new SimpleDateFormat("dd MMM yyyy HH:mm:ss z");    
formatter.setTimeZone(TimeZone.getTimeZone("GMT+13"));  

String newZealandTime = formatter.format(calendar.getTime());

但我想要的是设置时间而不是使用当前时间。

我发现任何时候我都尝试这样设置时间:

calendar.setTime(new Date(1317816735000L));

使用本地机器的时区。这是为什么?我知道当“new Date()”返回 UTC+0 时间时,为什么当您以毫秒为单位设置时间时,它不再假定时间为 UTC?

是否可以:

    为对象设置时间(日历/日期/时间戳) (可能)设置初始时间戳的时区(calendar.setTimeZone(...)) 使用新的 TimeZone 格式化时间戳 (formatter.setTimeZone(...))) 返回带有新时区时间的字符串。 (formatter.format(calendar.getTime()))

提前感谢您的帮助:D

【问题讨论】:

一篇文章中的问题太多... 为了清晰起见,使用场景算法第二次询问了第二个相同的 2 个问题。感谢您的输入:? 似乎唯一的问题是1317816735000L2011-10-06 03:35:05 GMT 的错误时间戳。否则你的方法是正确的。 仅供参考,麻烦的旧日期时间类,如 java.util.Datejava.util.Calendarjava.text.SimpleDateFormat 现在是 legacy,被 Java 8 及更高版本中内置的 java.time 类所取代.见Tutorial by Oracle。 【参考方案1】:

对我来说,最简单的方法是:

Calendar calendar = Calendar.getInstance();
calendar.setTime(new Date());
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");

//Here you say to java the initial timezone. This is the secret
sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
//Will print in UTC
System.out.println(sdf.format(calendar.getTime()));    

//Here you set to your timezone
sdf.setTimeZone(TimeZone.getDefault());
//Will print on your default Timezone
System.out.println(sdf.format(calendar.getTime()));

【讨论】:

@Charleston review 行中的date = sdf.parse(review); 是什么 @Charleston 但是 SDF 中没有这样的方法类型,sdf.parse(DateObject) 没有在我使用的 java 中定义JDK.1.7 我对我的第二个回答感到非常抱歉。我什至没有测试它!但现在它已经过测试并且可以正常工作了! 你如何得到一个实际的日期而不是一个字符串? 也许应该是:SimpleDateFormat("yyyy-MM-dd hh:mm:ss")【参考方案2】:

了解计算机时间的工作原理非常重要。话虽如此,我同意如果创建 API 来帮助您像实时一样处理计算机时间,那么它应该以允许您像实时一样对待它的方式工作。在大多数情况下,情况确实如此,但确实存在一些需要注意的重大疏忽。

反正我跑题了!!如果您有 UTC 偏移量(在 UTC 中工作比 GMT 偏移量更好),您可以以毫秒为单位计算时间并将其添加到您的时间戳中。请注意,SQL 时间戳可能与 Java 时间戳不同,因为计算历元的时间的方式并不总是相同 - 取决于数据库技术和操作系统。

我建议您使用 System.currentTimeMillis() 作为您的时间戳,因为这些可以在 java 中更一致地处理,而无需担心将 SQL 时间戳转换为 java Date 对象等。

要计算您的偏移量,您可以尝试以下方法:

Long gmtTime =1317951113613L; // 2.32pm NZDT
Long timezoneAlteredTime = 0L;

if (offset != 0L) 
    int multiplier = (offset*60)*(60*1000);
    timezoneAlteredTime = gmtTime + multiplier;
 else 
    timezoneAlteredTime = gmtTime;


Calendar calendar = new GregorianCalendar();
calendar.setTimeInMillis(timezoneAlteredTime);

DateFormat formatter = new SimpleDateFormat("dd MMM yyyy HH:mm:ss z");

formatter.setCalendar(calendar);
formatter.setTimeZone(TimeZone.getTimeZone(timeZone));

String newZealandTime = formatter.format(calendar.getTime());

希望对你有帮助!

【讨论】:

@user726478 当我们知道时区字符串时这是否正确? long timezoneAlteredTime = gmtTime + TimeZone.getTimeZone("Asia/Calcutta").getRawOffset();" 不好。时区偏移不是恒定的。这取决于实际日期。 你如何得到一个实际的日期而不是一个字符串? @KanagaveluSugumar 这里的偏移量是小时【参考方案3】:

与往常一样,我建议您阅读 this article 了解 Java 中的日期和时间,以便您理解它。

基本思想是“在幕后”,自纪元以来,一切都在 UTC 毫秒内完成。这意味着如果您完全不使用时区进行操作,则最简单,但用户的字符串格式除外。

因此,我会跳过您建议的大部分步骤。

    为对象(日期、日历等)设置时间。 在格式化程序对象上设置时区。 从格式化程序返回一个字符串。

或者,您可以使用Joda time。我听说它是​​一个更直观的日期时间 API。

【讨论】:

嗨,Bringer128 感谢您的回复,对我来说,没有直接的方法来调整给定时区的时间戳,这对我来说似乎很荒谬。如果它所做的只是改变格式化字符串中的时区标签,为什么还要包含该功能......我将尝试 Joda time。谢谢 @travega 如果您将时间表示为 UTC 并使用 SimpleDateFormat 格式化,则有一种简单的方法。不仅仅是“Z”部分(时区标签)被修改,整个日期都会被修改。检查两个不同的 SimpleDateFormat 对象在格式化相同日期时设置不同 TimeZone 的结果。 你如何得到一个实际的日期而不是一个字符串? @TulainsCórdova 我认为您需要更详细地解释。您可以创建一个问题或搜索以查找可能解决您的特定问题的相关问题吗?【参考方案4】:

tl;博士

Instant.ofEpochMilli( 1_317_816_735_000L )
    .atZone( ZoneId.of( "Pacific/Auckland" ) )
    .format( DateTimeFormatter.ofLocalizedDateTime( FormatStyle.MEDIUM ).withLocale( new Locale( "en" , "NZ" ) ) )

……还有……

LocalDateTime.parse( "2011-10-06 03:35:05".replace( " " , "T" ) )
    .atZone( ZoneId.of( "Pacific/Auckland" ) )

java.time

问题和大多数答案使用 Java 最早版本中过时的旧日期时间类。事实证明,这些旧课程既麻烦又令人困惑。避开他们。而是使用 java.time 类。

ISO 8601

您的输入字符串几乎采用标准 ISO 8601 格式。只需将中间的空格替换为T

String input = "2011-10-06 03:35:05".replace( " " , "T" );

LocalDateTime

现在解析为LocalDateTime,因为输入缺少任何关于从UTC 偏移或时区的信息。 LocalDateTime 没有偏移量和时区的概念,所以它确实代表时间线上的实际时刻。

LocalDateTime ldt = LocalDateTime.parse( input );

ZoneOffset

您似乎是在说,从业务上下文中您知道此字符串的目的是表示比 UTC 早 13 小时的时刻。所以我们实例化一个ZoneOffset

ZoneOffset offset = ZoneOffset.ofHours( 13 ); // 13 hours ahead of UTC, in the far east of the globe.

OffsetDateTime

应用它来获取OffsetDateTime 对象。这成为时间线上的一个实际时刻。

OffsetDateTime odt = ldt.atOffset( offset);

ZoneId

但是你提到了新西兰。所以你有一个特定的时区。时区是 UTC 的偏移量加上一组用于处理异常情况的规则,例如夏令时 (DST)。所以我们可以将ZoneId 指定为ZonedDateTime 而不仅仅是偏移量。

指定proper time zone name。切勿使用 3-4 个字母的缩写,例如 ESTIST,因为它们不是真正的时区,不是标准化的,甚至不是唯一的(!)。例如,Pacific/Auckland

ZoneId z = ZoneId.of( "Pacific/Auckland" );

ZonedDateTime

申请ZoneId

ZonedDateTime zdt = ldt.atZone( z );

您可以轻松地在时间轴上的同一时刻调整到另一个区域。

ZoneId zParis = ZoneId.of( "Europe/Paris" );
ZonedDateTime zdtParis = zdt.withZoneSameInstant( zParis );  // Same moment in time, but seen through lens of Paris wall-clock time.

从纪元开始计数

我强烈建议不要将日期时间值作为从纪元开始的计数来处理,例如从 1970 UTC 开始的毫秒数。但如果必须,请从这样的号码创建一个Instant

Instant instant = Instant.ofEpochMilli( 1_317_816_735_000L );

然后根据需要分配一个如上所示的时区,以远离 UTC。

ZoneId z = ZoneId.of( "Pacific/Auckland" );
ZonedDateTime zdt = instant.atZone( z );

1_317_816_735_000L 的值是:

2011-10-05T12:12:15Z(格林威治标准时间 2011 年 10 月 5 日星期三 12:12:15) 2011-10-06T01:12:15+13:00[Pacific/Auckland](2011 年 10 月 6 日星期四 01:12:15,新西兰奥克兰)。

生成字符串

要生成标准ISO 8601 格式的字符串,只需调用toString。请注意,ZonedDateTime 通过在方括号中附加时区名称来明智地扩展标准格式。

String output = zdt.toString();

对于其他格式,请在 Stack Overflow 中搜索 DateTimeFormatter 类。已经覆盖很多次了。

指定FormatStyleLocale

Locale l = new Locale( "en" , "NZ" );
DateTimeFormatter f = DateTimeFormatter.ofLocalizedDateTime( FormatStyle.MEDIUM ).withLocale( l );
String output = zdt.format( f );

请注意,时区与语言环境无关。您可以使用日语和文化规范显示 Europe/Paris 日期时间,或使用葡萄牙语和巴西文化规范显示 Asia/Kolkata 日期时间。

关于java.time

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

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

要了解更多信息,请参阅Oracle Tutorial。并在 Stack Overflow 上搜索许多示例和解释。

大部分 java.time 功能在ThreeTen-Backport 中向后移植到Java 6 和7,并进一步适应ThreeTenABP 中的Android(参见How to use…)。

ThreeTen-Extra 项目通过附加类扩展了 java.time。该项目是未来可能添加到 java.time 的试验场。您可以在这里找到一些有用的类,例如IntervalYearWeekYearQuarter 等等。

【讨论】:

【参考方案5】:

解决方案其实很简单(纯粹的、简单的Java):

System.out.println(" NZ Local Time: 2011-10-06 03:35:05");
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
LocalDateTime localNZ = LocalDateTime.parse("2011-10-06 03:35:05",formatter);
ZonedDateTime zonedNZ = ZonedDateTime.of(localNZ,ZoneId.of("+13:00"));
LocalDateTime localUTC = zonedNZ.withZoneSameInstant(ZoneId.of("UTC")).toLocalDateTime();
System.out.println("UTC Local Time: "+localUTC.format(formatter));

输出是:

 NZ Local Time: 2011-10-06 03:35:05
UTC Local Time: 2011-10-05 14:35:05

【讨论】:

这是 4 年前解决的问题,您的解决方案没有添加任何新内容。 我认为这是使用 Java 8 的新方法,但回答质量低。【参考方案6】:

看了一下,我认为 Java 中没有 GMT + 13 的时区。所以我认为你必须使用:

Calendar calendar = Calendar.getInstance();
//OR Calendar.getInstance(TimeZone.getTimeZone("GMT"));

calendar.set(Calendar.HOUR_OF_DAY, calendar.get(Calendar.HOUR_OF_DAY)+13);

Date d = calendar.getTime();

(如果有则将“GMT”更改为该时区并删除第二行代码)

SimpleDateFormat df = new SimpleDateFormat();
df.setTimeZone(TimeZone.getTimeZone("GMT+13"));
System.out.println(df.format(c.getTime()));

如果你想设置一个特定的时间/日期,你也可以使用:

    calendar.set(Calendar.DATE, 15);
calendar.set(Calendar.MONTH, 3);
calendar.set(Calendar.YEAR, 2011);
calendar.set(Calendar.HOUR_OF_DAY, 13); 
calendar.set(Calendar.MINUTE, 45);
calendar.set(Calendar.SECOND, 00);

【讨论】:

嗨,克雷格,感谢您的回复。 Java 不支持/不支持 ISO 时间标准 GMT 是独立于 java 调节的全球时间标准。时间/日历 API 确实符合标准,GMT+13 指的是任何 GMT+12 区域中的 NZDT 或夏令时。关于您的示例代码,如我的 IP 中所述,我的方案可以正常工作。我面临的问题是定义时间戳并输出原始时间戳的准确时区特定变体,而不是您的代码所做的当前时间的推导。谢谢T【参考方案7】:

我们可以通过使用偏移值来处理这个问题

 public static long convertDateTimeZone(long lngDate, String fromTimeZone,
        String toTimeZone)
    TimeZone toTZ = TimeZone.getTimeZone(toTimeZone);
    Calendar toCal = Calendar.getInstance(toTZ);        

    TimeZone fromTZ = TimeZone.getTimeZone(fromTimeZone);
    Calendar fromCal = Calendar.getInstance(fromTZ);
    fromCal.setTimeInMillis(lngDate);
    toCal.setTimeInMillis(fromCal.getTimeInMillis()
            + toTZ.getOffset(fromCal.getTimeInMillis())
            - TimeZone.getDefault().getOffset(fromCal.getTimeInMillis()));      
    return toCal.getTimeInMillis();

测试代码sn-p:

 System.out.println(new Date().getTime())
 System.out.println(convertDateTimeZone(new Date().getTime(), TimeZone
                .getDefault().getID(), "EST"));

输出: 1387353270742 1387335270742

【讨论】:

【参考方案8】:

我试过这段代码

try
            SimpleDateFormat sdf = new SimpleDateFormat("dd-MM-yyyy hh:mm:ss Z");
            Date datetime = new Date();

            System.out.println("date "+sdf.format(datetime));

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

            System.out.println("GMT "+ sdf.format(datetime));

            sdf.setTimeZone(TimeZone.getTimeZone("GMT+13"));

            System.out.println("GMT+13 "+ sdf.format(datetime));

            sdf.setTimeZone(TimeZone.getTimeZone("UTC"));

            System.out.println("utc "+sdf.format(datetime));

            Calendar calendar = new GregorianCalendar(TimeZone.getTimeZone("GMT"));

            DateFormat formatter = new SimpleDateFormat("dd MMM yyyy HH:mm:ss z");    
            formatter.setTimeZone(TimeZone.getTimeZone("GMT+13"));  

            String newZealandTime = formatter.format(calendar.getTime());

            System.out.println("using calendar "+newZealandTime);

        catch (Exception e) 
            // TODO Auto-generated catch block
            e.printStackTrace();
        

得到这个结果

date 06-10-2011 10:40:05 +0530
GMT 06-10-2011 05:10:05 +0000 // here getting 5:10:05
GMT+13 06-10-2011 06:10:05 +1300 // here getting 6:10:05
utc 06-10-2011 05:10:05 +0000
using calendar 06 Oct 2011 18:10:05 GMT+13:00

【讨论】:

您好,谢谢您的输入,但您没有抓住重点。正如我的 IP 中提到的,我让它适用于当前的时间戳。问题在于设置时间戳,然后生成准确的时区特定输出。 是的,如果您更改时间,它也可以工作。时区已设置为格式对象,因此无论您传递什么时间,都将基于格式对象中指定的时区 Hmmmm... 我尝试添加: datetime.setTime(Timestamp.valueOf("2011-10-06 03:35:05").getTime());它仍然不起作用。当你设置时间时,你认为它是如何工作的? @Pratik:我如何获得 AST 时区。【参考方案9】:

我们可以获取给定日期的 UTC/GMT 时间戳。

/**
 * Get the time stamp in GMT/UTC by passing the valid time (dd-MM-yyyy HH:mm:ss)
 */
public static long getGMTTimeStampFromDate(String datetime) 
    long timeStamp = 0;
    Date localTime = new Date();

    String format = "dd-MM-yyyy HH:mm:ss";
    SimpleDateFormat sdfLocalFormat = new SimpleDateFormat(format);
    sdfLocalFormat.setTimeZone(TimeZone.getDefault());

    try 

        localTime = (Date) sdfLocalFormat.parse(datetime); 

        Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("UTC"),
                Locale.getDefault());
        TimeZone tz = cal.getTimeZone();

        cal.setTime(localTime);

        timeStamp = (localTime.getTime()/1000);
        Log.d("GMT TimeStamp: ", " Date TimegmtTime: " + datetime
                + ", GMT TimeStamp : " + localTime.getTime());

     catch (Exception e) 
        // TODO Auto-generated catch block
        e.printStackTrace();
    

    return timeStamp;


它将根据过去的日期返回UTC时间。

我们可以像UTC时间戳一样将当前日期和时间反转(反之亦然)

    public static String getLocalTimeFromGMT(long gmtTimeStamp) 
             try
                    Calendar calendar = Calendar.getInstance();
                    TimeZone tz = TimeZone.getDefault();
                    calendar.setTimeInMillis(gmtTimeStamp * 1000);
    //              calendar.add(Calendar.MILLISECOND, tz.getOffset(calendar.getTimeInMillis())); 
                    SimpleDateFormat sdf = new SimpleDateFormat("dd-MM-yyyy HH:mm:ss");
                    Date currenTimeZone = (Date) calendar.getTime();
                    return sdf.format(currenTimeZone);
                catch (Exception e) 
                
                return "";  
            

我希望这对其他人有所帮助。谢谢!!

【讨论】:

【参考方案10】:

乔达时间

java.util.Date/Calendar 类很乱,应该避免。

更新:Joda-Time 项目处于维护模式。团队建议迁移到 java.time 类。

这是您使用 Joda-Time 2.3 库的答案。很简单。

如示例代码中所述,我建议您尽可能使用命名时区,以便您的编程可以处理 Daylight Saving Time (DST) 和其他异常情况。

如果您在字符串中间放置了T 而不是空格,则可以跳过前两行代码,处理格式化程序来解析字符串。 DateTime 构造函数可以采用ISO 8601 格式的字符串。

// © 2013 Basil Bourque. This source code may be used freely forever by anyone taking full responsibility for doing so.
// import org.joda.time.*;
// import org.joda.time.format.*;

// Parse string as a date-time in UTC (no time zone offset).
DateTimeFormatter formatter = org.joda.time.format.DateTimeFormat.forPattern( "yyyy-MM-dd' 'HH:mm:ss" );
DateTime dateTimeInUTC = formatter.withZoneUTC().parseDateTime( "2011-10-06 03:35:05" );

// Adjust for 13 hour offset from UTC/GMT.
DateTimeZone offsetThirteen = DateTimeZone.forOffsetHours( 13 );
DateTime thirteenDateTime = dateTimeInUTC.toDateTime( offsetThirteen );

// Hard-coded offsets should be avoided. Better to use a desired time zone for handling Daylight Saving Time (DST) and other anomalies.
// Time Zone list… http://joda-time.sourceforge.net/timezones.html
DateTimeZone timeZoneTongatapu = DateTimeZone.forID( "Pacific/Tongatapu" );
DateTime tongatapuDateTime = dateTimeInUTC.toDateTime( timeZoneTongatapu );

转储这些值...

System.out.println( "dateTimeInUTC: " + dateTimeInUTC );
System.out.println( "thirteenDateTime: " + thirteenDateTime );
System.out.println( "tongatapuDateTime: " + tongatapuDateTime );

运行时……

dateTimeInUTC: 2011-10-06T03:35:05.000Z
thirteenDateTime: 2011-10-06T16:35:05.000+13:00
tongatapuDateTime: 2011-10-06T16:35:05.000+13:00

【讨论】:

【参考方案11】:

我想提供现代答案。

您不应该真的想将日期和时间从一个 GMT 偏移量的字符串转换为一个不同的 GMT 偏移量和不同格式的字符串。而是在您的程序中保留一个瞬间(一个时间点)作为适当的日期时间对象。只有当您需要提供字符串输出时,才将您的对象格式化为所需的字符串。

java.time

解析输入

    DateTimeFormatter formatter = new DateTimeFormatterBuilder()
            .append(DateTimeFormatter.ISO_LOCAL_DATE)
            .appendLiteral(' ')
            .append(DateTimeFormatter.ISO_LOCAL_TIME)
            .toFormatter();

    String dateTimeString = "2011-10-06 03:35:05";
    Instant instant = LocalDateTime.parse(dateTimeString, formatter)
            .atOffset(ZoneOffset.UTC)
            .toInstant();

对于大多数用途,Instant 是存储时间点的不错选择。如果您需要明确说明日期和时间来自 GMT,请改用OffsetDateTime

转换、格式化和打印输出

    ZoneId desiredZone = ZoneId.of("Pacific/Auckland");
    Locale desiredeLocale = Locale.forLanguageTag("en-NZ");
    DateTimeFormatter desiredFormatter = DateTimeFormatter.ofPattern(
            "dd MMM uuuu HH:mm:ss OOOO", desiredeLocale);

    ZonedDateTime desiredDateTime = instant.atZone(desiredZone);
    String result = desiredDateTime.format(desiredFormatter);
    System.out.println(result);

这个打印出来的:

2011 年 10 月 6 日 16:35:05 GMT+13:00

我指定了太平洋/奥克兰时区,而不是您提到的偏移量,+13:00。我知道你想要新西兰时间,而太平洋/奥克兰更好地告诉读者这一点。时区还考虑了夏令时 (DST),因此您无需在自己的代码中考虑这一点(大多数情况下)。

由于Oct 是英文的,因此最好为格式化程序提供明确的语言环境。 GMT 也可能是本地化的,但我认为它只会在所有语言环境中打印 GMT

格式模式字符串中的OOOO 是打印偏移量的一种方式,这可能比打印您从z 获得的时区缩写更好,因为时区缩写通常不明确。如果您想要NZDT(新西兰夏令时间),只需将z 放在那里即可。

您的问题

我将回答您有关 java.time 中现代类的编号问题。

可以:

    为对象设置时间

不,现代类是不可变的。您需要从一开始就创建一个具有所需日期和时间的对象(这有很多优点,包括线程安全)。

    (可能)设置初始时间戳的时区

我在代码中使用的atZone 方法返回具有指定时区的ZonedDateTime。其他日期时间类也有类似的方法,有时称为atZoneSameInstant 或其他名称。

    使用新时区格式化时间戳

使用 java.time 转换为新时区和格式化是两个不同的步骤,如图所示。

    返回带有新时区时间的字符串。

是的,如图所示转换为所需的时区并按所示格式化。

我发现任何时候我都尝试这样设置时间:

calendar.setTime(new Date(1317816735000L));

使用本地机器的时区。这是为什么呢?

这不是你想的那样,它很好地展示了旧类的几个(许多)设计问题。

Date 没有时区。只有当您打印它时,它的toString 方法才会获取您的本地时区并将其用于呈现字符串。 new Date() 也是如此。在过去的 25 年里,这种行为让很多很多程序员感到困惑。 Calender有一个时区。 calendar.setTime(new Date(1317816735000L)); 不会改变。

链接

Oracle tutorial: Date Time 解释如何使用 java.time。

【讨论】:

【参考方案12】:

显示所有时区的日期和时间

import java.util.Calendar;
import java.util.TimeZone;
import java.text.DateFormat;
import java.text.SimpleDateFormat;



static final String ISO8601 = "yyyy-MM-dd'T'HH:mm:ssZ";
DateFormat dateFormat = new SimpleDateFormat(ISO8601);
Calendar c = Calendar.getInstance();
String formattedTime;
for (String availableID : TimeZone.getAvailableIDs()) 
    dateFormat.setTimeZone(TimeZone.getTimeZone(availableID));
    formattedTime = dateFormat.format(c.getTime());
    System.out.println(formattedTime + " " + availableID);

【讨论】:

【参考方案13】:

快速的方法是:

String dateText ="Thu, 02 Jul 2015 21:51:46";
long hours = -5; // time difference between places

DateTimeFormatter formatter = DateTimeFormatter.ofPattern(E, dd MMM yyyy HH:mm:ss, Locale.ENGLISH);     
LocalDateTime date = LocalDateTime.parse(dateText, formatter);        
date = date.with(date.plusHours(hours));

System.out.println("NEW DATE: "+date);

输出

新日期:2015-07-02T16:51:46

【讨论】:

【参考方案14】:

您的方法无需任何修改即可工作。

Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
// Timestamp for 2011-10-06 03:35:05 GMT
calendar.setTime(new Date(1317872105000L));

DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss z"); 
formatter.setTimeZone(TimeZone.getTimeZone("GMT+13"));

// Prints 2011-10-06 16:35:05 GMT+13:00
System.out.println(formatter.format(calendar.getTime()));

【讨论】:

【参考方案15】:
public Timestamp convertLocalTimeToServerDatetime(String dt,String timezone)

    String clientDnT = dt ;// "2017-06-01 07:20:00";
    try
    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    Date date = sdf.parse(clientDnT);
    TimeZone tz = TimeZone.getTimeZone(timezone.trim()); // get time zone of user
    sdf.setTimeZone(tz);

    // Convert to servertime zone 
    SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    TimeZone tzInAmerica = TimeZone.getDefault();
    sdf1.setTimeZone(tzInAmerica);

    // assign date to date
    String serverDate = sdf1.format(date);

    // Convert to servertime zone to Timestamp
    Date date2 =  sdf.parse(serverDate);
    Timestamp tsm = new Timestamp(date2.getTime());
    return  tsm;
    
    catch(Exception e)
        System.err.println(e);
    

    return null;

【讨论】:

请传递 dateclient timezone ,然后方法返回服务器 Timestamp .. for javascript var _timezone = Intl.DateTimeFormat().resolvedOptions().timeZone; 和 在java中 TimeZone tz = TimeZone.getDefault(); tz.getID()【参考方案16】:

查找具有两个不同时区的持续时间或时间间隔

import org.joda.time.DateTime, Period, PeriodType

val s1 = "2019-06-13T05:50:00-07:00"
val s2 = "2019-10-09T11:30:00+09:00"    

val period = new Period(DateTime.parse(s1), DateTime.parse(s2), PeriodType dayTime())

period.getDays
period.getMinutes
period.getHours

输出 周期 = P117DT13H40M

days = 117
minutes = 40
hours = 13

【讨论】:

以上是关于java 时区转换的主要内容,如果未能解决你的问题,请参考以下文章

如何在java中使用日光将日期格式从一个时区转换为另一种时区[重复]

Java - 日期时区转换

Java时间格式转换,如何获得时区?

转换给定时区的日期/时间 - java

Java不同时区(timezone)之间时间转换

在 Java 中获取时区的夏令时转换日期