[Java] Почему вычитание этих двух раз (в 1927 году) дает странный результат?



Answers

Вы столкнулись с локальным временным разрывом :

Когда местное стандартное время доходило до воскресенья, 1. января 1928 года, 00:00:00 часы были повернуты назад 0:05:52 часов до субботы, 31 декабря 1927 года, 23:54:08 вместо обычного местного времени

Это не особенно странно и случалось почти повсеместно в тот или иной момент, поскольку временные интервалы были изменены или изменены из-за политических или административных действий.

Question

Если я запустил следующую программу, которая анализирует две строки даты, ссылаясь на раз в 1 секунду и сравнивает их:

public static void main(String[] args) throws ParseException {
    SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");  
    String str3 = "1927-12-31 23:54:07";  
    String str4 = "1927-12-31 23:54:08";  
    Date sDt3 = sf.parse(str3);  
    Date sDt4 = sf.parse(str4);  
    long ld3 = sDt3.getTime() /1000;  
    long ld4 = sDt4.getTime() /1000;
    System.out.println(ld4-ld3);
}

Выход:

353

Почему ld4-ld3 не 1 (как я ожидал бы от разницы в одну секунду во времени), но 353 ?

Если я изменю даты на несколько секунд позже:

String str3 = "1927-12-31 23:54:08";  
String str4 = "1927-12-31 23:54:09";  

Тогда ld4-ld3 будет 1 .

Версия Java:

java version "1.6.0_22"
Java(TM) SE Runtime Environment (build 1.6.0_22-b04)
Dynamic Code Evolution Client VM (build 0.2-b02-internal, 19.0-b04-internal, mixed mode)

Timezone(`TimeZone.getDefault()`):

sun.util.calendar.ZoneInfo[id="Asia/Shanghai",
offset=28800000,dstSavings=0,
useDaylight=false,
transitions=19,
lastRule=null]

Locale(Locale.getDefault()): zh_CN



Мне жаль это говорить, но разрыв времени немного изменился

JDK 6 два года назад, а в JDK 7 совсем недавно в обновлении 25 .

Урок для изучения: избегайте времени, не связанного с UTC, любой ценой, за исключением, может быть, для отображения.




При увеличении времени вы должны вернуться в UTC, а затем добавить или вычесть. Используйте локальное время только для отображения.

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

Если вы конвертировали в UTC, добавьте каждую секунду и конвертируйте в локальное время для отображения. Вы бы прошли через 11:54:08 вечера LMT - 11:59:59 вечера LMT, а затем 11:54:08 вечера CST - 11:59:59 вечера КНТ.




ИМХО распространенная, неявная локализация в Java - это один из самых больших недостатков дизайна. Он может быть предназначен для пользовательских интерфейсов, но, честно говоря, кто действительно использует Java для пользовательских интерфейсов сегодня, за исключением некоторых IDE, где вы можете в основном игнорировать локализацию, потому что программисты не являются целевой аудиторией. Вы можете исправить это (особенно на серверах Linux):

  • экспорт LC_ALL = C TZ = UTC
  • установите системные часы на UTC
  • никогда не используйте локализованные реализации, если это абсолютно необходимо (т.е. только для отображения)

Являясь членами сообщества Java, я рекомендую:

  • сделать локализованные методы не стандартными, но требуют, чтобы пользователь явно запрашивал локализацию.
  • используйте UTF-8 / UTC как значение FIXED по умолчанию, потому что сегодня это просто по умолчанию. Нет причин делать что-то еще, за исключением случаев, когда вы хотите создавать такие потоки.

Я имею в виду, давайте, не являются глобальными статическими переменными анти-OO-образцом? Ничто другое не является распространенным дефолтом, данным некоторыми элементарными переменными среды .......




Links