SimpleDateFormat YYYY против yyyy
Привет всем!
Это мой первый пост на Хабре и он связан с форматом года в SimpleDateFormat в мире Android.
Предыстория
При разработки очередной фичи я написал экстеншен функцию расширяющую возможности класса Date.
@Throws(IllegalArgumentException::class)
fun Date.toString(pattern: String): String {
val simpleDateFormat = SimpleDateFormat(pattern, Locale.getDefault())
return simpleDateFormat.format(this)
}
По "счастливой" случайности, при использовании данного экстеншена, я написал формат года капсом.
textOperationDateTime.text = date.toString(pattern = "dd MMMM YYYY, HH:mm")
При тестировании никаких проблем обнаружено не было и данный код пошел в продакшн.
Проблема
В один прекрасный день на мою почту приходит письмо из Firebase c сообщением о массовых сбоях в приложении, а сбои связаны как раз с моим экстеншеном Date.toString.
Ошибка гласит, что используется неизвестный символ в паттерне.
java.lang.IllegalArgumentException: Unknown pattern character 'Y'
В чем же проблема и почему при тестировании не было этих сбоев?
А проблема в том, что существует разница между YYYY и yyyy:
1. Оба они представляют год, но yyyy представляет календарный год, а YYYY представляет год недели.
var date = SimpleDateFormat("yyyy-MM-dd").parse("2018-12-01")
date.toString("YYYY") //результат: 2018
date.toString("yyyy") //результат: 2018
date = SimpleDateFormat("yyyy-MM-dd").parse("2018-12-31")
date.toString("YYYY") //результат: 2019
date.toString("yyyy") //результат: 2018
2. YYYY появился в java 8 и поддерживается только в Android >= api 24
Запускаем на Android 7 или выше
var date = SimpleDateFormat("yyyy-MM-dd").parse("2018-12-01")
date.toString("YYYY") //результат: 2018
date.toString("yyyy") //результат: 2018
date = SimpleDateFormat("yyyy-MM-dd").parse("2018-12-31")
date.toString("YYYY") //результат: 2019
date.toString("yyyy") //результат: 2018
обратите внимание на 6-ую строчку кода.
Запускаем на Android 6 или ниже
var date = SimpleDateFormat("yyyy-MM-dd").parse("2018-12-31")
date.toString("YYYY") //результат: java.lang.IllegalArgumentException: Unknown pattern character 'Y'
date.toString("yyyy") //результат: 2018
обратите внимание на 2-ую строчку кода.
А сбоев при тестировании не было из-за того, что данный блок не тестировался на устройствах с Android ниже 7 версии.
Итог
И в итоге мы должны помнить, что почти всегда нужно использовать формат года yyyy, а про YYYY нужно знать и при специфичных требованиях логики отображения года использовать этот формат.
Будьте внимательны и не совершайте мою ошибку!