Главная » XSLT » Юлианский календарь

0

Задача

Требуется работать в старой юлианской системе летоисчисления.

Решение

<xsl:template name="ckbk:julian-date-to-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) + 365 * $y + floor($y div 4) – 32083"/>

</xsl:template>

Зная юлианский день, вы можете воспользоваться приведенными в этой главе рецептами для форматирования дат, выполнения математических операций над ними и преобразования в другие календарные системы.

Обсуждение

сегодня применяется редко (исключение составляет Русская православная церковь). Он был заменен григорианским из-за неточного предположения о том, что год состоит из 365 1/4 дней. На самом деле, средняя длина когда составляет 365.2425 дней, поэтому с течением времени в юлианском календаре времена года смещаются.

Задача

Требуется работать с датами, представленными в международном стандарте IS0-8601[1].

Читатели, знакомые со спецификацией XML Schema, не должны путать ка­лендарь ISO с форматом ISO, применяемым для записи григорианских дат (например, 2002-04-12 или 2002-0412T09:26:00). Стандарт 8601 описыва­ет и календарь, и способ форматирования. Данный рецепт относится к календарю ISO.

Решение

Для работы с ISO-датами (а также для вычисления дат некоторых праздни­ков) понадобится функция, вычисляющая абсолютный день k-ого дня недели, предшествующего заданному абсолютному дню или следующего за ним. Например, первый понедельник (k=1) не позднее 4 января 2004 года (абсолютный день 731 584) приходится на 29 декабря 2003 года (абсолютный день 731 578).

<xsl:template name="ckbk:k-date-on-or-before-abs-day"> <xsl:param name="abs-day"/> <xsl:param-name="k"/> <xsl:value-of select="$abs-day – (($abs-day – $k) mod 7)"/>

</xsl:template>

Теперь для преобразования ISO-даты в абсолютный день нужно лишь вычис­лить количество абсолютных дней в предшествующих годах и прибавить количе­ство дней в самой ISO-дате:

<xsl:template name="ckbk:iso-date-to-absolute-day"> <xsl:param name="iso-week"/> <xsl:param name="iso-day"/> <xsl:param name="iso-year"/>

<xsl:variable name="a">

<xsl:call-template name="ckbk:date-to-absolute-day"> <xsl:with-param name="year" select="$iso-year"/> <xsl:with-param name="month" select="1"/> <xsl:with-param name="day" select="4"/> </xsl:call-template> </xsl:variable>

<xsl:variable name="days-in-prior-yrs">

<xsl:call-template name="ckbk:k-day-on-or-before-abs-day"> <xsl:with-param name="abs-day" select="$a"/> <xsl:with-param name="k" select="1"/> </xsl:call-template> </xsl:variable>

<xsl:variable name="days-in-prior-weeks-this-yr" select="7 * ($iso-week – 1)"/>

<xsl:variable name="prior-days-this-week" select="$iso-day – 1"/>

<xsl:value-of select="$days-in-prior-yrs +

$days-in-prior-weeks-this-yr + $prior-days-this-week"/> </xsl:template>

Для преобразования абсолютного дня в ISO-дату мы сначала пытаемся опреде­лить год, предположив, что он такой же, как для григорианской даты минус 3 дня. Это предположение неверно только, если абсолютный день приходится на дату между 1 и 3 января следующего года. Чтобы исправить возможную ошибку, мы сравниваем дату с 1 января следующего года с помощью уже имеющегося шабло­на iso-date-to-absolute-day. Окончательно выяснив, чему равен ISO-год, мы находим номер недели и день, вычисляя смещение от 1 января этого года. ISO-дата возвращается в формате год-месяц-день. Такой формат определен в стандарте ISO, чтобы не спутать с датой по григорианскому календарю.

<xsl:template name="ckbk:absolute-day-to-iso-date"> <xsl:param name="abs-day"/>

<xsl:variable name="d">

<xsl:call-template name="ckbk:absolute-day-to-date">

<xsl:with-param name="abs-day" select="$abs-day – 3"/> </xsl:call-template> </xsl:variable>

<xsl:variable name="approx" select="substring-before($d,’/’)"/>

<xsl:variable name="iso-year"> <xsl:variable name="a">

<xsl:call-template name="ckbk:iso-date-to-absolute-day"> <xsl:with-param name="iso-week" select="1"/> <xsl:with-param name="iso-day" select="1"/> <xsl:with-param name="iso-year" select="$approx + 1"/> </xsl:call-template> </xsl:variable> <xsl:choose>

<xsl:when test="$abs-day >= $a"> <xsl:value-of select="$approx + 1"/> </xsl:when> <xsl:otherwise>

<xsl:value-of select="$approx"/> </xsl:otherwise> </xsl:choose> </xsl:variable>

<xsl:variable name="iso-week"> <xsl:variable name="a"> <xsl:call-template name="ckbk:iso-date-to-absolute-day"> <xsl:with-param name="iso-week" select="1"/> <xsl:with-param name="iso-day" select="1"/> <xsl:with-param name="iso-year" select="$iso-year"/> </xsl:call-template> </xsl:variable>

<xsl:value-of select="1 + floor(($abs-day – $a) div 7)"/> </xsl:variable>

<xsl:variable name="iso-day">

<xsl:variable name="a" select="$abs-day mod 7"/> <xsl:choose>

<xsl:when test="not($a)">

<xsl:value-of select="7"/> </xsl:when> <xsl:otherwise>

<xsl:value-of select="$a"/> </xsl:otherwise> </xsl:choose> </xsl:variable>

<xsl:value-of select="concat($iso-year,’-W’,$iso-week,’-‘,$iso-day)"/> </xsl:template>

Обсуждение

В европейских приложениях для торговых и промышленных предприятий часто бывает необходимо знать номер недели в году. В календаре ISO дата задает­ся в виде года по григорианскому календарю, номера недели (1-53) и номера дня недели (1-7, причем, согласно стандарту ISO, первым днем недели считается по­недельник). Неделя, пересекающая границу двух годов, считается принадлежа­щей тому году, в который попадает наибольшее число дней. Согласно этому правилу, первая неделя по календарю ISO может начинаться как 4 января, так и 29 декабря предыдущего года. Аналогично последняя неделя года по календарю

ISO может заканчиваться и 28 декабря, и 3 января следующего года. Например, первая ISO-неделя 2004 года началась 29 декабря 2003 года!1 Следовательно, что­бы определить, когда начинается ISO-неделя, необходимо найти последний поне­дельник, приходящийся на 4 января или ранее.

См. также

Увидеть календарь ISO в действии можно на странице http://personal.ecu.edu/ mccartyr/isowdcalhtml.

Мангано Сэл  XSLT. Сборник рецептов. – М.: ДМК Пресс, СПБ.: БХВ-Петербург, 2008. – 864 с.: ил.

По теме:

  • Комментарии