Kann man Daten / Uhrzeiten lokalisiert formatieren und parsen ohne die globale "locale"-Einstellung zu verändern?

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
AFoeee
User
Beiträge: 11
Registriert: Montag 22. Januar 2018, 07:00

Hallo,
ich versuche eine Möglichkeit zu finden Daten bzw. Uhrzeiten lokalisiert zu formatieren und zu parsen.
Dabei ist die eigentliche Problematik, dass die "default locale"-Einstellung des Systems ("de_DE") von der Lokalisierung des Input / Output abweicht ("en_US").

Ich möchte also folgendes erzielen:
  • einen lokalisierten String zu einem "datetime"-Objekt parsen,
  • mittels eines "datetime"-Objekts einen formatierten String erzeugen (selbes "locale" und Muster wie Input).

Bild



Während meiner Recherche bin ich auf folgende zwei Möglichkeiten gestoßen:
  1. Verändern der globalen "locale"-Einstellung.

    Dieser Ansatz ist meiner Meinung nach etwas problematisch, da er einen globalen Wert manipuliert und daraus ggf. unerwünschte Nebeneffekte entstehen können.

    Code: Alles auswählen

    import datetime
    import locale
    
    locale.setlocale(locale.LC_TIME, "en_US.UTF-8")
    
    dt = datetime.datetime.strptime("Thu 3 Apr 2014 13:19:52",
                                    "%a %d %b %Y %H:%M:%S")
    # datetime.datetime(2014, 4, 3, 13, 19, 52)
    
    dtr_str = dt.strftime("%a %-d %b %Y %H:%M:%S")
    # 'Thu 3 Apr 2014 13:19:52'
  2. Verwenden der Python Bibliothek babel.

    Der Vorteil hieran ist, dass das gewünschte "locale" der Methode zum Formatieren einfach übergeben werden kann.
    Leider scheint babel nicht das Parsen beliebiger Muster zu unterstützen. (Offenbar funktioniert nur das Format "short" wirklich zuverlässig, welches mein Input allerdings nicht hat.)

    Code: Alles auswählen

    import babel.dates    # installed via pip
    import datetime
    
    dt = datetime.datetime(2014, 4, 3, 13, 19, 52)
    
    dt_str = babel.dates.format_datetime(dt,
                                         "EEE d MMM yyyy H:mm:ss", 
                                         locale="en_US")
    # 'Thu 3 Apr 2014 13:19:52'

Gibt es eine Möglichkeit die beschriebenen Konvertierungen durchzuführen ohne die globale "locale"-Einstellung zu verändern?

Diese Frage wurde in englischer Sprache auch auf stackoverflow gepostet.

Mit freundlichen Grüßen
AFoeee
Benutzeravatar
__blackjack__
User
Beiträge: 13004
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@AFoeee: Im zweiten von Dir verlinkten Issue verweist jemand auf das `dateparser`-Modul. Dann gäbe es noch `maya` von Kenneth Reitz, der in der Dokumentation als Konkurrentz bzw. Grundlage die Packages Arrow, Delorean, und Pendulum erwähnt. Also ist gibt da durchaus noch andere Bibliotheken.
“Most people find the concept of programming obvious, but the doing impossible.” — Alan J. Perlis
AFoeee
User
Beiträge: 11
Registriert: Montag 22. Januar 2018, 07:00

__blackjack__ hat geschrieben: Dienstag 18. September 2018, 22:32 Dann gäbe es noch `maya` von Kenneth Reitz, der in der Dokumentation als Konkurrentz bzw. Grundlage die Packages Arrow, Delorean, und Pendulum erwähnt. Also ist gibt da durchaus noch andere Bibliotheken.
Hallo __blackjack__,

die Bibliothek arrow scheint genau das zu sein, wonach ich gesucht habe. Vielen Dank!

Code: Alles auswählen

import arrow        # installiert mittels pip

dt_str = "Thu 3 Apr 2014 13:19:52"              # en_US

a_dt = arrow.get(dt_str,
                 "ddd D MMM YYYY H:mm:ss",
                 locale="en_US")                # "en_US" ist ebenfalls der default-Wert

dt = a_dt.datetime
# datetime.datetime(2014, 4, 3, 13, 19, 52, tzinfo=tzutc())

s = a_dt.format("ddd D MMM YYYY H:mm:ss",
                locale="en_US")                 # "en_US" ist ebenfalls der default-Wert
# 'Thu 3 Apr 2014 13:19:52'
Ich habe zusätzlich den Eintrag auf stackoverflow aktualisiert.

Mit freundlichen Grüßen
AFoeee
Benutzeravatar
DeaD_EyE
User
Beiträge: 1012
Registriert: Sonntag 19. September 2010, 13:45
Wohnort: Hagen
Kontaktdaten:

Ich nutze pytz für Zeitzonen.

Könnte so aussehen:

Code: Alles auswählen

import datetime
import pytz


berlin = pytz.timezone('Europe/Berlin')
london = pytz.timezone('Europe/London')
utc_now = datetime.datetime.now(tz=pytz.UTC)

print(berlin.normalize(utc_now))
print(london.normalize(utc_now))
Was dort fehlt, ist die Lokalisierung des Strings.
DateTime nutze ich grundsätzlich mit UTC0 und erst, wenn es zur Anzeige kommt, normalisiere ich.
Falls die Ausgabe in einer Datenbank gespeichert werden soll und die Datenbank Informationen über die Zeitzone nicht speichert, sollte man ISO8601 verwenden.
Das datetime-Modul kann seit 3.7 auch ISO8601 strings parsen. Die Ausgabe als ISO8601 string wird schon etwas länger unterstützt.
sourceserver.info - sourceserver.info/wiki/ - ausgestorbener Support für HL2-Server
Antworten