challenge 年間カレンダー

nを入力としてn年の年間カレンダーを返すプログラムを作ってください
少なくとも日曜日と土曜日が判別出来るようにしてください
出力は標準出力でもファイルでも構いません
デザインは各自のお好みで

出力例1:
(y-calendar 2008)=>
#=Saturday, @=Sunday
2008/1 1 2 3 4 #5 @6 7 ...
2008/2 1 #2 @3 4 5 6 7 ...
...
2008/12 1 2 3 4 5 #6 @7 ...

出力例2:
(y-calendar 2008)=>
        M T W T F S S M
2008/ 1   1 2 3 4 5 6 7 ...
2008/ 2         1 2 3 4 ...
...
2008/12 1 2 3 4 5 6 7 8 ...

出力例3:
(y-calendar 2008)は2008.htmlを出力する
2008.htmlの中身
----
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
       "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<title>2008 calendar</title>
<style type="text/css">
* {font-family: monospace;}
span {margin: 0px 3px;}
span.sunday {color:red;font-weight:bold;}
span.saturday {color:blue;font-weight:bold;}
dd ul li{display:inline;}
</style>
</head>
<body>
<h1>2008 calendar</h1>
<dl>
<dt>2008/1</dt>
<dd><ul>
<li><span class="weekday">1</span></li>
<li><span class="weekday">2</span></li>
<li><span class="weekday">3</span></li>
<li><span class="weekday">4</span></li>
<li><span class="saturday">5</span></li>
<li><span class="sunday">6</span></li>
...
</ul></dd>
...
</dl>
</body>
</html>
----

Posted feedbacks - XSLT

出力はシンプルなHTMLのtableで。
しかし、曜日を取得する関数を自作しなきゃいかんとわ...
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
<xsl:stylesheet version="2.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:xs="http://www.w3.org/2001/XMLSchema"
  xmlns:fn="http://www.w3.org/2005/xpath-functions"
  xmlns:my="uri:ja.doukaku.org:my-functions"
  exclude-result-prefixes="xs fn my"
  >

  <xsl:param name="n" as="xs:integer" >2008</xsl:param>

  <xsl:output method="html" />

  <xsl:template match="/" >
    <html>
      <head>
        <title><xsl:value-of select="$n" />年の年間カレンダー</title>
      </head>
      <body>
        <h1><xsl:value-of select="$n" />年の年間カレンダー</h1>
        <xsl:for-each select="1 to 12">
          <hr />
          <h2><xsl:value-of select="." />月</h2>
          <xsl:call-template name="mcalender">
            <xsl:with-param name="year" select="$n" />
            <xsl:with-param name="month" select="." />
          </xsl:call-template>
        </xsl:for-each>
      </body>
    </html>
  </xsl:template>

  <xsl:template name="mcalender">
    <xsl:param name="year" as="xs:integer" />
    <xsl:param name="month" as="xs:integer" />

    <!-- 今月1日 -->
    <xsl:variable name="first-date" as="xs:date"
      select="xs:date(
        fn:string-join(
          (my:pad($year,4),my:pad($month,2),'01'),
          '-'))" />
    <!-- 次月1日 -->
    <xsl:variable name="next-first-date" as="xs:date">
      <xsl:choose>
        <xsl:when test="$month=12">
          <xsl:value-of
            select="xs:date(
              fn:string-join(
                (my:pad($year+1,4),'01','01'),
                '-'))" />
        </xsl:when>
        <xsl:otherwise>
          <xsl:value-of
            select="xs:date(
              fn:string-join(
                (my:pad($year,4),my:pad($month+1,2),'01'),
                '-'))" />
        </xsl:otherwise>
      </xsl:choose>
    </xsl:variable>
    <!-- 今月の日数を求める -->
    <xsl:variable name="days" as="xs:integer"
      select="fn:days-from-duration($next-first-date - $first-date)" />

    <!-- 今月1日 の曜日を求める -->
    <xsl:variable name="start-day" as="xs:integer"
      select="my:get-day($first-date)" />

    <!-- カレンダーの左上の開始日 -->
    <xsl:variable name="rstart" as="xs:integer"
      select="1 - $start-day" />
    <!-- カレンダーの右下の終了日 -->
    <xsl:variable name="rend" as="xs:integer">
      <xsl:choose>
        <xsl:when test="(($days - $rstart + 1) mod 7)=0">
          <xsl:value-of select="$days - $rstart + 1" />
        </xsl:when>
        <xsl:otherwise>
          <xsl:value-of select="((($days - $rstart+1) idiv 7)+1)*7" />
        </xsl:otherwise>
      </xsl:choose>
    </xsl:variable>

    <table border="1">
      <xsl:call-template name="calender-header" />
      <xsl:for-each select="1 to $rend idiv 7">
        <tr>
          <xsl:for-each select="$rstart+((.-1)*7) to $rstart+(.*7)-1">
            <td>
              <xsl:choose>
                <xsl:when test="1 &lt;= . and . &lt;= $days">
                  <xsl:value-of select="." />
                </xsl:when>
                <xsl:otherwise>
                  <xsl:text>&#160;</xsl:text>
                </xsl:otherwise>
              </xsl:choose>
            </td>
          </xsl:for-each>
        </tr>
      </xsl:for-each>
    </table>
  </xsl:template>

  <xsl:template name="calender-header">
    <tr>
      <xsl:for-each select="('日','月','火','水','木','金','土')">
        <th><xsl:value-of select="." /></th>
      </xsl:for-each>
    </tr>
  </xsl:template>

  <!-- 曜日を取得する -->
  <xsl:function name="my:get-day" as="xs:integer">
    <xsl:param name="date" as="xs:date" />
    <xsl:variable name="epoch" as="xs:date"
      select="xs:date('1970-01-01')" />

    <xsl:variable name="day" as="xs:integer"
      select="(fn:days-from-duration($date - $epoch) + 4) mod 7" />
    <xsl:choose>
      <xsl:when test="$day &lt; 0">
        <xsl:value-of select="$day + 7" />
      </xsl:when>
      <xsl:otherwise>
        <xsl:value-of select="$day" />
      </xsl:otherwise>
    </xsl:choose>
  </xsl:function>

  <xsl:function name="my:pad" as="xs:string">
    <xsl:param name="i" as="xs:integer" />
    <xsl:param name="digit" as="xs:integer" />

    <xsl:variable name="seq" as="xs:string*">
      <xsl:for-each
        select="1 to $digit - fn:string-length(xs:string($i))">
        <xsl:sequence select="'0'" />
      </xsl:for-each>
      <xsl:sequence select="xs:string($i)" />
    </xsl:variable>

    <xsl:value-of select="fn:string-join($seq, '')" />
  </xsl:function>
</xsl:stylesheet>

Index

Feed

Other

Link

Pathtraq

loading...