import ceylon.language { sys = system } import ceylon.time { Instant } import ceylon.time.base { ms = milliseconds } import ceylon.time.iso8601 { parseTimeZone } "The interface representing a timezone." shared interface TimeZone of OffsetTimeZone | RuleBasedTimezone { "Returns offset in milliseconds of the specified instant according to this time zone." shared formal Integer offset(Instant instant); } "A simple time zone with a constant offset from UTC." shared class OffsetTimeZone(offsetMilliseconds) satisfies TimeZone { "The value that represents this constant offset in milliseconds." shared Integer offsetMilliseconds; "Returns offset in milliseconds of the specified instant according to this time zone. This implementation always returns a constant offset." shared actual Integer offset(Instant instant) => offsetMilliseconds; "Returns _true_ if given value is same type and offset milliseconds." shared actual Boolean equals( Object other ) { if ( is OffsetTimeZone other ) { return this.offsetMilliseconds == other.offsetMilliseconds; } return false; } "This implementation respect the constraint that if `x==y` then `x.hash==y.hash`." shared actual Integer hash { value prime = 31; value result = 7; return prime * result + offsetMilliseconds.hash; } "Returns ISO-8601 formatted String representation of this _time of day_.\n https://en.wikipedia.org/wiki/ISO_8601#Time_offsets_from_UTC" shared default actual String string { value offsetHours = ((offsetMilliseconds.magnitude / ms.perHour)).string.padLeading(2, '0'); value offsetMinutes = ((offsetMilliseconds.magnitude % ms.perHour) / ms.perMinute).string.padLeading(2, '0'); if (offsetMilliseconds >= 0) { return "+``offsetHours``:``offsetMinutes``"; } else { return "-``offsetHours``:``offsetMinutes``"; } } } "This represents offsets based on daylight saving time." shared interface RuleBasedTimezone satisfies TimeZone { //TODO: Implement complex rule based time zones } "Common utility methods for getting time zone instances." shared object timeZone { "Current system time zone." shared object system extends OffsetTimeZone(sys.timezoneOffset) {} "Coordinated Universal Time (UTC) time zone." shared object utc extends OffsetTimeZone(0) { "Returns ISO-8601 formatted String representation of this _time of day_.\n https://en.wikipedia.org/wiki/ISO_8601#Time_offsets_from_UTC" shared actual String string = "Z"; } "Parses input string and returns appropriate time zone. Currently it accepts only ISO-8601 time zone offset patterns: ±`[hh]:[mm]`, ±`[hh][mm]`, and ±`[hh]`. In addition, the special code `Z` is recognized as a shorthand for `+00:00`." shared TimeZone? parse(String zone) { return parseTimeZone(zone); } "Represents fixed timeZone created based on given values." shared OffsetTimeZone offset(Integer hours, Integer minutes = 0, Integer milliseconds = 0) { value offsetMilliseconds = hours * ms.perHour + minutes * ms.perMinute + milliseconds; assert (-12 * ms.perHour <= offsetMilliseconds <= 12 * ms.perHour); if (offsetMilliseconds == 0) { return utc; } return OffsetTimeZone( offsetMilliseconds ); } }