5

I am making a diary application for Android and I want to allow the user to select the timezone they are in. Time has always been a area of confusion for me programatically.

I am going to create an enum for the available timezones.

I am going to save date/time entries to a sqlite in long UTC format, then handling offsets and DST programmatically in Java for display purposes.

I am actually aware of Java's limitations when it comes to date/time handling.

Calendar utc = Calendar.getInstance(TimeZone.getTimeZone("UTC")); //returns the current time in UTC format
Long utcLong = utc.getTimeInMillis(); //returns current utc time in long for database insertion

Question 1: How would I apply an offset to it and account for when to apply any additional DST offsets? Because not all timezones observe DST and DST comes into effect at different dates for different timezones.

Question 2: Java's TimeZone class has something like ~800 ids, it would be annoying to the user to have to scroll through ~800 options to find the one that applys to them. Is there a short list available? I'm thinking there are around ~50 useful timezones.

glend
  • 1,592
  • 1
  • 17
  • 36
  • for the record, the code example here doesn't work. it returns local time and just changes the timezone information while not adjusting the time. – glend Jun 03 '17 at 18:41

1 Answers1

7

First of all, I recommend you to not use the Calendar class. It's outdated and has lots of bugs and design issues. This terrible API was replaced by much better ones:

The code below works for all, the only difference is the package names (in Java 8 is java.time and in ThreeTen Backport is org.threeten.bp), but the classes and methods names are the same.

To get the UTC current date/time, the best choice is to use Instant class:

// current date/time in UTC - now() always returns the current instant in UTC
Instant instant = Instant.now();
System.out.println(instant); // 2017-06-03T18:03:55.976Z

// equivalent to calendar.getTimeInMillis(), it returns a long
System.out.println(instant.toEpochMilli()); // 1496513035976

To convert this instant to a timezone, you can use the ZoneId with a ZonedDateTime:

// ZoneId accepts the same IDs used by TimeZone
ZoneId zone = ZoneId.of("America/Sao_Paulo");
// convert instant to timezone
ZonedDateTime z = instant.atZone(zone);
System.out.println(z); // 2017-06-03T15:03:55.976-03:00[America/Sao_Paulo]

// converts back to UTC (returns an Instant)
System.out.println(z.toInstant()); // 2017-06-03T18:03:55.976Z

The code above already takes care of DST changes, so the conversion from and to UTC is straightforward.

Timezone list

You say that you have a list of ~50 "useful" timezones. I don't know what criteria you used to define that list, but what happens if an user is in a timezone that's not in the list?

There are some ideas of timezone-picking user interfaces in this link and here. You can choose one and adapt to your app.

I also suggest to not use (if possible) the 3-letter timezone abbreviations (like CST or PST) because they are ambiguous and not standard. It's better to use the full names (like America/Sao_Paulo or Europe/London) as they are the ones used by Java's APIs (you can get the full list with ZoneId.getAvailableZoneIds()) and they are configured with all DST changes for each zone.

  • I've been looking around a joda-time seems like a popular alternative. have you used that? do you think threeten is better? – glend Jun 03 '17 at 18:06
  • 2
    Jodatime is good **but** it's being discontinued and replaced by the new API's. Threeten is better because it's a backport to the new java 8 API (so a future migration will be easier than if you use jodatime). Even in joda's website it says *Note that Joda-Time is considered to be a largely “finished” project. No major enhancements are planned. If using Java SE 8, please migrate to java.time (JSR-310)*. And if you use java <= 7, use the Threeten backport. So I don't recommend to start a new project with jodatime. –  Jun 03 '17 at 18:12
  • 1
    I've also added some more links to the answer, hope it helps. –  Jun 03 '17 at 18:25
  • 3
    @psycotik The java.time framework is the official successor to Joda-Time. Both projects are led by the same man, Stephen Colebourne. – Basil Bourque Jun 04 '17 at 04:01
  • The back-port may no longer be needed for early Android. Gradle Plugin 4 provides for API desugaring to bring a subset of *java.time* functionality to all versions of Android. – Basil Bourque Jul 09 '20 at 21:33