Last active
August 4, 2020 14:50
-
-
Save nimatrueway/ac74e0f6efd2b25396a872633e859121 to your computer and use it in GitHub Desktop.
Runtime's session timezone possible problem
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package classloaders | |
import java.time._ | |
import java.util.TimeZone | |
import java.util.concurrent.TimeUnit | |
import scala.concurrent.duration.Duration | |
object Main { | |
private val dt = LocalDateTime.of(1900, 1, 2, 3, 4, 5) | |
def main(args: Array[String]): Unit = { | |
pprint(dt.atZone(ZoneOffset.UTC)) | |
pprint(dt.atZone(ZoneId.systemDefault())) | |
pprint(dt.atZone(ZoneId.of("GMT+02:00"))) | |
pprint(dt.atZone(simulateRuntime("GMT+02:00"))) // this is expected to yield the same result as the former | |
} | |
private def pprint(time: Any): Unit = { | |
def diff(instant: Instant): String = { | |
((instant.toEpochMilli / 1000) - (dt.atZone(ZoneOffset.UTC).toInstant.toEpochMilli / 1000)).toString | |
} | |
println(time match { | |
case zdt: ZonedDateTime => s"[${diff(zdt.toInstant)}] $zdt" | |
case instant: Instant => s"[${diff(instant)}] $instant" | |
}) | |
} | |
private def simulateRuntime(zoneId: String): ZoneId = { | |
val originalTimeZone = TimeZone.getTimeZone(zoneId) | |
val session = new RuntimeSession() | |
session.setTimeZone(getJavascriptDatetimeOffset(originalTimeZone)) | |
session.getTimeZone.toZoneId | |
} | |
class RuntimeSession { // What we do in runtime | |
var timeZone: TimeZone = _ | |
def getTimeZone: TimeZone = timeZone | |
def setTimeZone(offset: Int): Unit = timeZone = calculateTimeZone(offset) | |
def calculateTimeZone(timezoneOffset: Int): TimeZone = { | |
val zone = TimeZone.getTimeZone("UTC") | |
zone.setRawOffset(timezoneOffset * -1 * 60 * 1000) //Javascript returns timezone offset in negative minutes (so -120 for UTC+2) | |
val roundedOffsetInHours = Math.round(timezoneOffset / 60f * -1) | |
zone.setID("Etc/GMT" + (if (roundedOffsetInHours < 0) roundedOffsetInHours else "+" + roundedOffsetInHours)) | |
// the problem gets solved if we change "Etc/GMT" to "GMT" | |
zone | |
} | |
} | |
def getJavascriptDatetimeOffset(timeZone: TimeZone): Int = { | |
// scale it to javascript's timezone offset (see javascript's ) | |
// (e.g. javascript "new Date().getTimezoneOffset()" returns -120 for CET) | |
timeZone.getRawOffset / (-1 * 60 * 1000) | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
[0] 1900-01-02T03:04:05Z | |
[-1172] 1900-01-02T03:04:05+00:19:32[Europe/Amsterdam] | |
[-7200] 1900-01-02T03:04:05+02:00[GMT+02:00] | |
[7200] 1900-01-02T03:04:05-02:00[Etc/GMT+2] // why the zone offset here is -02:00 ? |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment