суббота, 28 апреля 2012 г.

Иногда возникает непонятное желание получить дату в Юлианском стиле.
Если у кого-то вдруг это желание возникает при написании XSLT преобразования, то ему - я думаю - облегчит жизнь следующий скрипт (julian-1600.xsl):


<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:template name="julian">
    <!--Construct Julian value for the Date-->
    <xsl:param name="date"/>
    <xsl:param name="add" select="0"/>
    <xsl:param name="year"/>
    <xsl:param name="month"/>
    <xsl:param name="day"/>
    <xsl:param name="jul_year"/>
    <xsl:param name="jul_month"/>
    <xsl:param name="jul_day"/>
    <xsl:choose>
      <xsl:when test="number($add) != $add">
        <xsl:call-template name="julian">
          <xsl:with-param name="date" select="$date"/>
          <xsl:with-param name="add" select="0"/>
          <xsl:with-param name="year" select="$year"/>
          <xsl:with-param name="month" select="$month"/>
          <xsl:with-param name="day" select="$day"/>
          <xsl:with-param name="jul_year" select="$jul_year"/>
          <xsl:with-param name="jul_month" select="$jul_month"/>
          <xsl:with-param name="jul_day" select="$jul_day"/>
        </xsl:call-template>
      </xsl:when>
      <xsl:when test="string-length($date) &gt;= 10">
        <xsl:call-template name="julian">
          <xsl:with-param name="year" select="substring-before($date,'-')"/>
          <xsl:with-param name="month" select="substring-before(substring-after($date,'-'),'-')"/>
          <xsl:with-param name="day">
            <xsl:choose>
              <xsl:when test="contains($date,'T')">
                <xsl:value-of select="substring-before(substring-after(substring-after($date,'-'),'-'),'T')"/>
              </xsl:when>
              <xsl:otherwise>substring-after(substring-after($date,'-'),'-'))</xsl:otherwise>
            </xsl:choose>
          </xsl:with-param>
          <xsl:with-param name="jul_year" select="1600"/>
          <xsl:with-param name="jul_month" select="1"/>
          <xsl:with-param name="jul_day" select="1"/>
          <xsl:with-param name="add" select="2305448 + $add"/>
        </xsl:call-template>
      </xsl:when>
      <xsl:when test="number($jul_year) + 400 &lt;= number($year)">
        <xsl:call-template name="julian">
          <xsl:with-param name="year" select="$year"/>
          <xsl:with-param name="month" select="$month"/>
          <xsl:with-param name="day" select="$day"/>
          <xsl:with-param name="jul_year" select="$jul_year+400"/>
          <xsl:with-param name="jul_month" select="$jul_month"/>
          <xsl:with-param name="jul_day" select="$jul_day"/>
          <xsl:with-param name="add" select="$add + 365*400 + 97"/>
        </xsl:call-template>
      </xsl:when>
      <xsl:when test="number($jul_year) + 4 &lt;= number($year)">
        <xsl:call-template name="julian">
          <xsl:with-param name="year" select="$year"/>
          <xsl:with-param name="month" select="$month"/>
          <xsl:with-param name="day" select="$day"/>
          <xsl:with-param name="jul_year" select="$jul_year+4"/>
          <xsl:with-param name="jul_month" select="$jul_month"/>
          <xsl:with-param name="jul_day" select="$jul_day"/>
          <xsl:with-param name="add" select="$add + 365*4 + 1"/>
        </xsl:call-template>
      </xsl:when>
      <xsl:otherwise>
        <xsl:variable name="bis_sextus">
          <xsl:value-of select="1 * (number($jul_year) mod 400 = 0 or (number($jul_year) mod 4 = 0 and number($jul_year) mod 100 != 0))"/>
        </xsl:variable>
        <xsl:variable name="month_days">
          <xsl:value-of select="31 - (number($jul_month)=4 or number($jul_month)=6 or number($jul_month)=9 or number($jul_month)=11) * 1 - (number($jul_month)=2)*(3-number($bis_sextus))"/>
        </xsl:variable>
        <xsl:choose>
          <xsl:when test="number($jul_year) &lt; number($year)">
            <xsl:call-template name="julian">
              <xsl:with-param name="year" select="$year"/>
              <xsl:with-param name="month" select="$month"/>
              <xsl:with-param name="day" select="$day"/>
              <xsl:with-param name="jul_year" select="$jul_year+1"/>
              <xsl:with-param name="jul_month" select="$jul_month"/>
              <xsl:with-param name="jul_day" select="$jul_day"/>
              <xsl:with-param name="add" select="$add + 365 + $bis_sextus"/>
            </xsl:call-template>
          </xsl:when>
          <xsl:when test="number($jul_month) &lt; number($month)">
            <xsl:call-template name="julian">
              <xsl:with-param name="year" select="$year"/>
              <xsl:with-param name="month" select="$month"/>
              <xsl:with-param name="day" select="$day"/>
              <xsl:with-param name="jul_year" select="$jul_year"/>
              <xsl:with-param name="jul_month" select="$jul_month + 1"/>
              <xsl:with-param name="jul_day" select="$jul_day"/>
              <xsl:with-param name="add" select="$add + $month_days"/>
            </xsl:call-template>
          </xsl:when>
          <xsl:when test="number($jul_day) &lt; number($day)">
            <xsl:call-template name="julian">
              <xsl:with-param name="year" select="$year"/>
              <xsl:with-param name="month" select="$month"/>
              <xsl:with-param name="day" select="$day"/>
              <xsl:with-param name="jul_year" select="$jul_year"/>
              <xsl:with-param name="jul_month" select="$jul_month"/>
              <xsl:with-param name="jul_day" select="$day"/>
              <xsl:with-param name="add" select="$add + $day - $jul_day"/>
            </xsl:call-template>
          </xsl:when>
          <xsl:otherwise>
            <xsl:value-of select="$add"/>
          </xsl:otherwise>
        </xsl:choose>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>
</xsl:stylesheet>

Ну и ниже привожу пример трансляции xml файла с датой в её "Юлианское" представление.
root.xml:
<?xml version="1.0" encoding="UTF-8"?>
<root>2011-12-02T00:00:00</root>
root.xsl:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:include href="julian-1600.xsl"/>
    <xsl:output method="text" version="1.0" encoding="UTF-8" indent="yes"/>
    <xsl:template match="root">Julian (<xsl:value-of select="."/>): <xsl:call-template name="julian">
            <xsl:with-param name="date">
                <xsl:value-of select="."/>
            </xsl:with-param>
        </xsl:call-template>
    </xsl:template>
</xsl:stylesheet>

msxsl root.xml root.xsl:
Julian (2011-12-02T00:00:00): 2455898

P.S.> Единственное ограничение - дата не ранее 01.01.1600.

Комментариев нет:

Отправить комментарий