Julianische und absolute Tageszahlen aus einem angegebenen Datum berechnen

(Auszug aus "XSLT Kochbuch" von Sal Mangano)

Problem

Sie haben ein Datum und wollen die entsprechenden Zahlen des julianischen Tages und/oder des absoluten Tages ermitteln.

Julianischer Tag und julianisches Datum im Vergleich

Machen Sie nicht den Fehler, den julianischen Tag mit dem julianischen Kalender zu verwechseln. Joseph J. Scaliger hat die julianische Periode erfunden, bei der jedes Jahr mit einer positiven Zahl verknüpft werden kann, ohne dass man sich um Formulierungen wie v. Chr. oder v. u. Z. bzw. n. Chr. oder u. Z. befassen muss. Die Periode beginnt am 1. Januar 4713 v. u. Z. (entsprechend dem julianischen Kalender) und dauert 7980 Jahre. Astronomen haben die julianische Periode verwendet, um dem Tag seit dem 1. Januar 4713 v. u. Z. eine eindeutige Zahl zuzuweisen. Das ist der julianische Tag. Dieses Kapitel ist am julianischen Tag 2.452.376 entstanden. Wenn Sie neugierig sind, können Sie anhand des Codes in diesem Kapitel das tatsächliche Datum ermitteln. Ein anderes absolutes Zahlenschema, das von N. Dershowitz und E. Reingold in ihren Kalenderalgorithmen benutzt wird, beginnt am 1. Januar 1 u. Z. Ich bezeichne eine Zahl in deren System als absolute Tageszahl. Der absolute Tag 1 entspricht dem julianischen Tag 1.721.426.

Lösung

XSLT 1.0

Dieses Template liefert Ihnen den julianischen Tag, wenn Jahr, Monat und Tag gegeben sind:

<xsl:template name="ckbk:calculate-julian-day">
  <xsl:param name="year"/>
  <xsl:param name="month"/>
  <xsl:param name="day"/>
  <xsl:variable name="a" select="floor((14 - $month) div 12)"/>
  <xsl:variable name="y" select="$year + 4800 - $a"/>
  <xsl:variable name="m" select="$month + 12 * $a - 3"/>
  <xsl:value-of select="$day + floor((153 * $m + 2) div 5) + $y * 365 + floor($y div 4) - floor($y div 100) + floor($y div 400) - 32045"/>
</xsl:template>

Sobald Sie eine Methode haben, um die julianische Tageszahl zu berechnen, ist es einfach, die Anzahl der Tage zwischen zwei beliebigen Daten zu ermitteln:

<xsl:template name="ckbk:date-difference">
  <xsl:param name="from-year"/>
  <xsl:param name="from-month"/>
  <xsl:param name="from-day"/>
  <xsl:param name="to-year"/>
  <xsl:param name="to-month"/>
  <xsl:param name="to-day"/>
  <xsl:variable name="jd1">
    <xsl:call-template name="ckbk:calculate-julian-day">
      <xsl:with-param name="year" select="$from-year"/>
      <xsl:with-param name="month" select="$from-month"/>
      <xsl:with-param name="day" select="$from-day"/>
    </xsl:call-template>
  </xsl:variable>
  <xsl:variable name="jd2">
    <xsl:call-template name="ckbk:calculate-julian-day">
      <xsl:with-param name="year" select="$to-year"/>
      <xsl:with-param name="month" select="$to-month"/>
      <xsl:with-param name="day" select="$to-day"/>
    </xsl:call-template>
  </xsl:variable>
  <xsl:value-of select="$jd1 - $jd2"/>
</xsl:template>

Die folgenden Templates konvertieren von einem julianischen Tag in ein gregorianisches Datum der Form JJJJ/MM/TT. Verwenden Sie substring-before, substring-after und translate, um die Konventionen einer bestimmten Lokalisierung zu analysieren oder zu konvertieren:

<xsl:template name="ckbk:julian-day-to-julian-date">
  <xsl:param name="j-day"/>
  <xsl:call-template name="ckbk:julian-or-gregorian-date-elem">
    <xsl:with param name="b" select="0"/>
    <xsl:with param name="c" select="$j-day + 32082"/>
  </xsl:call-template>
</xsl:template>
<xsl:template name="ckbk:julian-day-to-gregorian-date">
  <xsl:param name="j-day"/>
  <xsl:variable name="a" select="$j-day + 32044"/>
  <xsl:variable name="b" select="floor((4 * $a + 3) div 146097)"/>
  <xsl:variable name="c" select="$a - 146097 * floor($b div 4)"/>
  <xsl:call-template name="ckbk:julian-or-gregorian-date-elem">
    <xsl:with param name="b" select="$b"/>
    <xsl:with param name="c" select="$c"/>
  </xsl:call-template>
</xsl:template>
<!-- Ein Hilfsmittel, das sowohl für gregorianische als auch für julianische Kalender verwendet wird. -->
<xsl:template name="ckbk:julian-or-gregorian-date-elem">
  <xsl:param name="b"/>
  <xsl:param name="c"/>
  <xsl:variable name="d" select="floor((4 * $c + 3) div 1461)"/>
  <xsl:variable name="e" select="$c - floor((1461 * $d) div 4)"/>
  <xsl:variable name="m" select="floor((5 * $e + 2) div 153)"/>
  <xsl:variable name="day" select="$e - floor((153 * $m + 2) div 5) + 1"/>
  <xsl:variable name="month" select="$m + 3 - (12 * floor($m div 10))"/>
  <xsl:variable name="year" select="100 * $b + $d - 4800 + floor($m div 10)"/>
  <xsl:value-of select="concat($year,'/',$month,'/',$day)"/>
</xsl:template>

Mit den folgenden Templates können Sie einfach zwischen julianischen Tagen und absoluten Tagen konvertieren:

<xsl:template name="ckbk:julian-day-to-absolute-day">
  <xsl:param name="j-day"/>
  <xsl:value-of select="$j-day - 1721425"/>
</xsl:template>
<xsl:template name="ckbk:absolute-day-to-julian-day">
  <xsl:param name="abs-day"/>
  <xsl:value-of select="$abs-day + 1721425"/>
</xsl:template>

Sie können dann die Umrechnungen des absoluten Tages in ein gregorianisches Datum in Bezug auf die existierenden Umrechnungen von julianischem Tag in ein gregorianisches Datum ausdrücken:

<xsl:template name="ckbk:date-to-absolute-day">
  <xsl:param name="year"/>
  <xsl:param name="month"/>
  <xsl:param name="day"/>
  <xsl:call-template name="ckbk:julian-day-to-absolute-day">
    <xsl:with-param name="j-day">
      <xsl:call-template name="ckbk:date-to-julian-day">
        <xsl:with-param name="year" select="$year"/>
        <xsl:with-param name="month" select="$month"/>
        <xsl:with-param name="day" select="$day"/>
      </xsl:call-template>
    </xsl:with-param>
  </xsl:call-template>
</xsl:template>
<xsl:template name="ckbk:absolute-day-to-date">
  <xsl:param name="abs-day"/>
  <xsl:call-template name="ckbk:julian-day-to-date">
    <xsl:with-param name="j-day">
      <xsl:call-template name="ckbk:absolute-day-to-julian-day">
        <xsl:with-param name="abs-day" select="$abs-day"/>
      </xsl:call-template>
    </xsl:with-param>
  </xsl:call-template>
</xsl:template>

XSLT 2.0

Es besteht in XSLT 2.0 kein Bedarf mehr an Funktionen für julianische und absolute Tage, da die Datumsberechnungen direkt unterstützt werden.

<dateDiff>
  <xsl:value-of select="xs:date('2005-02-21') - xs:date('2005-01-01')"/>
</dateDiff>

ergibt zum Beispiel:

<dateDiff>P51D</dateDiff>

Manche Anwendungen brauchen diese Werte aber möglicherweise für andere Zwecke. Hier beschließen wir, die 1.0-Templates im Hinblick auf Funktionen zu implementieren, die anstelle der einzelnen Komponenten ein xs:date entgegennehmen:

<xsl:function name="ckbk:calculate-julian-day">
  <xsl:param name="date" as="xs:date"/>
  <xsl:variable name="year" select="year-from-date($date)" as="xs:integer"/>
  <xsl:variable name="month" select="month-from-date($date)" as="xs:integer"/>
  <xsl:variable name="day" select="month-from-date($date)" as="xs:integer"/>
  <xsl:variable name="a" select="(14 - $month) idiv 12" as="xs:integer"/>
  <xsl:variable name="y" select="$year + 4800 - $a" as="xs:integer"/>
  <xsl:variable name="m" select="$month + 12 * $a - 3" as="xs:integer"/>
  <xsl:sequence select="$day + ((153 * $m + 2) idiv 5) + $y * 365 + floor($y div 4) - ($y idiv 100) + ($y idiv 400) - 32045"/>
</xsl:function>

Diskussion

Julianischer und absoluter Tag sind nützlich, weil sie die anderen Datumsalgorithmen stark vereinfachen. Andere Beispiele in diesem Kapitel greifen immer wieder auf diese Konvertierungen zurück. Die Nummerierungsschemata dienen als gemeinsame Währung für alle Kalendersysteme in diesem Kapitel. Sollten Sie jemals vor der Aufgabe stehen, ein hebräisches Datum in ein muslimisches Datum umzuwandeln, können Sie bequem den Weg »muslimisches zu absolutes zu hebräisches Datum« gehen.

  

<< zurück vor >>

 

 

 

Tipp der data2type-Redaktion:
Zum Thema XSLT bieten wir auch folgende Schulungen zur Vertiefung und professionellen Fortbildung an:

Copyright © 2006 O'Reilly Verlag GmbH & Co. KG
Für Ihren privaten Gebrauch dürfen Sie die Online-Version ausdrucken.
Ansonsten unterliegt dieses Kapitel aus dem Buch "XSLT Kochbuch" denselben Bestimmungen, wie die gebundene Ausgabe: Das Werk einschließlich aller seiner Teile ist urheberrechtlich geschützt. Alle Rechte vorbehalten einschließlich der Vervielfältigung, Übersetzung, Mikroverfilmung sowie Einspeicherung und Verarbeitung in elektronischen Systemen.

O'Reilly Verlag GmbH & Co. KG, Balthasarstraße 81, 50670 Köln, kommentar(at)oreilly.de