Using Joda-Time to get UTC offset for a given date and timezone

会有一股神秘感。 提交于 2020-01-01 04:12:09

问题


I have dates in the format 20Jan2013, 08Aug2012 etc, with their own specific timezones. So for example, 20Jan2013 might have a timezone ID of Australia/Melbourne, and 08Aug2012 might have an ID of Europe/London. What I want to do is, based on these timezones and the dates, calculate the UTC offset for that timezone on the given date. I've come up with this so far:

DateTimeFormatter dtf = DateTimeFormat.forPattern("ZZ");
DateTimeFormatter dtf1 = DateTimeFormat.forPattern("ddMMMYYYY");

DateTimeZone zone = DateTimeZone.forID("Australia/Melbourne");  

DateTime thisDate = dtf1.parseDateTime("30Jul2013");                                            
System.out.println("\nZone: " + thisDate.withZone(zone));

This gives me the output:

Zone: 2013-07-30T00:00:00.000+10:00

This is correct, but I would like to extract just the UTC offset from this, which in this case is +10:00. I've looked for ways to do this but can't find anything. Is there any way I can do this? The only option I see is to convert the output to a String and use the substring method to get the UTC offset.

The above code does take DST (Daylight Saving Time) into account. So for example if I had: DateTime thisDate = dtf1.parseDateTime("30Jan2013");

The output would be: 2013-01-30T00:00:00.000+11:00

(+11:00 at the end instead of +10:00)

So basically all I need to do is find a way to extract +11:00 from 2013-07-30T00:00:00.000+11:00. Please help!


回答1:


Simple Method for Obtaining Timezone Name and Offset in Hours

public static String getCurrentTimeZoneOffset() {
    DateTimeZone tz = DateTimeZone.getDefault();
    Long instant = DateTime.now().getMillis();

    String name = tz.getName(instant);

    long offsetInMilliseconds = tz.getOffset(instant);
    long hours = TimeUnit.MILLISECONDS.toHours( offsetInMilliseconds );
    String offset = Long.toString( hours );

    return name + " (" + offset + " Hours)";
    // Example: "Mountain Standard Time (-7 Hours)"
}

Couple caveats:

  • This gets the default DateTimeZone from JodaTime. You can modify it to accept a specific DateTimeZone that is passed into the method.
  • This returns it in a format like "Mountain Standard Time (-7 Hours)" but you can format it as you see fit quite easily.

Hope that helps.

JP




回答2:


If you just need the timezone offset, use DateTimeZone.forID() to get the time zone and then tz.getOffset(instant) to get the offset to UTC in milliseconds.

It may look odd that you need an instant to calculate the offset to UTC but this is necessary to take Daylight Savings into account as well as changes in the timezone. Yes, countries change their timezones once in a while:

Why does timezone data change?

Timezone settings are adopted locally, and there is no world timezone authority.

EDIT This gives you the correct result:

    DateTimeFormatter dtf1 = DateTimeFormat.forPattern("ddMMMYYYY");

    DateTimeZone zone = DateTimeZone.forID("Australia/Melbourne");  

    DateTime thisDate = dtf1.parseDateTime("30Jul2013").withZone(zone);                                            
    assertEquals( 10 * CommonConstants.MILLISECONDS_PER_HOUR,
        zone.getOffset( thisDate ) );

thisDate.get




回答3:


In order for Joda to give the correct offset, you must provide a datetime instant.Without a datetime instant, it is impossible to calculate the offset since we have different offsets(daylight savings). This is how I would use Joda to get offset in + HH:mm format :

    int offsetInMillis = DateTimeZone.forID(zoneId).getOffset(new DateTime().getMillis());
    String offset = String.format("%02d:%02d", Math.abs(offsetInMillis / 3600000),
            Math.abs((offsetInMillis / 60000) % 60));
    offset = (offsetInMillis >= 0 ? "+" : "-") + offset; 



回答4:


Java 8 introduced better Date and Time handling to address some of the language's previous limitations in that area. A few of my projects have started to use it rather than Joda.

Using the java.time package:

    ZonedDateTime dateTime = LocalDate.of(2013 , 1 , 20).atStartOfDay( ZoneId.of("Australia/Melbourne"));
    ZoneOffset zo = dateTime.getOffset();
    int offset = zo.getTotalSeconds();

    long hours = TimeUnit.SECONDS.toHours(offset);
    long minutes = TimeUnit.SECONDS.toMinutes(offset % 3600);

The hours variable is set to 11 and the minutes to 0.

It also calculates the minutes-offset, for time zones that are partial hours, such as Newfoundland and Labrador in eastern Canada:

ZonedDateTime dateTime = LocalDate.of(2013, 1, 20).atStartOfDay( ZoneId.of("Canada/Newfoundland"));

In this case, the offset is -03:30 (three and a half hours behind UTC), hours is -3 and minutes is -30.

For the String representation, rather than the integer number of hours and minutes, use the ZoneOffset's toString() method. So for the example above, use:

String offsetString = zo.toString();



回答5:


When you know offset and timestamp so in order to get current time you can use

 public static String formatMonthDayMinuteByGivenUtcOffset(long timestamp, int offset) {
        return JODA_FORMATTER.print(createDateTime(timestamp, offset));
    }


来源:https://stackoverflow.com/questions/14602610/using-joda-time-to-get-utc-offset-for-a-given-date-and-timezone

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