CGI のカレンダーを作成しました。 ちょっと殺風景ですが... CGI のサンプル? 的なものです。
カレンダー関係は、
などがありますが、CGI も作ってあったので... 基本的には、Ruby でカレンダー の出力部分を cgi-lib.rb で処理しているだけです。 コマンドライン上で動かすと、HTML の出力をしますよ。
- Ruby でカレンダー コマンドライン
- JavaScript による calendar
cgi-lib.rb は 1.9 系ではサポートされません。
引数がない場合は、当年当月です。 引数として、「1970 〜 2037」までは年、「1 〜 12」までは月として扱います。
cgi-bin に登録してある場合には、URL は次のようになります。
上から順番に、「当月」「2000 年 1 月」「今年の 12 月」です。http://localhost/cgi-bin/cal.rb http://localhost/cgi-bin/cal.rb?2000+1 http://localhost/cgi-bin/cal.rb?12
出力は次のような感じです。
April 1999
Su Mo Tu We Th Fr Sa
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
ページにこれしか出力しないので、ちょっとつまらないですね。
Web ブラウザでの表示上は Ruby のスクリプトですが、HTML の特殊文字をエスケープしています。 テキストとしてセーブしてご利用ください。
#! /usr/local/bin/ruby
# /home/tetsu/src/ruby/cgi/cal.rb
# Created: March 26,1999 Friday 14:55:05
# Author: tetsu(WATANABE Tetsuya)
# $Id: cal.rb,v 1.6 2007/04/28 12:22:49 tetsu Exp $
# usage:
def mkLastMod
t = Time.at(0)
[
'/home/httpd/cgi-bin/cal.rb'
].each do |f|
next if not File.exist?(f)
w = File.mtime(f)
t = w if w > t
end
t
end
require 'cgi-lib'
require 'tcal'
year = 0
month = 0
ARGV.each do |arg|
foo = arg.to_i
if foo >= 1 and foo <= 12
month = foo
elsif foo >= 1970 and foo <= 2037
year = foo
end
end
cal = TCalendar.new(year, month)
msg = cal.header
1.upto(31) do |d|
wday = cal.wday(d)
break unless wday
status = cal.status(d)
if (d == 1)
msg.concat(' ' * wday)
elsif wday == 0
msg.concat("\n")
end
day_str =
case status
when 'weekend', 'holiday'
CGI::tag("font", {"color"=>"red"}) {
format('%2d', d)
}
when 'workday'
format('%2d', d)
end
if cal.today?(d)
msg.concat(CGI::tag('b') {day_str})
else
msg.concat(day_str)
end
msg.concat(' ')
end
# last_mod = mkLastMod.gmtime.strftime('%a, %d %b %Y %X %Z')
# CGI::print("Content-Type: text/html", "Last-Modified: " + last_mod) {
CGI::print {
CGI::tag("html") {
CGI::tag("head") {
CGI::tag("meta",
{"http-equiv"=>"Content-Type",
"content"=>"text/html; charset=ISO-2022-JP"}) +\
CGI::tag("title") { 'cal' }
} +\
CGI::tag("body",
{"bgcolor"=>"#e0e0e0",
"text"=>"#0f0f0f",
"link"=>"#0000ff",
"vlink"=>"#000080",
"alink"=>"#ff0000"
}) {
CGI::tag('pre') { msg }
}
}
}
print "\n"
クラスライブラリです。 cgi ですので、site_ruby などのシステムレベルのライブラリを入れる場所にお願いします。
#! /usr/local/bin/ruby
# /home/tetsu/src/ruby/class/tcal.rb
# created: September 24,2005 Saturday 13:38:32
# author: tetsu(WATANABE Tetsuya)
# $Id: tcal.rb,v 1.2 2005/09/24 04:53:40 tetsu Exp $
# usage:
class TCalendar
def initialize(year = 0, month = 0)
@now = Time.now
@year = if year == 0 then @now.year else year end
@month = if month == 0 then @now.month else month end
@holiday = []
@holiday_name = []
@mday_arr = []
1.upto(31) do |d|
@mday_arr[d] = Time.local(@year, @month, d, 0, 0, 0)
if d > 28
if @mday_arr[d].month != @month
@mday_arr[d] = nil
end
end
@holiday[d] = false
end
month_name = @mday_arr[1].strftime('%b')
# このデータ形式は次のようになっています。
# 月名<space>日付<space>有効年<space>コメント
# 行の先頭の「#」以降はコメント
# 木村さん感謝!
# HM2 Happy Monday(2nd monday)
# HM3 Happy Monday(3rd monday)
holiday_str = '
Jan 1 0 元旦
Jan 15 -1999 成人の日
Jan HM2 2000- 成人の日
Feb 11 0 建国記念の日
Mar SHUNBUN 0 春分の日
Apr 29 -1988 天皇誕生日
Apr 29 1989-2006 みどりの日
Apr 29 2007- 昭和の日
May 3 0 憲法記念日
# May 4 1986-2006 国民の休日
May 4 2007- みどりの日
May 5 0 こどもの日
Jul 20 1996-2002 海の日
Jul HM3 2003- 海の日
Sep 15 -2002 敬老の日
Sep HM3 2003- 敬老の日
Sep SYUBUN 0 秋分の日
Oct 10 -1999 体育の日
Oct HM2 2000- 体育の日
Nov 3 0 文化の日
Nov 23 0 勤労感謝の日
Dec 23 1989- 天皇誕生日
'
holiday_str.split(/\n/).each do |l|
next if l == '' or l =~ /^\#/
l.sub!(/\#.*$/, '')
m, d, y, c = l.split(/\s+/, 4)
if y != '0'
if y[0,1] == '-'
next if @year > y[1,4].to_i
elsif y[-1,1] == '-'
next if @year < y[0,4].to_i
elsif y[4,1] == '-'
next if @year < y[0,4].to_i || @year > y[5,4].to_i
end
end
if month_name == m
case d
when 'SHUNBUN'
d = syunbun(@year).to_s
when 'SYUBUN'
d = syubun(@year).to_s
when 'HM2'
d = nMonday(2).to_s
when 'HM3'
d = nMonday(3).to_s
end
@holiday[d.to_i] = true
@holiday_name[d.to_i] = c
end
end
if @year >= 1986
i = 0
while i < 31 - 2
if @holiday[i] and @holiday[i + 1] == false and @mday_arr[i + 1].wday != 0 and @holiday[i + 2]
@holiday[i + 1] = true
@holiday_name[i + 1] = '国民の休日'
i += 1 # skip
end
i += 1
end
end
end
attr_reader :holiday_name, :year, :month
def nMonday(n)
count = 0
@mday_arr.each_index do |d|
next if d < 1
count += 1 if @mday_arr[d].wday == 1
return d if count == n
end
end
def today?(mday)
@now.year == @year and @now.month == @month and @now.mday == mday
end
def wday(mday)
return nil unless @mday_arr[mday]
@mday_arr[mday].wday
end
def status(mday)
return nil unless @mday_arr[mday]
return 'holiday' if @holiday[mday]
case @mday_arr[mday].wday
when 1
if mday > 1 and @holiday[mday - 1]
return 'holiday'
else
return 'workday'
end
when 2, 3, 4, 5
'workday'
when 0, 6
'weekend'
end
end
def header
msg = @mday_arr[1].strftime('%B %Y').center(20)
msg + "\n" + 'Su Mo Tu We Th Fr Sa' + "\n"
end
#| From: hajima@crimson.gen.u-tokyo.ac.jp (Ryoichi Hajima)
#| Newsgroups: fj.questions.misc
#| Subject: Re: vernal/autumnal equinox
#| Message-ID: <HAJIMA.94Jul13161542@tanelorn.gen.u-tokyo.ac.jp>
#| Date: 13 Jul 94 07:15:42 GMT
#|
#| 春分日 (31y+2213)/128-y/4+y/100 (1851年-1999年通用)
#| (31y+2089)/128-y/4+y/100 (2000年-2150年通用)
#|
#| 秋分日 (31y+2525)/128-y/4+y/100 (1851年-1999年通用)
#| (31y+2395)/128-y/4+y/100 (2000年-2150年通用)
def syunbun(year)
if year > 2150
STDERR.print "over year's: #{year}\n" #'
exit 1
end
v = if year < 2000 then 2213 else 2089 end
(31 * year + v)/128 - year/4 + year/100
end
def syubun(year)
if year > 2150
STDERR.print "over year's: #{year}\n" #'
exit 1
end
v = if year < 2000 then 2525 else 2395 end
(31 * year + v)/128 - year/4 + year/100
end
end
「年」として有効なものは、UNIX としての一般的年の 1970 〜 2037 までです。
祝日はとても簡単な形で実現しています。 定義中「XX」の場合には、不定のため計算します。 この計算については、同じ月に不定の祝日が 2 日もないと決めつけていますので、もし対応できないような場合になれば修正が必要です。
休日の形式は単純なので、個人の休日などを加えるのは容易と思います。 ただ、「年」の指定が、当年だけというフォーマットは、現状ではありません。
ちょっと無駄なことをしています。 出力する「月」について、毎日の Time クラスのオブジェクトを生成しています。 曜日の計算を自分で行えば、こういうことはしなくてすむとは思いますが、便利なのでついつい。
引数の「年」と「月」には、指定のための順番がありません。 好きな順番で指定してください。 URL で表記するという意味では、決まりがあった方がいいと思うのですが...
クラスライブラリを別ファイルにしました。 この別ファイルは Ruby でカレンダー と共通になっています。
ハッピーマンデーの「海の日」「敬老の日」の開始年は 2003 年から