I have a table that has country timezone range
e.g.
Country: Canada
Start Range: -3.5
End Range: -8.0
I have a method that pulls back the start and end range values from the table
I need to convert the system time (UTC) to the country time range.
If I was dealing with whole numbers it would be fine, and would just use the Calendar add regular methods that take int values but my method return doubles
I have:
private Calendar[] setCountryTime( double startRange double endRange) {
Calendar[] clientTimeRange = null;
Date today = new Date();
Calendar cal = Calendar.getInstance();
cal.setTime(today);
Calendar clientStartRange = getCurrentServerTime();
clientStartRange.add(Calendar.HOUR_OF_DAY, //what value here);
clientStartRange.add(Calendar.MINUTE, //what value here);
clientTimeRange[0] = clientStartRange;
Calendar clientEndRange = getCurrentServerTime();
clientEndRange.add(Calendar.HOUR_OF_DAY, //what value here);
clientEndRange.add(Calendar.MINUTE, //what value here);
clientTimeRange[1] = clientEndRange ;
return clientTimeRange;
}
java.time
private static final long HOURS_TO_SECONDS = TimeUnit.HOURS.toSeconds(1);
private static OffsetDateTime[] setCountryTime(double startRange, double endRange) {
ZoneOffset startOffset = hoursToOffset(startRange);
ZoneOffset endOffset = hoursToOffset(endRange);
Instant now = Instant.now();
return new OffsetDateTime[] { now.atOffset(startOffset), now.atOffset(endOffset) };
}
private static ZoneOffset hoursToOffset(double offsetHours) {
long offsetSeconds = Math.round(offsetHours * HOURS_TO_SECONDS);
if (offsetSeconds < ZoneOffset.MIN.getTotalSeconds()
|| offsetSeconds > ZoneOffset.MAX.getTotalSeconds()) {
throw new IllegalArgumentException("Offset too large " + offsetHours);
}
return ZoneOffset.ofTotalSeconds((int) offsetSeconds);
}
Let’s try it:
OffsetDateTime[] canadaTimeRange = setCountryTime(-3.5, -8.0);
System.out.println(Arrays.toString(canadaTimeRange));
Running just now this printed:
[2018-05-23T10:06:47.489234-03:30, 2018-05-23T05:36:47.489234-08:00]
Since we can instantiate a ZoneOffset
from a number of seconds, the main trick is to convert your hours to seconds. The TimeUnit
enum could do that for you if we had only whole hours. We can still use its conversion factor for the multiplication. It makes our intention clearer and the code less error-prone.
The Calendar
class is long outdated and poorly designed. Instead I use java.time
, the modern Java date and time API. It is so much nicer to work with. If you do need Calendar
objects, for example for a legacy API that you cannot change, a conversion can be made.
We are still using Java 7, hence our use of Calendar
EDIT No big problem, java.time
works nicely on Java 6 and 7.
- In Java 8 and later and on newer Android devices (from API level 26, I’m told) the modern API comes built-in.
- In Java 6 and 7 get the ThreeTen Backport, the backport of the new classes (ThreeTen for JSR 310; see the links at the bottom).
- On (older) Android use the Android edition of ThreeTen Backport. It’s called ThreeTenABP. And make sure you import the date and time classes from
org.threeten.bp
with subpackages.
Links
- Oracle tutorial: Date Time explaining how to use
java.time
.
- Java Specification Request (JSR) 310, where
java.time
was first described.
- ThreeTen-Backport project, the backport of
java.time
to Java 6 and 7 (ThreeTen for JSR-310).
- ThreeTenABP, Android edition of ThreeTen Backport
- Question: How to use ThreeTenABP in Android Project, with a very thorough explanation.