Преобразование UT C в EST не работает при экономии дневного света на Android - PullRequest
0 голосов
/ 10 марта 2020

Я пытался преобразовать местное время (EST) в UT C и наоборот. Итак, я представляю выбор времени, пользователь выбирает время, я конвертирую его в UT C и отправляю на сервер. Вот код:

        val cal = Calendar.getInstance()
        cal.set(Calendar.HOUR_OF_DAY, mHour) //mHour = 15
        cal.set(Calendar.MINUTE, mMinute)    //mMinute = 00
        cal.set(Calendar.SECOND, 0)
        val formatter = SimpleDateFormat("HH:mm:ss")
        formatter.timeZone = TimeZone.getTimeZone("UTC")
        val cutOffTime = formatter.format(cal.time)  //this gives 19:00:00 which is correct

Приведенный выше вывод для cutOffTime правильный, так как 15:00 EST - 19:00 UT C после учета экономии дневного света.

Теперь я получаю это же CutOffTime с сервера, преобразовать его в локальный (EST) и отобразить. Вот код:

        val cutOffTime = jsonObject.get("cutOffTime").getAsString())  //value is 19:00:00
        var cutoffTime: Time? = null
        val format = SimpleDateFormat("hh:mm:ss")
        format.timeZone = TimeZone.getTimeZone("UTC")
        cutoffTime = Time(format.parse(cutOffTime).time)

        //cutoffTime has value 14:00 which is strange, it should be 15:00

Итак, cutoffTime в приведенном выше коде имеет значение 14:00, что странно, оно должно быть 15:00. Обратите внимание, что этот код работал до перехода на летнее время 8 марта 2020 года. Есть идеи, что я делаю не так?

Ответы [ 2 ]

1 голос
/ 10 марта 2020

Пожалуйста, не используйте старые и плохо разработанные java API для даты и времени. Используйте новый java .time API. Это гораздо надежнее и удобнее в использовании.

Вот пример того, как сделать ваш код с java .time :

int mHour = 15;
int mMinute = 0;
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("HH:mm:ss");

ZonedDateTime toFormat = LocalDateTime
    .now() // Current date and time.
    .withHour(mHour).withMinute(mMinute).withSecond(0) // Change hour, minute and second like in your example.
    .truncatedTo(ChronoUnit.SECONDS) // Throw away milliseconds and nanoseconds.
    .atZone(ZoneOffset.UTC); // Say that the time is located at UTC+0.

String formatted = formatter
    .withZone(ZoneId.of("America/New_York")) // Create a new formatter that formats toFormat to the local time America/New_York.
    .format(toFormat);

System.out.println(formatted); // Gives 11:00:00 on my machine now. America/New_York is either UTC-5 or UTC-4.

ZonedDateTime parsed = LocalTime
    .parse(formatted, formatter) // Parse the String. The result is an instance of LocalTime.
    .atDate(LocalDate.now(ZoneId.of("America/New_York"))) // Add the date values which are those of the current local date at America/New_York.
    .atZone(ZoneId.of("America/New_York")); // Create a ZonedDateTime of the LocalDateTime to explicitly define the zone.

Instant pointInTimeA = parsed.toInstant();
Instant pointInTimeB = toFormat.toInstant();

System.out.println(pointInTimeA.equals(pointInTimeB)); // Gives true because both describe the same point in time as they should.

Великий Преимущество в том, что API будет обрабатывать все, что касается летнего и зимнего времени для вас. Прочитайте здесь для получения информации о EST и почему вы не должны его использовать.

Проблема, с которой вы столкнулись, вероятно, связана с тем, что вы использовали HH в одном форматере но hh в другой. Это не то же самое. Прочитайте здесь о Шаблоны для форматирования и разбора .

0 голосов
/ 11 марта 2020

Я закончил с приведенным ниже решением. Я знал формат строки с сервера, поэтому я разделил ее. Я не хотел использовать новый API времени, поскольку он доступен начиная с уровня API 26 и выше.

                val cutOffString = jsonObject.get("cutOffTime").getAsString() //UTC date 19:00:00 from server

                val cal = Calendar.getInstance()
                cal.set(Calendar.HOUR_OF_DAY, cutOffString.split(":")[0].toInt())
                cal.set(Calendar.MINUTE, cutOffString.split(":")[1].toInt())
                cal.set(Calendar.SECOND, 0)
                cal.timeZone = TimeZone.getTimeZone("UTC")

                val cutoffTime: Time = Time(cal.time.time) //15:00:00

...