Самый простой способ рассчитать смещение между двумя часовыми поясами Scala / Java - PullRequest
0 голосов
/ 11 сентября 2018

Не могу найти хорошего ответа, как легко рассчитать смещение часового пояса для данного момента времени в Scala / Java.

Дано:

  • дата со временем
  • часовой пояс 1
  • часовой пояс 2

Требования: рассчитать смещение для конкретной даты в часовом поясе 1, необходимое для перемещения этой даты в часовой пояс 2.

Пример:

datetime = 2017-10-23 00:00:00 в America/Los_Angeles часовой пояс 1,

часовой пояс 2 = Europe/Paris

Смещение должно равняться +9, можетиспользоваться для перемещения даты из часового пояса 1 в часовой пояс 2.

Ответы [ 3 ]

0 голосов
/ 11 сентября 2018
  import java.time._
  val date: LocalDate = ???
  val zone1: ZoneId = ???
  val zone2: ZoneId = ???

  val duration: Duration = Duration.between(date.atStartOfDay(zone1), date.atStartOfDay(zone2))

Затем вы можете извлечь то, что вам нужно из продолжительности, наиболее вероятно, .getHours

0 голосов
/ 11 сентября 2018

Разве это не делает это?

import java.time.{LocalDateTime, ZoneId}
import java.time.temporal.ChronoUnit

val dateOfInterest = LocalDateTime.parse("2020-02-02T12:00")

ChronoUnit.HOURS.between(dateOfInterest.atZone(ZoneId.of("Europe/Paris"))
                        ,dateOfInterest.atZone(ZoneId.of("America/Los_Angeles")))
//res0: Long = 9
0 голосов
/ 11 сентября 2018

Насколько я нашел, самый простой способ - это вычислить смещение по GMT для каждого часового пояса и затем суммировать их:

package dates;

import java.time.ZoneId
import java.util.TimeZone
import java.util.concurrent.TimeUnit

 /**
    * Returns timezone GMT delta offset for given point of time.
    */
  def timezoneOffset(millis: Long, tz: ZoneId): Int = {
    TimeUnit.MILLISECONDS.toHours(TimeZone.getTimeZone(tz).getOffset(millis)).toInt
  }

/**
    * Returns offset required to move `millis` from `baseTz` to `targetTz`:
    *
    * @example
    *          PDT(Los_Angeles) is -7 from GMT
    *          EDT(Paris) is +2 from GMT
    *
    *          timezoneOffsetBetween(millisInPdt, PDT, EDT) == +9
    *          timezoneOffsetBetween(millisInEdt, EDT, PDT) == -9
    */
  def timezoneOffsetBetween(millis: Long, baseTz: ZoneId, targetTz: ZoneId): Int = {
    -(timezoneOffset(millis, baseTz) - timezoneOffset(millis, targetTz))
  }

Вот тестовые случаи:

package dates;

import java.time.{ZoneId, ZonedDateTime}

import org.scalatest.{FreeSpec, Matchers}

class DateSpec extends FreeSpec with Matchers {

  val laTz = ZoneId.of("America/Los_Angeles")
  val gmtTz = ZoneId.of("GMT")
  val sydneyTz = ZoneId.of("Australia/Sydney")
  val parisTz = ZoneId.of("Europe/Paris")

  "timezoneOffset should be" - {
    "-7 for PDT millis" in {
      val pdtMillis = ZonedDateTime.of(2018, 9, 10, 0, 0, 0, 0, laTz).toInstant.toEpochMilli

      dates.timezoneOffset(pdtMillis, laTz) shouldEqual -7
    }

    "-8 for PST millis" in {
      val pstMillis = ZonedDateTime.of(2017, 11, 6, 0, 0, 0, 0, laTz).toInstant.toEpochMilli

      dates.timezoneOffset(pstMillis, laTz) shouldEqual -8
    }

    "0 for GMT millis" in {
      val gmtMillis = ZonedDateTime.of(2017, 11, 6, 0, 0, 0, 0, gmtTz).toInstant.toEpochMilli

      dates.timezoneOffset(gmtMillis, gmtTz) shouldEqual 0
    }

    "10 for AEST millis" in {
      val aestMillis = ZonedDateTime.of(2018, 9, 10, 0, 0, 0, 0, sydneyTz).toInstant.toEpochMilli

      dates.timezoneOffset(aestMillis, sydneyTz) shouldEqual 10
    }

    "11 for AEDT millis" in {
      val aedtMillis = ZonedDateTime.of(2017, 10, 10, 0, 0, 0, 0, sydneyTz).toInstant.toEpochMilli

      dates.timezoneOffset(aedtMillis, sydneyTz) shouldEqual 11
    }
  }

  "timezoneOffsetBetween should be" - {
    "17 between PDT and AEST millis" in {
      val pdtMillis = ZonedDateTime.of(2018, 9, 10, 0, 0, 0, 0, laTz).toInstant.toEpochMilli

      dates.timezoneOffsetBetween(pdtMillis, laTz, sydneyTz) shouldEqual 17
    }

    "18 between PDT and AEDT millis" in {
      val pdtMillis = ZonedDateTime.of(2017, 10, 10, 0, 0, 0, 0, laTz).toInstant.toEpochMilli

      dates.timezoneOffsetBetween(pdtMillis, laTz, sydneyTz) shouldEqual 18
    }

    "19 between PST and AEDT millis" in {
      val pstMillis = ZonedDateTime.of(2017, 11, 6, 0, 0, 0, 0, laTz).toInstant.toEpochMilli

      dates.timezoneOffsetBetween(pstMillis, laTz, sydneyTz) shouldEqual 19
    }

    "-19 between AEDT and PST millis" in {
      val aedtMillis = ZonedDateTime.of(2017, 11, 6, 0, 0, 0, 0, sydneyTz).toInstant.toEpochMilli

      dates.timezoneOffsetBetween(aedtMillis, sydneyTz, laTz) shouldEqual -19
    }

    "0 between PDT and PDT" in {
      val pdtMillis = ZonedDateTime.of(2018, 9, 10, 0, 0, 0, 0, laTz).toInstant.toEpochMilli

      dates.timezoneOffsetBetween(pdtMillis, laTz, laTz) shouldEqual 0
    }

    "8 between EDT and AEST" in {
      val edtMillis = ZonedDateTime.of(2018, 9, 10, 0, 0, 0, 0, parisTz).toInstant.toEpochMilli

      dates.timezoneOffsetBetween(edtMillis, parisTz, sydneyTz) shouldEqual 8
    }

    "-8 between AEST and EDT" in {
      val aestMillis = ZonedDateTime.of(2018, 9, 10, 0, 0, 0, 0, sydneyTz).toInstant.toEpochMilli

      dates.timezoneOffsetBetween(aestMillis, sydneyTz, parisTz) shouldEqual -8
    }
  }
}
...