简体   繁体   English

如何设置java.util.Date的偏移量?

[英]How to set offset of a java.util.Date?

I have a Date as a String - 15Sep20162040 , which I have to format it into another format with Timezone as 2016-09-15T20:40:00+0400 . 我有一个日期作为字符串15Sep20162040 ,我必须将其格式化15Sep20162040区为2016-09-15T20:40:00+0400另一种格式。

What I did to do it as follows: 我所做的如下:

import java.text.ParseException;
import java.text.SimpleDateFormat;

public class DateFormatExample {

    private static SimpleDateFormat offsetDateFormat = new SimpleDateFormat(
            "yyyy-MM-dd'T'HH:mm:ssZ");

    private static SimpleDateFormat dateFormatter = new SimpleDateFormat(
            "ddMMMyyyyHHmm");

    public static void main(String[] args) throws ParseException {
        String date = "15Sep20162040";
        String result = offsetDateFormat.format(dateFormatter.parse(date));
        System.out.println(result); // 2016-09-15T20:40:00+0400         

    }
}

Now, I have to modify the output based on timezone difference, for example if difference is +0100 , output should resemble as: 2016-09-15T20:40:00+0100 and if difference is -0200 , output should resemble as: 2016-09-15T20:40:00-0200 . 现在,我必须根据时区差异修改输出,例如,如果差异为+0100 ,则输出应类似于: 2016-09-15T20:40:00+0100 ,如果差异为-0200 ,则输出应类似于: 2016-09-15T20:40:00-0200

How can I achieve it? 我该如何实现?

You can use SimpleDateFormat 's setTimeZone method as below: 您可以使用SimpleDateFormatsetTimeZone方法,如下所示:

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.TimeZone;

public class DateFormatExample {

    private static SimpleDateFormat offsetDateFormat = new SimpleDateFormat(
            "yyyy-MM-dd'T'HH:mm:ssZ");

    private static SimpleDateFormat dateFormatter = new SimpleDateFormat(
            "ddMMMyyyyHHmm");

    public static void main(String[] args) throws ParseException {
        String date = "15Sep20162040";
        String result = offsetDateFormat.format(dateFormatter.parse(date));
        System.out.println(result); // 2016-09-15T20:40:00+0400
        offsetDateFormat.setTimeZone(TimeZone.getTimeZone("GMT-8:00"));
        result = offsetDateFormat.format(dateFormatter.parse(date));
        System.out.println(result);
    }
}

If you simply want to change the timezone at the end of result , please try the following: 如果您只想在result末尾更改时区,请尝试以下操作:

    String offset = "GMT-8:00";
    String date = "15Sep20162040";
    date = date+" "+offset;
    SimpleDateFormat dateFormatter2 = new SimpleDateFormat("ddMMMyyyyHHmm Z");
    SimpleDateFormat offsetDateFormat2 = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ");
    offsetDateFormat2.setTimeZone(TimeZone.getTimeZone(offset));
    String result = offsetDateFormat2.format(dateFormatter2.parse(date));
    System.out.println(result);

Hope this helps. 希望这可以帮助。

tl;dr tl; dr

ZonedDateTime zdt = 
    LocalDateTime.parse ( "15Sep20162040" , 
                          DateTimeFormatter.ofPattern ( "ddMMMyyyyHHmm" )
                                           .withLocale( Locale.English ) 
                        )
                 .atZone ( ZoneId.of ( "America/Puerto_Rico" ) );

2016-09-15T20:40-04:00[America/Puerto_Rico] 2016-09-15T20:40-04:00 [美国/波多黎各]

zdt.atZone( ZoneId.of ( "Pacific/Auckland" ) )  // Same moment viewed through different wall-clock time

2016-09-16T12:40+12:00[Pacific/Auckland] 2016-09-16T12:40 + 12:00 [太平洋/奥克兰]

Using java.time 使用java.time

Avoid the troublesome old date-time classes, now supplanted by the java.time classes. 避免使用麻烦的旧日期时间类,而该类现在已被java.time类取代。

Define a formatting pattern to match your input string. 定义格式模式以匹配您的输入字符串。

String input = "15Sep20162040";
DateTimeFormatter f = DateTimeFormatter.ofPattern ( "ddMMMyyyyHHmm" ).withLocale ( Locale.ENGLISH );

By the way, this is a terrible format for a date-time string. 顺便说一句,这是日期时间字符串的糟糕格式。 It assumes English, abuses English with incorrect abbreviation of month name, and is confusing and ambiguous. 它假定英语,使用不正确的月份名称缩写来滥用英语,并且造成混淆和歧义。 Instead, use the standard ISO 8601 formats when serializing date-time values to text. 而是在将日期时间值序列化为文本时使用标准ISO 8601格式。

Un-zoned 未分区

Parse the input string as a LocalDateTime since it lacks any info about offset-from-UTC or time zone. 将输入字符串解析为LocalDateTime因为它缺少有关自UTC偏移或时区的任何信息。

LocalDateTime ldt = LocalDateTime.parse ( input , f );

Understand that without an offset or time zone, this LocalDateTime object has no real meaning. 请理解,没有偏移量或时区,此LocalDateTime对象没有实际意义。 It represents many possible moments, but not a specific point on the timeline. 它代表许多可能的时刻,但不是时间轴上的特定点。 For example, noon in Auckland NZ is a different moment than noon in Kolkata India which is an earlier moment than noon in Paris France. 例如,新西兰奥克兰的中午不同于印度加尔各答的中午,这比法国巴黎的中午要早。

Assign an offset-from-UTC 分配UTC偏移量

You indicate this date-time was intended to be a moment with an offset-from-UTC of four hours behind UTC (-04:00). 您指示此日期时间是一个相对于UTC偏移 UTC(-04:00)四个小时的时刻。 So next we apply a ZoneOffset to get a OffsetDateTime object. 因此,接下来我们应用ZoneOffset来获取OffsetDateTime对象。

Tip: Always include the colon and the minutes and padding zeros in your offset-from-UTC strings. 提示:始终在与UTC偏移的字符串中包含冒号,分钟和填充零。 While not required by the ISO 8601 standard, common software libraries and protocols expect the fuller formatting. 尽管ISO 8601标准没有要求,但通用软件库和协议要求更完整的格式。

ZoneOffset offset = ZoneOffset.ofHours( -4 ); 
OffsetDateTime odt = ldt.atOffset( offset );

Assign a time zone 分配时区

If by your context you knew of a time zone rather than a mere offset, use a ZoneId to instantiate a ZonedDateTime object. 如果根据您的上下文,您知道的是时区而不是单纯的偏移量,请使用ZoneId实例化ZonedDateTime对象。 A time zone is an offset plus a set of rules for handling anomalies such as Daylight Saving Time (DST) . 时区是一个偏移量以及一组用于处理异常的规则,例如夏令时(DST)

Specify a proper time zone name in the format of continent/region . 请以continent/region的格式指定正确的时区名称 Never use the 3-4 letter abbreviation such as EST or IST as they are not true time zones, not standardized, and not even unique(!). 切勿使用ESTIST等3-4个字母的缩写,因为它们不是真实的时区,不是标准化的,甚至不是唯一的(!)。

ZoneId z = ZoneId.of( "America/Puerto_Rico" );
ZonedDateTime zdt = ldt.atZone( z );

Different time zones 不同时区

Your question is not clear near the end, about changing offsets. 关于更改偏移量,您的问题在年底时还不清楚。 If your goal is to view the date-time through the various lenses of various time zones, you can easily adjust by creating new ZonedDateTime objects. 如果您的目标是通过各个时区的各个镜头查看日期时间,则可以通过创建新的ZonedDateTime对象轻松进行调整。 Assign a different time zone to each. 为每个分配不同的时区。

Note that all these date-time objects (zdt, zKolkata, and zAuckland) represent the same moment, the same point on the timeline. 请注意,所有这些日期时间对象(zdt,zKolkata和zAuckland)都表示同一时刻,时间轴上的同一点。 Each presents a different wall-clock time but for the same simultaneous moment . 每个代表不同的挂钟时间,同时出现相同的时刻

ZoneId zKolkata = ZoneId.of ( "Asia/Kolkata" );
ZonedDateTime zdtKolkata = zdt.withZoneSameInstant ( zKolkata );

ZoneId zAuckland = ZoneId.of ( "Pacific/Auckland" );
ZonedDateTime zdtAuckland = zdt.withZoneSameInstant ( zAuckland );

System.out.println ( "input: " + input + " | ldt: " + ldt + " | odt: " + odt + " | zdt: " + zdt + " | zdtKolkata " + zdtKolkata + " | zdtAuckland: " + zdtAuckland );

Dump to console. 转储到控制台。

input: 15Sep20162040 | 输入:15Sep20162040 | ldt: 2016-09-15T20:40 | ldt:2016-09-15T20:40 | odt: 2016-09-15T20:40-04:00 | odt:2016-09-15T20:40-04:00 | zdt: 2016-09-15T20:40-04:00[America/Puerto_Rico] | zdt:2016-09-15T20:40-04:00 [美国/波多黎各] | zdtKolkata 2016-09-16T06:10+05:30[Asia/Kolkata] | zdtKolkata 2016-09-16T06:10 + 05:30 [亚洲/加尔各答] | zdtAuckland: 2016-09-16T12:40+12:00[Pacific/Auckland] zdtAuckland:2016-09-16T12:40 + 12:00 [Pacific / Auckland]

About java.time 关于java.time

The java.time framework is built into Java 8 and later. java.time框架内置于Java 8及更高版本中。 These classes supplant the troublesome old date-time classes such as java.util.Date , .Calendar , & java.text.SimpleDateFormat . 这些类取代了麻烦的旧日期时间类,例如java.util.Date.Calendarjava.text.SimpleDateFormat

The Joda-Time project, now in maintenance mode , advises migration to java.time. 现在处于维护模式Joda-Time项目建议迁移到java.time。

To learn more, see the Oracle Tutorial . 要了解更多信息,请参见Oracle教程 And search Stack Overflow for many examples and explanations. 并在Stack Overflow中搜索许多示例和说明。

Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport and further adapted to Android in ThreeTenABP (see How to use… ). 大部分的java.time功能后移植到Java 6和7 ThreeTen,反向移植 ,并进一步适应的AndroidThreeTenABP (见如何使用...... )。

The ThreeTen-Extra project extends java.time with additional classes. ThreeTen-Extra项目使用其他类扩展了java.time。 This project is a proving ground for possible future additions to java.time. 该项目为将来可能在java.time中添加内容提供了一个试验场。 You may find some useful classes here such as Interval , YearWeek , YearQuarter , and more. 您可能会在这里找到一些有用的类,例如IntervalYearWeekYearQuarter等。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM