2013-01-26

Zeitzonen

…hallo, noch jemand da…?

Smiley

Nach einer etwas längeren schöpferischen Pause habe ich ein hoffentlich spannendes Thema für Sie. Mobile Geräte werden weltweit genutzt. Und damit auch deren Apps. Bei der Programmierung ist deshalb darauf zu achten, dass Kalender, Termine oder Erinnerungen überall funktionieren. Das hört sich allerdings einfacher an, als es ist. Nehmen Sie als Beispiel den Geschäftsreisenden, der in München wohnt und zu einem Kunden nach New York muss. Wenn die beiden einen Termin vereinbaren, wählen sie normalerweise eine Zeit bezogen auf den Ort des Treffens, also New York. Tippt der Münchner unbesonnen einfach die beschlossene Uhrzeit in sein teures Smartphone, finden die beiden nicht zueinander. Warum? Unterschiedliche Zeitzonen. Ist es in Deutschland 19:20, zeigt die Uhr an der amerikanischen Ostküste 13:20 (Spezialitäten wie Sommerzeit einmal außen vor gelassen).

Die App zur Erfassung von Terminen wird dem Anwender also die Möglichkeit geben, eine Zeitzone auszuwählen. Gleiches gilt natürlich für klassische Desktop- und Webanwendungen. Der folgende Google Kalender-Screenshot zeigt, wie so etwas aussehen kann.

Anlegen eines Termins mit Zeitzone in Google Kalender

Wie aber kommt man an solche Zeitzonen-Informationen? Tatsächlich kennt Java schon seit Version 1.1 die Klasse java.util.TimeZone. Diese speichert die Abweichung von einer Standardzeit sowie die Information, ob bzw. wann in der Zeitzone die Sommerzeit gilt. Die Standardzeit wird in der Java-Dokumentation als Greenwich Mean Time (GMT) bezeichnet. Allerdings wurde GMT (schon vor geraumer Zeit) durch die Coordinated Universal Time (Achtung, deren Abkürzung lautet UTC!) abgelöst. Bis auf subtile Unterschiede sind GMT und UTC aber synonym. Details hierzu enthält der korrespondierende englischsprachige Wikipedia-Artikel. Fassen wir zusammen: Es gibt also eine weltweit eindeutige Standardzeit (UTC/GMT). Alle Regionen der Erde werden in bestimmte Zeitzonen unterteilt. Lokale Uhrzeiten ergeben sich aus festgelegten Differenzen zu der Standardzeit

Das folgende Quelltextfragment ermittelt alle Zeitzonen, die der Java Runtime bekannt sind bzw. hinterlegt wurden.

    String[] ids = TimeZone.getAvailableIDs();
    System.out.println("Anzahl: " + ids.length);
    for (String id : ids) {
      TimeZone tz = TimeZone.getTimeZone(id);
      System.out.println("Name: " + tz.getDisplayName());
    }

Wenn Sie den Codeschnipsel in eine main-Methode packen und ausführen, sind Sie vielleicht verwundert. Unter Java 7 wandern mehr als 600 Zeilen über den Schirm, von denen viele gleich sind. Dubletten? Fügen Sie der for-Schleife eine Zeile hinzu, die die Variable id ausgibt.

      System.out.println("id: " + id);

Ausgabe von Zeitzonen

Auf den ersten Blick ist es sicher ungewöhnlich, dass eine Id Städtenamen (Honolulu, Johnston) enthält sowie eine hierarchische Struktur (der Slash trennt sehr oft zwei Elemente) aufweist. Würde man diese Informationen nicht eher in der Klasse TimeZone selbst erwarten? Ein Blick in die Dokumentation ernüchtert. Es gibt keine Methoden, die die Gruppierung oder Strukturierung der vielen Daten erleichtern. Das Parsen und Anzeigen der Id würde ich mir wahrscheinlich sehr genau überlegen.

Das folgende Beispiel greift meine Geschichte von weiter oben auf. Es berechnet, wie spät es in New York ist, wenn die Zeiger der Uhr in Berlin (für München existiert leider kein eigener Eintrag in der Java-Zeitzonentabelle) auf 19:20 stehen. Von wegen, in Bayern gehen die Uhren anders.

Smiley

    String[] ids = TimeZone.getAvailableIDs();
    TimeZone berlin = null;
    TimeZone newYork = null;
    for (String id : ids) {
      String lc = id.toLowerCase();
      if (lc.contains("berlin")) {
        berlin = TimeZone.getTimeZone(id);
      } else if (lc.contains("new_york")) {
        newYork = TimeZone.getTimeZone(id);
      }
    }
    if ((berlin != null) && (newYork != null)) {
      Calendar cal = Calendar.getInstance(berlin);
      cal.set(Calendar.HOUR_OF_DAY, 19);
      cal.set(Calendar.MINUTE, 20);
      System.out.println(cal.get(Calendar.HOUR_OF_DAY) + ":"
          + cal.get(Calendar.MINUTE));
      cal.setTimeZone(newYork);
      System.out.println(cal.get(Calendar.HOUR_OF_DAY) + ":"
          + cal.get(Calendar.MINUTE));
    }

Das programmatische Ermitteln von Zeitzonen auf Basis der Ids ist nicht ganz ungefährlich. Ich würde mich eher auf die Auswahl durch den Benutzer verlassen. Ansonsten sollte das kurze Quelltextfragment keine Fragen aufwerfen. Oder haben Sie welche? Falls ja, schreiben Sie mir.

2 comments:

  1. Hi,
    der Beitrag gefällt mir.
    Hab hier noch weitere Inhalte zu dem Thema Zeitzonen und UTC gefunden:

    http://www.zeitzonen.org/weltzeit.html

    ReplyDelete
  2. Vielen Dank für den Link.

    Freunde des .NET-Frameworks werden vielleicht Gefallen an meinem Follow-Up finden. Dort zeige ich, wie man in .NET zwischen Zeitzonen konvertiert.

    ReplyDelete