Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Invalid ID for ZoneOffset

I am trying to convert from java.sql.timestamp to OffsetDateTime so that i can return ISO8601 standard string in my rest api. I am using this code to convert from timestamp to OffsetDateTime

public static OffsetDateTime sqlTimetampeToOffsetDateTime(Timestamp ts, String timeZone)
{
    if (ts == null)
    {
        return null;
    }

    Calendar cal = Calendar.getInstance();
    cal.setTime(ts);
    ZoneOffset offset = ZoneOffset.of(timeZone);
    return OffsetDateTime.of(
            cal.get(Calendar.YEAR),
            cal.get(Calendar.MONTH)+1,
            cal.get(Calendar.DAY_OF_MONTH),
            cal.get(Calendar.HOUR_OF_DAY),
            cal.get(Calendar.MINUTE),
            cal.get(Calendar.SECOND),
            cal.get(Calendar.MILLISECOND)*1000000,
            offset);
}

However, the code fails at ZoneOffset offset = ZoneOffset.of(timezone) for value Europe/Copenhagen.

I used following code to print list of all timezones and i do see Europe/Copenhagen in that list

    Set<String> allZones = ZoneId.getAvailableZoneIds();
    LocalDateTime dt = LocalDateTime.now();

    List<String> zoneList = new ArrayList<String>(allZones);
    Collections.sort(zoneList);

    for (String s : zoneList) {
        ZoneId zone = ZoneId.of(s);
        ZonedDateTime zdt = dt.atZone(zone);
        ZoneOffset offset = zdt.getOffset();
        int secondsOfHour = offset.getTotalSeconds() % (60 * 60);
        String out = String.format("%35s %10s%n", zone, offset);
        System.out.printf(out);
    }

Now I don't understand what is going on. How can i convert java.sql.timestamp to ISO8601 string (i don't care if i have to use OffsetDateTime or not. I would prefer not to use any third party library

http://pastebin.com/eHJKWpAv

like image 834
Em Ae Avatar asked Apr 29 '16 21:04

Em Ae


People also ask

What is the zone ID for UTC?

A ZoneId is used to identify the rules used to convert between an Instant and a LocalDateTime. There are two distinct types of ID: Fixed offsets - a fully resolved offset from UTC/Greenwich, that uses the same offset for all local date-times.

What is ZoneOffset in Java?

ZoneOffset extends ZoneId and defines the fixed offset of the current time-zone with GMT/UTC, such as +02:00. This means that this number represents fixed hours and minutes, representing the difference between the time in current time-zone and GMT/UTC: LocalDateTime now = LocalDateTime.

How do I make the system default ZoneOffset?

The systemDefault() method of the ZoneOffset class in Java is used to return the system default time-zone. Parameters: This method does not accepts any parameters. Return Value: This method returns the system default time-zone.


2 Answers

ZoneOffset only makes sense when dealing with a specific point in time. In Europe/London we currently use either BST or GMT depending on the time of year. However, 100 years ago (give or take), Europe/London didn't have BST. ZoneOffset.of() only retrieves zone offsets from an internal cache which is only populated when ZoneOffset.ofTotalSeconds() is called. This is poorly documented. However, an easy solution exists:

ZoneId.of("Europe/London").getRules().getOffset(Instant.now());

which returns the correct ZoneOffset for Europe/London for right now (e.g. today)

like image 193
Chris Knight Avatar answered Oct 19 '22 22:10

Chris Knight


If you have the ZoneId, it's pretty trivial to use the Instant class to do this:

Timestamp t = new Timestamp(System.currentTimeMillis());

ZoneId zone = ZoneId.of("Europe/Copenhagen");

OffsetDateTime offsetDateTime = ZonedDateTime
    .ofInstant(Instant.ofEpochMilli(t.getTime()), zone)
    .toOffsetDateTime();
like image 30
djmorton Avatar answered Oct 19 '22 22:10

djmorton