StackOverflowError с использованием нового периода joda-time (long)

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

Во-вторых, мой реальный вопрос: я делаю что-то не так или это ошибка в библиотеке joda-time?

Я пытаюсь использовать joda-time (1.6.1) для расчета, а затем форматировать продолжительность времени.

В настоящее время я использую Period, что может быть неправильным выбором. Пожалуйста, дайте мне знать, если это так. Однако, даже если это неправильный выбор, я почти уверен, что этого не должно происходить.

Я инициализирую Period, используя миллисекунды (путем умножения продолжительности в секундах на 1000). Я использую Period, поэтому я могу отформатировать его и распечатать:

long durationLong = durationSec * 1000;
Period duration = new Period(durationLong);

PeriodFormatter daysHoursMinutes = new PeriodFormatterBuilder()
    .appendHours()
    .appendSeparator(":")
    .appendMinutes()
    .appendSeparator(":")
    .appendSeconds()
    .toFormatter();

String formattedString = daysHoursMinutes.print(callDuration.normalizedStandard());

Я получаю исключение ниже и просматриваю источник, чтобы подтвердить цикл.

Caused by: java.lang.StackOverflowError
    at java.util.Hashtable.get(Hashtable.java:274)
    at java.util.Properties.getProperty(Properties.java:177)
    at java.lang.System.getProperty(System.java:440)
    at java.lang.System.getProperty(System.java:412)
    at org.joda.time.DateTimeZone.getDefault(DateTimeZone.java:132)
    at org.joda.time.DateTimeZone.forID(DateTimeZone.java:190)
    at org.joda.time.DateTimeZone.getDefault(DateTimeZone.java:132)
    at org.joda.time.DateTimeZone.forID(DateTimeZone.java:190)

...snip (all the same)...

    at org.joda.time.DateTimeZone.getDefault(DateTimeZone.java:132)
    at org.joda.time.DateTimeZone.forID(DateTimeZone.java:190)
    at org.joda.time.DateTimeZone.getDefault(DateTimeZone.java:132)
    at org.joda.time.DateTimeZone.forID(Dat

Период (длительный):

public Period(long duration) {
    super(duration, null, null);
}

супер(длинный, тип периода, хронология):

protected BasePeriod(long duration, PeriodType type, Chronology chrono) {
    super();
    type = checkPeriodType(type);
    chrono = DateTimeUtils.getChronology(chrono);
    iType = type;
    iValues = chrono.get(this, duration);
}

DateTimeUtils.getChronology (хроно):

public static final Chronology getChronology(Chronology chrono) {
    if (chrono == null) {
        return ISOChronology.getInstance();
    }
    return chrono;
}

ISOChronology.getInstance():

public static ISOChronology getInstance() {
    return getInstance(DateTimeZone.getDefault());
}

DateTimeZone.getDefault():

public static DateTimeZone getDefault() {
    DateTimeZone zone = cDefault;
    if (zone == null) {
        synchronized(DateTimeZone.class) {
            zone = cDefault;
            if (zone == null) {
                DateTimeZone temp = null;
                try {
                    try {
                        temp = forID(System.getProperty("user.timezone"));
                    } catch (RuntimeException ex) {
                        // ignored
                    }
                    if (temp == null) {
                        temp = forTimeZone(TimeZone.getDefault());
                    }
                } catch (IllegalArgumentException ex) {
                    // ignored
                }
                if (temp == null) {
                    temp = UTC;
                }
                cDefault = zone = temp;
            }
        }
    }
    return zone;
}

forID(String) вызывает getDefault(), который создает цикл:

 public static DateTimeZone forID(String id) {
    if (id == null) {
        return getDefault();
    }
    if (id.equals("UTC")) {
        return DateTimeZone.UTC;
    }
    DateTimeZone zone = cProvider.getZone(id);
    if (zone != null) {
        return zone;
    }
    if (id.startsWith("+") || id.startsWith("-")) {
        int offset = parseOffset(id);
        if (offset == 0L) {
            return DateTimeZone.UTC;
        } else {
            id = printOffset(offset);
            return fixedOffsetZone(id, offset);
        }
    }
    throw new IllegalArgumentException("The datetime zone id is not recognised: " + id);
}

person cofiem    schedule 11.09.2010    source источник


Ответы (2)


Поскольку циклическая часть есть только в коде joda, я бы сказал, что это ошибка.


Исправлено в trunk и будет доступен в версии 2.0.


Ресурсы:

person Colin Hebert    schedule 11.09.2010
comment
Дал вам ответ на ссылку на ствол и отчет об ошибке - я тоже не нашел! - person cofiem; 11.09.2010

Похоже, это ошибка, поскольку предполагается, что свойство user.timezone будет установлено.

Это способ обойти это в этом случае - просто убедитесь, что user.timezone установлен правильно. Хотя жалко, что приходится.

Joda Time во многих местах использует «null означает значение по умолчанию» - к сожалению, на мой взгляд. Обычно я предпочитаю, чтобы "null недействителен". В Noda Time (перенос Joda Time на .NET) мы пытаемся избавиться от много такого рода вещей, а также предотвращение того, чтобы часовой пояс по умолчанию был настолько распространенным в первую очередь.

person Jon Skeet    schedule 11.09.2010