How to set offset of a java.util.Date?

假装没事ソ 提交于 2019-12-25 09:22:38

问题


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.

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.

How can I achieve it?


回答1:


You can use SimpleDateFormat's setTimeZone method as below:

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:

    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.




回答2:


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]

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

2016-09-16T12:40+12:00[Pacific/Auckland]

Using java.time

Avoid the troublesome old date-time classes, now supplanted by the java.time classes.

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.

Un-zoned

Parse the input string as a LocalDateTime since it lacks any info about offset-from-UTC or time zone.

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

Understand that without an offset or time zone, this LocalDateTime object has no real meaning. 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

You indicate this date-time was intended to be a moment with an offset-from-UTC of four hours behind UTC (-04:00). So next we apply a ZoneOffset to get a OffsetDateTime object.

Tip: Always include the colon and the minutes and padding zeros in your offset-from-UTC strings. While not required by the ISO 8601 standard, common software libraries and protocols expect the fuller formatting.

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. A time zone is an offset plus a set of rules for handling anomalies such as Daylight Saving Time (DST).

Specify a proper time zone name in the format of 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(!).

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. 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. 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 | ldt: 2016-09-15T20:40 | odt: 2016-09-15T20:40-04:00 | zdt: 2016-09-15T20:40-04:00[America/Puerto_Rico] | zdtKolkata 2016-09-16T06:10+05:30[Asia/Kolkata] | zdtAuckland: 2016-09-16T12:40+12:00[Pacific/Auckland]

About java.time

The java.time framework is built into Java 8 and later. These classes supplant the troublesome old date-time classes such as java.util.Date, .Calendar, & java.text.SimpleDateFormat.

The Joda-Time project, now in maintenance mode, advises migration to java.time.

To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations.

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…).

The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.



来源:https://stackoverflow.com/questions/39557374/how-to-set-offset-of-a-java-util-date

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!