Я пытаюсь проанализировать строку даты / времени с SimpleDateFormat, но вывод, который я получаю, на час позже, чем ожидалось.

Код

fun formatDate(dateString: String): String {
    val locale = Locale.ENGLISH
    val time = SimpleDateFormat("EEE MMM dd HH:mm:ss ZZZZZ yyyy", locale).parse(dateString)?.time

    return SimpleDateFormat("dd/MM/yyyy HH:mm", locale).format(time)
}

Тест

@Test
fun shouldFormatDate() {
    val dateString = "Wed Mar 31 23:13:44 +0000 2010"
    val expected = "31/03/2010 23:13"

    assertThat(formatDate(dateString)).isEqualTo(expected)
}

Вывод

expected: 31/03/2010 23:13
but was : 01/04/2010 00:13

Я попытался использовать форматирование часового пояса ISO-8601 (X вместо Z), но оно тоже не сработало.

Любая помощь будет высоко ценится

-1
92AlanC 28 Мар 2020 в 20:02

2 ответа

Лучший ответ

Ваш вход определяет смещение часового пояса по Гринвичу, равное +0000 - для входа часовой пояс локали не имеет значения.

Однако в выводе используется смещение часового пояса, действующее на 2010-03-31 23:12 GMT в ENGLISH часовом поясе локали. Первого апреля 2010 года в ENGLISH локали используется летнее время, которое имеет смещение часового пояса +0100, то есть на час позже, чем время по Гринвичу.

0
Thomas Kläger 28 Мар 2020 в 17:48

Вы указываете неправильный часовой пояс в dateString, который следует ожидать, поскольку через два часа он будет отличаться в сумме на два дня (разница между 31/03 и 01/04); поэтому, чтобы ваш тест работал, вам нужно изменить часовой пояс с +0000 на +0200, как показано ниже:

@Test
fun shouldFormatDate() {
    val dateString = "Wed Mar 31 23:13:44 +0200 2010"
    val expected = "31/03/2010 23:13"

    assertThat(formatDate(dateString)).isEqualTo(expected)
}

ОБНОВЛЕНИЕ

TimeZone в переменной dateString зависит от TimeZone локальной машины, на которой вы запускаете этот тест; и именно поэтому +0100 работает с вами, но не со мной, потому что у меня установлен часовой пояс GMT + 200, и, скорее всего, вы находитесь в месте с GMT + 100 ,

Чтобы убедиться в этом, попробуйте изменить часовой пояс вашего локального компьютера на другой, отличный от вашего, и запустите тест, вы обнаружите, что он не работает.

Чтобы сделать ваш тест независимым от часового пояса вашего компьютера, вам необходимо явно установить его; например, я выберу часовой пояс «Австралия / Сидней», который GMT + 11, затем использовать TimeZone.setDefault() переопределить часовой пояс вашего компьютера.

Код

fun formatDate(dateString: String): String {
    TimeZone.setDefault(TimeZone.getTimeZone("Australia/Sydney")) // (GMT+11:00)
    val locale = Locale.ENGLISH
    val time = SimpleDateFormat("EEE MMM dd HH:mm:ss ZZZZZ yyyy", locale).parse(dateString)?.time

    return SimpleDateFormat("dd/MM/yyyy HH:mm", locale).format(time)
}

Тест

@Test
fun shouldFormatDate() {
    val dateString = "Wed Mar 31 23:13:44 +1100 2010"
    val expected = "31/03/2010 23:13"

    assertThat(formatDate(dateString)).isEqualTo(expected)
}

Также вы можете посмотреть этот

0
Zain 28 Мар 2020 в 22:28