Почему новый объект SimpleDateFormat содержит календарь с неправильным годом?

Команда Python очень упорно работала для создания отсутствия обратной совместимости максимально безболезненным к точке, где 2,6 релиза Python были созданы с умом к безболезненному процессу обновления. Как только Вы обновили до 2,6 существуют сценарии, которые можно выполнить, который переместит Вас в 3,0 без проблемы.

8
задан Community 23 May 2017 в 12:19
поделиться

5 ответов

I'm not sure why Tom says "it's something to do with serialization", but he has the right line:

private void initializeDefaultCentury() {
    calendar.setTime( new Date() );
    calendar.add( Calendar.YEAR, -80 );
    parseAmbiguousDatesAsAfter(calendar.getTime());
}

It's line 813 in SimpleDateFormat.java, which is very late in the process. Up to that point, the year is correct (as is the rest of the date part), then it's decremented by 80.

Aha!

The call to parseAmbiguousDatesAsAfter() is the same private function that set2DigitYearStart() calls:

/* Define one-century window into which to disambiguate dates using
 * two-digit years.
 */
private void parseAmbiguousDatesAsAfter(Date startDate) {
    defaultCenturyStart = startDate;
    calendar.setTime(startDate);
    defaultCenturyStartYear = calendar.get(Calendar.YEAR);
}

/**
 * Sets the 100-year period 2-digit years will be interpreted as being in
 * to begin on the date the user specifies.
 *
 * @param startDate During parsing, two digit years will be placed in the range
 * <code>startDate</code> to <code>startDate + 100 years</code>.
 * @see #get2DigitYearStart
 * @since 1.2
 */
public void set2DigitYearStart(Date startDate) {
    parseAmbiguousDatesAsAfter(startDate);
}

Now I see what's going on. Peter, in his comment about "apples and oranges", was right! The year in SimpleDateFormat is the first year of the "default century", the range into which a two-digit year string (e.g, "1/12/14") is interpreted to be. See http://java.sun.com/j2se/1.4.2/docs/api/java/text/SimpleDateFormat.html#get2DigitYearStart%28%29 :

So in a triumph of "efficiency" over clarity, the year in the SimpleDateFormat is used to store "the start of the 100-year period into which two digit years are parsed", not the current year!

Thanks, this was fun -- and finally got me to install the jdk source (I only have 4GB total space on my / partition.)

5
ответ дан 5 December 2019 в 17:39
поделиться

Вы исследуете внутреннее поведение. Если это выходит за рамки опубликованного API, то вы видите неопределенный материал, и вам не следует об этом заботиться.

Помимо этого, я полагаю, что 1929 год используется для рассмотрения того, когда интерпретировать двузначный год как находящийся в 19xx вместо 20xx.

2
ответ дан 5 December 2019 в 17:39
поделиться

SimpleDateFormat имеет изменяемое внутреннее состояние. Вот почему я избегаю этого как чумы (я рекомендую Joda Time ). Этот внутренний календарь, вероятно, используется в процессе синтаксического анализа даты, но нет причин, по которым он будет инициализирован каким-либо конкретным образом до того, как он проанализирует дату.

Вот пример кода для иллюстрации:

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.GregorianCalendar;

public class DateTest {
    public static void main(String[] args) {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat();
        System.out.println("sdf cal: " + simpleDateFormat.getCalendar());
        System.out.println("new cal: " + new GregorianCalendar());
        System.out.println("new date: " + simpleDateFormat.format(new Date()));
        System.out.println("sdf cal: " + simpleDateFormat.getCalendar());
    }
}
2
ответ дан 5 December 2019 в 17:39
поделиться

Просматривая SimpleDateFormat, кажется, что это как-то связано с сериализацией:

/* Initialize the fields we use to disambiguate ambiguous years. Separate
 * so we can call it from readObject().
 */
private void initializeDefaultCentury() {
    calendar.setTime( new Date() );
    calendar.add( Calendar.YEAR, -80 );
    parseAmbiguousDatesAsAfter(calendar.getTime());
}
1
ответ дан 5 December 2019 в 17:39
поделиться
System.out.println(new SimpleDateFormat().getCalendar());
System.out.println(new GregorianCalendar());

сравнение кода выше - это сравнение яблок и груш

Первый предоставляет вам инструмент для синтаксического анализа строки на даты и наоборот Вторая - DateUtility, которая позволяет вам манипулировать датами.

На самом деле нет причин, по которым они должны выдавать аналогичный вывод.

Сравните это со следующим

System.out.println(new String() );
System.out.println(new Date().toString() );

, обе строки будут выводить String, но логически вы не ожидаете, что тот же результат

0
ответ дан 5 December 2019 в 17:39
поделиться
Другие вопросы по тегам:

Похожие вопросы: