Gunnar Bittersmann: Regular Expression für ein Datum

Beitrag lesen

Hello out there!

Aber wenn du Zeit und Muße hast, kannst du ja mal so eine schaltjahrberücksichtigende Datums-RegExp erstellen. Die Kalenderkorrekturen längst vergangener Jahrhunderte kannst du ja für den Anfang erst einmal unberücksichtigt lassen. :-)

-?\d*(?:(?:(?:(?:[02468][048]|[13579][26])(?:[02468][048]|[13579][26])|(?:[02468][^048]|[13579][^26])(?:0[48]|[2468][048]|[13579][26]))[-./]?02[-./]?(?:0[1-9]|[12]\d)|(?:(?:[02468][^048]|[13579][^26])00|\d\d(?:[02468][^048]|[13579][^26]))[-./]?02[-./]?(?:0[1-9]|12\d|2[0-8]))|\d{4}[-./]?(?:(?:0[13578]|1[02])[-./]?(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)[-./]?(?:0[1-9]|[12]\d|30)))

Na, so schwer war’s doch gar nicht. ;-)

Der Ausdruck passt auf gültige Daten im Format ISO 8601 (heutige Schaltjahrregel auf gesamten Bereich angewandt). Der Audruck lässt '-', '.' oder '/' als Trennzeichen zu oder auch kein Trennzeichen. Da haben wir ein Manko: Der Ausdruck erkennt nicht, ob zwischen Jahr und Monat sowie zwischen Monat und Tag dasselbe Trennzeichen steht (2006.03/25 würde auch matchen). Ließe sich mit einigem Aufwand beheben (statt foo[-./]?bar[-./]?baz dann foo-bar-baz|foo\.bar\.baz|foo/bar/baz|foobarbaz).

Zur Erklärung:

-?\d*                                        # für die Ewigkeit
(?:
  (?:
    (?:
      (?:[02468][048] | [13579][26])         # Jahrhundert durch 4 teilbar
      (?:[02468][048] | [13579][26])         # Jahr duch 4 teilbar
      |
      (?:[02468][^048] | [13579][^26])       # Jahrhundert nicht durch 4 teilbar
      (?:0[48] | [2468][048] | [13579][26])  # Jahr duch 4 teilbar außer volle Jahrhunderte
    )
    [-./]?                                   # Trennzeichen
    02                                       # Februar im Schaltjahr
    [-./]?                                   # Trennzeichen
    (?:0[1-9] | [12]\d)                      # 01 bis 29
    |
    (?:
      (?:[02468][^048] | [13579][^26])       # Jahrhundert nicht durch 4 teilbar
      00                                     # selbsterklärend
      |
      \d\d                                   # beliebiges Jahrhundert
      (?:[02468][^048] | [13579][^26])       # Jahr nicht durch 4 teilbar
    )
    [-./]?                                   # Trennzeichen
    02                                       # Februar im Nicht-Schaltjahr
    [-./]?                                   # Trennzeichen
    (?:0[1-9] | 12\d | 2[0-8])               # 01 bis 28
  )
  |
  \d{4}                                      # beliebiges Jahr
  [-./]?                                     # Trennzeichen
  (?:
    (?:0[13578] | 1[02])                     # langer Monat
    [-./]?                                   # Trennzeichen
    (?:0[1-9] | [12]\d | 3[01])              # 01 bis 31
    |
    (?:0[469] | 11)                          # kurzer Monat
    [-./]?                                   # Trennzeichen
    (?:0[1-9] | [12]\d | 30)                 # 01 bis 30
  )
)

See ya up the road, Gunnar

--
“Remember, in the end, nobody wins unless everybody wins.” (Bruce Springsteen)