30.Februar 2015

Wer glaubt, das der Februar maximal 29 Tage haben kann, soll sich mal in JavaScript und HTML Tiefen stürzen. Datum und Uhrzeit ist in der IT Welt schon immer keine leichte Aufgaben gewesen. Wer lange genug dabei ist, wird sich noch den den Millenium Bug erinnern. Aber auch heute ist es nicht trivial mit Zeitzonen und Daylight Saving Time zu operieren. Am Ende dieses Artikels wird der  Leser den Glauben an die Programmierwelt verloren haben.

In HTML5 werden Input Elemente mit neuen Typ Attributen versehen. Auf den ersten Blick würde man meinen, das damit formatierte Datumseingabe möglich ist. Mitnichten, nicht nur der Internet Explorer 11, sondern auch nahezu die restliche Browserwelt unterstützt zwar das Attribut, beachtet es aber weiter nicht. Der Benutzer kann also in folgendes HTML Schnippsel auch Text eingeben,

   1:   <input type="date" id="d1" /> 
   2:   <a onclick="alert(document.getElementById('d1').value);">wert</a>

Ein richtiger Datumstyp muss auch die Lokalisierungsdaten beinhalten. Die ISO-8601 definiert das Format bis hin zur Zeitzone. AngularJS setzt auf das HTML5 und damit auf das Eingabeformat- total Benutzerfreundlich.

image

Der Screenshot stammt aus folgendem AngularJS Beispiel

   1:  <input ng-init ="dat='2015-02-14T11:24:05.0Z'" ng-model="dat"/><br />
   2:  {{dat | date: "dd.MM.yyyy"}}<br />

Die Anzeige wird mit dem Angular Date Filter formatiert, so das sie dem typische deutschen Datumsformat entspricht.

Die Bindung eines Date INPUT ist auf der Angular Website samt live Beispiel beschrieben. Wenn sich ein Benutzer an das ISO Format Jahr-Monat-Tag hält, dann kann er Problemlos den 30.Februar als gültiges Datum eingeben.

image

Weder das eine noch das andere ist in unserem Kulturkreis geläufig. Die Anzeige lässt sich passend formatieren. Die Eingabe leider nicht.

AngularJS typisch wird für Manipulation eines HTML DOM Elements eine Direktive erzeugt. Wer mit Silverlight oder WPF gearbeitet hat, kennt die Value Converter Klassen, die man zwischen bindendes UI Element und der Viewmodel Eigenschaft hängt. Quasi das selbe lässt sich mit einer Angular Direktive erreichen.

Die Methoden $parsers und $formatters entsprechen den Convert und ConvertBack Methoden.

   1:  .directive('deutschesDatum', function ($filter) {
   2:      return {
   3:       require: 'ngModel',
   4:       link: function (scope, element, attrs, ctrl) {
   5:           ctrl.$parsers.push(function (data) {
   6:                       //View -> Model
   7:                var d = data.split(".");
   8:                var parsedDate = new Date(d[2], d[1] - 1, d[0]);
   9:                return parsedDate;
  10:                });
  11:          ctrl.$formatters.push(function (data) {
  12:                      //Model -> View
  13:               return $filter('date')(data, "dd.MM.yyyy");
  14:           });
  15:       }
  16:  };

 

Obiger JavaScript Code löst aber noch nicht das Problem des 30.Februars. Man müsste mehr Code in den Teil ab Zeile 5 schreiben. Es reicht das Konzept.

In der HTML5 Deklaration wird nun die Direktive als Attribut eingefügt.

   1:   <input id="datum1" type="text" ng-model="datum" deutsches-datum /><br />

 

image

Üblicherweise werden für Datumseingabe fertige Kalender Popup verwendet.

Kommentare sind geschlossen