Java 8 настройка глобальных форматтеров времени


Я хочу установить свой собственный DateTimeFormatter в качестве глобального форматера. Когда я делаю следующую строку:

ZonedDateTime.now();

Я получаю:

2016-03-30T08:58:54.180-06:00[America/Chicago]

Если я сделаю это:

ZonedDateTime.now().format(DateTimeFormatter.RFC_1123_DATE_TIME)

Я получаю:

Wed, 30 Mar 2016 9:00:06 -0600

Я хочу то, что напечатано выше, но с am/pm, поэтому я сделал свой пользовательский форматер и распечатал время так:

DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("EEE, dd MMM yyyy HH:mm:ss a Z");

ZonedDateTime.now().format(FORMATTER);

Что дало мне:

Wed, 30 Mar 2016 9:00:06 AM -0600

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

2 8

2 ответа:

Можно просто объявить константу в классе:

class UtilsOrWhatever {
  public static final DateTimeFormater RFC_1123_DATE_TIME_AM_PM = DateTimeFormatter.ofPattern("EEE, dd MMM yyyy hh:mm:ss a Z");
}

И просто используйте в своем коде:

ZonedDateTime.now().format(RFC_1123_DATE_TIME_AM_PM); //needs a static import

Альтернативно, с помощью чистой Java EE 7, Вы можете создатьгенератор DateTimeFormatter с помощью @Produces, а затем просто @Inject.

import javax.enterprise.context.ApplicationScoped;
import javax.enterprise.inject.Produces;

@ApplicationScoped
public class RfcFormatterProducer {
  @Produces
  private static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("EEE, dd MMM yyyy hh:mm:ss a Z");
}

В вашем коде:

@Inject DateTimeFormatter rfc;

Вы также можете дать ему имя, как в ссылке выше, если у вас есть несколько формататоров.

Позвольте мне сначала объяснить, почему вы получаете то, что получаете, когда не называете формат. toString вызывается на ZonedDateTime, который в свою очередь вызывает toString on на DateTime и Offset, который вызывает toString на LocalDate и LocalTime. Эти строки не используют форматеры, поэтому даже если бы вы могли указать форматер по умолчанию, он не вызывался бы при неявном преобразовании ZonedDateTime в строку.

Есть много способов сделать производство, что форматировать строку проще. Одним из способов может быть служебный класс, который вы поменяете местами во всех своих операторах журнала. Я не обязательно предлагаю следующее, Но это наиболее точно соответствует тому, что вы спрашиваете:

public class MyAwesomeUtility {
    private static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("EEE, dd MMM yyyy HH:mm:ss a Z");

    public static String getFormattedZonedDateTime() {
        return ZonedDateTime.now().format(FORMATTER);
    }
}

Следующее не является вариантом, поскольку ZonedDateTime является окончательным, как указывает @assylias. Оставим это здесь в любом случае.

Если вы действительно хотите сделать то, что вы просили в вопросе, который перезаписывает метод now, чтобы вернуть объект, который дал бы указанный формат при вызове toString вам придется сделать что-то вроде следующего (Примечание: это антипаттерн. НА САМОМ ДЕЛЕ НЕ ДЕЛАЙТЕ ЭТОГО):

public class DefaultFormattedZonedDateTime extends ZonedDateTime {
    private static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("EEE, dd MMM yyyy HH:mm:ss a Z");
    @Overwrite
    public String toString() {
        this.format(FORMATTER);
    }
}

Тогда, поскольку now on ZonedDateTime статичен и все еще возвращает ZonedDateTime, вам придется использовать AspectJ (вы не можете использовать AOP статический метод только с spring), чтобы теперь вернуть этот новый объект.