2016-03-30 6 views
8

Ich möchte meinen eigenen DateTimeFormatter als globalen Formatierer setzen. Wenn ich die folgende Zeile zu tun:Java 8 Einstellung globaler Zeitformatierer

ZonedDateTime.now(); 

ich:

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

Wenn ich dies tun:

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

ich:

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

Ich will, was gedruckt ist oben, aber mit am/pm, also habe ich meinen eigenen Formatierer gemacht und ausgedruckt die Zeit, in etwa so:

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

ZonedDateTime.now().format(FORMATTER); 

Was mir gab:

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

Aber ich benutze diese Methode .now() überall zur Protokollierung und ich möchte nicht die Formatierungs überall im Code definieren. Gibt es eine Möglichkeit, den Formatierer als Standardformat für den Aufruf der Methode .now() zu konfigurieren? Ich denke, wie der Frühling Bohne Konfigurationsmethode oder etwas .....

+2

Warum FORMATTER nicht statisch Singleton machen und überall darauf zugreifen? – Loc

+0

Ich bin mir nicht sicher, ob ich das verstehe. 'ZonedDateTime.now()' hängt nicht von einem Formatierungsprogramm ab. Und wenn Sie nach dem Aufruf von 'format' einen einzelnen formatieren wollen, warum sollte er nicht irgendwo eine Konstante haben? – Tunaki

+0

Was Sie bekommen, ist das toString-Ergebnis: Verwenden Sie println? Logger? ein Serializer? Wenn Sie sich im toString-Fall befinden, gibt es nicht viel zu tun. – pdem

Antwort

5

Sie einfach eine Konstante in einer Klasse erklären könnte:

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

und verwenden Sie einfach in Ihrem Code:

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

Alternativ, mit reinem Java EE 7, könnten Sie a DateTimeFormatter Producer mit @Produces erstellen und dann einfach @Inject es.

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"); 
} 

In Ihrem Code:

@Inject DateTimeFormatter rfc; 

Man könnte es auch einen Namen geben wie in den obigen Link, wenn Sie mehrere Formatter haben.

+0

aber ich müsste in alle Klassen spritzen wo ich das Datetime ausdrucken möchte oder? Oder Nein? – Richard

+1

Ja, Sie würden - es gibt keine Möglichkeit, das Verhalten der "Format" -Methode zu "überschreiben". Definieren Sie eine Konstante irgendwo 'public static final DateTimeFormater RFC_1123_DATE_TIME_AM_PM = ...' ist auch eine Option. – assylias

+0

Irgendwo zu definieren und es statisch zu machen, ist eine großartige Idee. Das hält den Code etwas sauber. Es ist nicht die ideale Lösung, aber die ideale Lösung ist buchstäblich unmöglich, also ist dies die nächstbeste Sache. Danke! – Richard

0

Lassen Sie mich zuerst erklären, warum Sie bekommen, was Sie bekommen, wenn Sie nicht das Format aufrufen. Die toString wird auf der ZonedDateTime aufgerufen, die wiederum die ToString bei DateTime und Offset, die ToString auf LocalDate und LocalTime aufrufen. Diese toStrings verwenden KEINE Formatter. Selbst wenn Sie einen "Standard" -Formatierer angeben könnten, würde er nicht aufgerufen werden, wenn Sie eine ZonedDateTime implizit in eine Zeichenkette konvertieren.

Es gibt viele Möglichkeiten, diese formatierte Zeichenfolge einfacher zu erstellen. Eine Möglichkeit wäre eine Dienstprogrammklasse, die Sie in allen Ihren Protokollanweisungen austauschen würden. Ich schlage vor, nicht unbedingt die folgenden, aber es am ehesten passt, was Sie fordern:

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); 
    } 
} 

Das folgende ist keine Option, da ZonedDateTime endgültig ist, wie durch @assylias hingewiesen. Das hier auf jeden Fall lassen.

Wenn Sie wirklich tun wollte, was man in der Frage gestellt, welche die now Methode überschreiben ein Objekt zurück, das eine das angegebene Format geben würde, wenn toString aufgerufen wurde Sie so etwas wie die folgenden (HINWEIS tun würde : Dies ist eine Antipattern tun es nicht TATSÄCHLICH.):

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); 
    } 
} 

Dann seit now auf ZonedDateTime statisch ist und nach wie vor gibt ZonedDateTime Sie würden AspectJ verwenden müssen (man kann eine statische Methode mit Feder nicht um AOP alleine), um das neue Objekt stattdessen zurückgeben zu lassen.

+5

ZonedDateTime ist endgültig ... – assylias

+0

Guter Fang. Das habe ich nicht einmal bemerkt. Ich habe die Antwort aktualisiert, um zu erklären, dass es keine Option ist. –