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

前端 未结 5 772
余生分开走
余生分开走 2021-01-01 19:03

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 08Aug2

相关标签:
5条回答
  • 2021-01-01 19:31

    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();
    
    0 讨论(0)
  • 2021-01-01 19:43

    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

    0 讨论(0)
  • 2021-01-01 19:46

    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));
        }
    
    0 讨论(0)
  • 2021-01-01 19:47

    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

    0 讨论(0)
  • 2021-01-01 19:52

    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; 
    
    0 讨论(0)
提交回复
热议问题