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


79

我想将此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));

使用本地计算机的TimeZone。这是为什么?我知道,当“ new Date()”返回UTC + 0时间时,为什么当您将时间设置为毫秒时,它不再假设该时间是UTC?

是否有可能:

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

在此先感谢您的帮助:D


一个帖子中有太多问题……
Barmaley 2011年

为了清晰起见,使用场景算法第二次问了同样的两个问题,只是第二个问了。感谢您的输入tho:?
travega 2011年

似乎唯一的问题1317816735000L是的时间戳错误2011-10-06 03:35:05 GMT。否则,您的方法是正确的。
augurar '16

1
仅供参考,麻烦的旧日期,时间类,如java.util.Datejava.util.Calendarjava.text.SimpleDateFormat现在的遗产,由取代java.time内置到Java 8和更高等级。请参见Oracle教程
罗勒·布尔克

Answers:


58

对我而言,最简单的方法是:

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()));

1
@Charleston什么是review符合date = sdf.parse(review);
09Q71AO534

1
@Charleston但是SDF中没有这样的方法类型,sdf.parse(DateObject)我正在使用的Java中未定义JDK.1.7
09Q71AO534

对于第二个答案,我感到非常抱歉。我什至没有测试!但是现在它已经过测试并且可以正常工作!
查尔斯顿

1
如何获得实际的日期而不是字符串?
图兰斯·科尔多瓦

1
也许应该是:SimpleDateFormat(“ yyyy-MM-dd hh:mm:ss”)
Marcos

31

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

无论如何我离题!如果您有UTC偏移量(比GMT偏移量更适合在UTC中使用),则可以以毫秒为单位计算时间并将其添加到时间戳中。请注意,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();“
Kanagavelu Sugumar 2012年

3
不好。时区偏移量不是恒定的。这取决于实际日期。
德米特里·特里弗诺夫

1
如何获得实际的日期而不是字符串?
图兰斯·科尔多瓦

@KanagaveluSugumar这里偏移小时
我的

25

与往常一样,我建议您阅读有关Java中日期和时间的文章,以便您理解。

基本思想是,从时代开始,“全部”都在UTC毫秒内完成。这意味着最简单的操作是完全不使用时区,用户的字符串格式除外。

因此,我将跳过您建议的大多数步骤。

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

另外,您可以使用Joda time。我听说这是一个更加直观的日期时间API。


嗨Bringer128,谢谢您的答复,这对我来说似乎很荒谬,没有针对给定时区调整时间戳的直接方法。如果包括所有功能,那么为什么要包含该功能,只要更改格式化字符串中的时区标记...我将尝试使用Joda时间。谢谢
travega 2011年

@travega如果您将时间表示为UTC并使用SimpleDateFormat对其进行格式化,则有一种简单的方法。修改的不仅是“ Z”部分(时区标记),而是整个日期。检查两个不同的SimpleDateFormat对象在设置相同日期格式时是否设置了不同的TimeZones的结果。
Bringer128 2011年

如何获得实际的日期而不是字符串?
图兰斯·科尔多瓦

@TulainsCórdova我想您需要详细解释。您可以创建问题或搜索以找到可以解决您的特定问题的相关问题吗?
Bringer128 '16

19

tl; dr

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格式。只需将中间的SPACE替换为即可T

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

LocalDateTime

现在将其解析为a,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)。因此,我们可以将a指定ZoneId为一个ZonedDateTime而不是一个单纯的偏移量。

指定正确的时区名称。切勿使用3-4字母的缩写,例如EST或,IST因为它们不是真实的时区,不是标准化的,甚至不是唯一的(!)。例如,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日,星期三,格林尼治标准时间)
  • 2011-10-06T01:12:15+13:00[Pacific/Auckland] (2011年10月6日,星期四,01:12:15在新西兰奥克兰)。

产生字串

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

String output = zdt.toString();

对于其他格式,请在堆栈溢出中搜索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.Calendar,和java.text.SimpleDateFormat

现在处于维护模式Joda-Time项目建议迁移到java.time。

要了解更多信息,请参见Oracle教程。并在Stack Overflow中搜索许多示例和说明。

大部分的java.time功能后移植到Java 6和7 ThreeTen,反向移植,并进一步用于安卓ThreeTenABP(见如何使用......)。

ThreeTen-额外项目与其他类扩展java.time。该项目为将来可能在java.time中添加内容打下了基础。你可能在这里找到一些有用的类,如IntervalYearWeekYearQuarter,等。


9

该解决方案实际上非常简单(纯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

1
这是4年前解决的,您的解决方案未添加任何新内容。
travega 2015年

1
我认为这是使用Java 8的新方法,但是回答质量很低。
Przemek

6

看了一下,我认为Java中没有格林尼治标准时间+ 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);

1
嘿克雷格,谢谢您的回覆。Java不支持/不支持ISO时间标准GMT是独立于Java的全球时间标准。时间/日历Apis确实符合标准,GMT + 13指的是NZDT或任何GMT + 12区域中的夏时制。关于您的示例代码,正如我的IP中所述,我希望您的方案可以正常工作。我面临的问题是定义时间戳并输出原始时间戳的准确时区特定变体,而不是代码所执行的当前时间的派生。谢谢T
travega

3

我们可以使用偏移值来处理

 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();
}

测试代码段:

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

输出:1387353270742 1387335270742


2

我尝试过此代码

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

嗨,pratik,谢谢您的输入,但您遗漏了重点。正如我在IP中提到的,我让它为当前时间戳工作。问题在于设置时间戳,然后生成准确的时区特定输出。
travega 2011年

是的,如果您更改时间,它也会起作用。时区已设置为格式对象,因此无论您经过什么时间,都会基于格式对象中指定的时区
Pratik

嗯...我尝试添加:datetime.setTime(Timestamp.valueOf(“ 2011-10-06 03:35:05”)。getTime()); 仍然不起作用。您如何设定时间?
travega 2011年

@Pratik:如何获取AST时区。
Ved Prakash

2

乔达时代

java.util.Date/Calendar类是一团糟,应避免使用。

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

这是使用Joda-Time 2.3库的答案。很容易。

如示例代码中所述,建议您尽可能使用命名时区,以便您的程序可以处理夏令时(DST)和其他异常。

如果T在字符串的中间而不是空格处放置了a ,则可以跳过前两行代码,处理格式化程序以解析字符串。该日期时间构造可以在一个字符串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

2

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

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);
}

1

我们可以从给定日期获取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 "";  
                }
    

我希望这会帮助其他人。谢谢!!


1

一种快速的方法是:

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


1

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

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()));

1
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;
}

请通过日期客户端时区 ,则方法返回服务器时间戳..对JavaScript var _timezone = Intl.DateTimeFormat().resolvedOptions().timeZone;Java中 TimeZone tz = TimeZone.getDefault(); tz.getID()
Sourav巴曼

1

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

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

1

我想提供现代的答案。

您实际上不应该将日期和时间从一个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是存储时间点的一个不错的选择。如果您需要明确指出日期和时间来自格林尼治标准时间,请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格式模式字符串中的s是打印偏移量的一种方法,这可能比打印时区缩写要好,z因为时区缩写通常是模棱两可的。如果需要NZDT(针对新西兰夏令时间),只需放在z那里即可。

你的问题

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

有可能:

  1. 设置对象的时间

不,现代的阶级是一成不变的。您需要从一开始就创建具有所需日期和时间的对象(这具有许多优势,包括线程安全性)。

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

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

  1. 使用新的TimeZone格式化时间戳

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

  1. 返回具有新时区时间的字符串。

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

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

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

使用本地计算机的TimeZone。这是为什么?

这不是您的想法,它很好地显示了旧类中的几个(许多)设计问题。

  • ADate没有时区。仅当您打印它时,它的toString方法才会获取您的本地时区并将其用于呈现字符串。这是真的new Date()。在过去的25年中,这种行为使很多程序员感到困惑。
  • ACalender 具有时区。当您这样做时,它不会改变calendar.setTime(new Date(1317816735000L));

链接

Oracle教程:Date Time,说明如何使用java.time。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.