summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authortadf <tadf@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2004-01-18 22:14:02 +0000
committertadf <tadf@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2004-01-18 22:14:02 +0000
commit089aecb1490bbe182126de0c8007e1ba43c0a549 (patch)
tree7f9fd541b44b1ecd035b30bb1d6c224109871370
parentc5c450cded45a3e61e5560f7b739489de260d548 (diff)
synchronized with date2 3.5.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/ruby_1_8@5495 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r--ChangeLog10
-rw-r--r--lib/date.rb114
-rw-r--r--lib/date/format.rb14
-rw-r--r--sample/cal.rb225
4 files changed, 207 insertions, 156 deletions
diff --git a/ChangeLog b/ChangeLog
index 095232fe4d..82cd4949b1 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,13 @@
+Mon Jan 19 07:09:20 2004 Tadayoshi Funaba <tadf@dotrb.org>
+
+ * lib/date.rb: zone was wrong when it was behind UTC.
+ Thanks Mark J. Reed.
+
+ * lib/date/format.rb: %z is now always replaced by four digits
+ with a leading plus or minus sign.
+
+ * sample/cal.rb: added a class, anyway.
+
Sun Jan 18 20:47:35 2004 WATANABE Hirofumi <eban@ruby-lang.org>
* ruby.c: use translate_char() on Cygwin.
diff --git a/lib/date.rb b/lib/date.rb
index 21e35a6660..0747da1295 100644
--- a/lib/date.rb
+++ b/lib/date.rb
@@ -1,20 +1,20 @@
-#
+#
# date.rb - date and time library
#
-# Author: Tadayoshi Funaba 1998-2002
+# Author: Tadayoshi Funaba 1998-2004
#
# Documentation: William Webber <william@williamwebber.com>
#
#--
-# $Id: date.rb,v 2.8 2002-06-08 00:39:51+09 tadf Exp $
+# $Id: date.rb,v 2.11 2004-01-19 04:56:12+09 tadf Exp $
#++
#
# == Overview
#
# This file provides two classes for working with
# dates and times.
-#
-# The first class, Date, represents dates.
+#
+# The first class, Date, represents dates.
# It works with years, months, weeks, and days.
# See the Date class documentation for more details.
#
@@ -28,11 +28,11 @@
# In common usage, the date is reckoned in years since or
# before the Common Era (CE/BCE, also known as AD/BC), then
# as a month and day-of-the-month within the current year.
-# This is known as the *Civil* *Date*, and abbrevated
+# This is known as the *Civil* *Date*, and abbrevated
# as +civil+ in the Date class.
#
-# Instead of year, month-of-the-year, and day-of-the-month,
-# the date can also be reckoned in terms of year and
+# Instead of year, month-of-the-year, and day-of-the-month,
+# the date can also be reckoned in terms of year and
# day-of-the-year. This is known as the *Ordinal* *Date*,
# and is abbreviated as +ordinal+ in the Date class. (Note
# that referring to this as the Julian date is incorrect.)
@@ -58,7 +58,7 @@
# Date class as the *Astronomical* *Julian* *Day* *Number*, and
# abbreviated as +ajd+. In the Date class, the Astronomical
# Julian Day Number includes fractional days.
-#
+#
# Another absolute day count is the *Modified* *Julian* *Day*
# *Number*, which takes November 17, 1858 as its initial day.
# This is abbreviated as +mjd+ in the Date class. There
@@ -80,7 +80,7 @@
# The standard civil year is 365 days long. However, the
# solar year is fractionally longer than this. To account
# for this, a *leap* *year* is occasionally inserted. This
-# is a year with 366 days, the extra day falling on February 29.
+# is a year with 366 days, the extra day falling on February 29.
# In the early days of the civil calendar, every fourth
# year without exception was a leap year. This way of
# reckoning leap years is the *Julian* *Calendar*.
@@ -94,7 +94,7 @@
#
# The Gregorian Calendar was introduced at different times
# in different regions. The day on which it was introduced
-# for a particular region is the *Day* *of* *Calendar*
+# for a particular region is the *Day* *of* *Calendar*
# *Reform* for that region. This is abbreviated as +sg+
# (for Start of Gregorian calendar) in the Date class.
#
@@ -103,24 +103,24 @@
# the Day of Calendar Reform for Italy and most Catholic
# countries. The second is September 14, 1752, which was
# the Day of Calendar Reform for England and its colonies
-# (including what is now the United States). These two
+# (including what is now the United States). These two
# dates are available as the constants Date::ITALY and
# Date::ENGLAND, respectively. (By comparison, Germany and
# Holland, less Catholic than Italy but less stubborn than
# England, changed over in 1698; Sweden in 1753; Russia not
# till 1918, after the Revolution; and Greece in 1923. Many
# Orthodox churches still use the Julian Calendar. A complete
-# list of Days of Calendar Reform can be found at
+# list of Days of Calendar Reform can be found at
# http://www.polysyllabic.com/GregConv.html.)
#
# Switching from the Julian to the Gregorian calendar
# involved skipping a number of days to make up for the
# accumulated lag, and the later the switch was (or is)
# done, the more days need to be skipped. So in 1582 in Italy,
-# 4th October was followed by 15th October, skipping 10 days; in 1752
+# 4th October was followed by 15th October, skipping 10 days; in 1752
# in England, 2nd September was followed by 14th September, skipping
-# 11 days; and if I decided to switch from Julian to Gregorian
-# Calendar this midnight, I would go from 27th July 2003 (Julian)
+# 11 days; and if I decided to switch from Julian to Gregorian
+# Calendar this midnight, I would go from 27th July 2003 (Julian)
# today to 10th August 2003 (Gregorian) tomorrow, skipping
# 13 days. The Date class is aware of this gap, and a supposed
# date that would fall in the middle of it is regarded as invalid.
@@ -148,13 +148,13 @@
# of time zones. Time zones are represented as an offset
# from UTC, as a fraction of a day. This offset is the
# how much local time is later (or earlier) than UTC.
-# UTC offset 0 is centred on England (also known as GMT).
+# UTC offset 0 is centred on England (also known as GMT).
# As you travel east, the offset increases until you
# reach the dateline in the middle of the Pacific Ocean;
# as you travel west, the offset decreases. This offset
# is abbreviated as +of+ in the Date class.
#
-# This simple representation of time zones does not take
+# This simple representation of time zones does not take
# into account the common practice of Daylight Savings
# Time or Summer Time.
#
@@ -201,7 +201,7 @@ require 'date/format'
# See the documentation to the file date.rb for an overview.
#
# Internally, the date is represented as an Astronomical
-# Julian Day Number, +ajd+. The Day of Calendar Reform, +sg+, is
+# Julian Day Number, +ajd+. The Day of Calendar Reform, +sg+, is
# also stored, for conversions to other date formats. (There
# is also an +of+ field for a time zone offset, but this
# is only for the use of the DateTime subclass.)
@@ -217,7 +217,7 @@ require 'date/format'
# Date objects are immutable once created.
#
# Once a Date has been created, date values
-# can be retrieved for the different date formats supported
+# can be retrieved for the different date formats supported
# using instance methods. For instance, #mon() gives the
# Civil month, #cwday() gives the Commercial day of the week,
# and #yday() gives the Ordinal day of the year. Date values
@@ -237,7 +237,7 @@ class Date
MONTHNAMES = [nil] + %w(January February March April May June July
August September October November December)
- # Full names of days of the week, in English. Days of the week
+ # Full names of days of the week, in English. Days of the week
# count from 0 to 6 (except in the commercial week); a day's numerical
# represenation indexed into this array gives the name of that day.
DAYNAMES = %w(Sunday Monday Tuesday Wednesday Thursday Friday Saturday)
@@ -312,7 +312,7 @@ class Date
# the Julian Day Number. +sg+ specifies the Day of
# Calendar Reform.
#
- # Returns the corresponding [year, month, day_of_month]
+ # Returns the corresponding [year, month, day_of_month]
# as a three-element array.
def self.jd_to_civil(jd, sg=GREGORIAN)
if os?(jd, sg)
@@ -351,7 +351,7 @@ class Date
# +jd+ is the Julian Day Number to convert.
# +sg+ specifies the Day of Calendar Reform.
#
- # Returns the corresponding Ordinal Date as
+ # Returns the corresponding Ordinal Date as
# [year, day_of_year]
def self.jd_to_ordinal(jd, sg=GREGORIAN)
y = jd_to_civil(jd, sg)[0]
@@ -378,7 +378,7 @@ class Date
# Convert a Commercial Date to a Julian Day Number.
#
- # +y+, +w+, and +d+ are the (commercial) year, week of the year,
+ # +y+, +w+, and +d+ are the (commercial) year, week of the year,
# and day of the week of the Commercial Date to convert.
# +sg+ specifies the Day of Calendar Reform.
def self.commercial_to_jd(y, w, d, ns=GREGORIAN)
@@ -405,7 +405,7 @@ class Date
# Convert an Astronomical Julian Day Number to a (civil) Julian
# Day Number.
#
- # +ajd+ is the Astronomical Julian Day Number to convert.
+ # +ajd+ is the Astronomical Julian Day Number to convert.
# +of+ is the offset from UTC as a fraction of a day (defaults to 0).
#
# Returns the (civil) Julian Day Number as [day_number,
@@ -416,10 +416,10 @@ class Date
# Day Number.
#
# +jd+ is the Julian Day Number to convert, and +fr+ is a
- # fractional day.
+ # fractional day.
# +of+ is the offset from UTC as a fraction of a day (defaults to 0).
#
- # Returns the Astronomical Julian Day Number as a single
+ # Returns the Astronomical Julian Day Number as a single
# numeric value.
def self.jd_to_ajd(jd, fr, of=0) jd + fr - of - 1.to_r/2 end
@@ -438,7 +438,7 @@ class Date
h.to_r/24 + min.to_r/1440 + s.to_r/86400
end
- # Convert an Astronomical Modified Julian Day Number to an
+ # Convert an Astronomical Modified Julian Day Number to an
# Astronomical Julian Day Number.
def self.amjd_to_ajd(amjd) amjd + 4800001.to_r/2 end
@@ -450,7 +450,7 @@ class Date
# Day Number.
def self.mjd_to_jd(mjd) mjd + 2400001 end
- # Convert a Julian Day Number to a Modified Julian Day
+ # Convert a Julian Day Number to a Modified Julian Day
# Number.
def self.jd_to_mjd(jd) jd - 2400001 end
@@ -490,7 +490,7 @@ class Date
# Create a new Date object from a Julian Day Number.
#
# +jd+ is the Julian Day Number; if not specified, it defaults to
- # 0.
+ # 0.
# +sg+ specifies the Day of Calendar Reform.
def self.jd(jd=0, sg=ITALY)
jd = valid_jd?(jd, sg)
@@ -504,8 +504,8 @@ class Date
# +d+ can be a negative number, in which case it counts backwards
# from the end of the year (-1 being the last day of the year).
# No year wraparound is performed, however, so valid values of
- # +d+ are -365 .. -1, 1 .. 365 on a non-leap-year,
- # -366 .. -1, 1 .. 366 on a leap year.
+ # +d+ are -365 .. -1, 1 .. 365 on a non-leap-year,
+ # -366 .. -1, 1 .. 366 on a leap year.
# A date falling in the period skipped in the Day of Calendar Reform
# adjustment is not valid.
#
@@ -541,15 +541,15 @@ class Date
new0(jd_to_ajd(jd, 0, 0), 0, sg)
end
- # Do year +y+, month +m+, and day-of-month +d+ make a
- # valid Civil Date? Returns the corresponding Julian
+ # Do year +y+, month +m+, and day-of-month +d+ make a
+ # valid Civil Date? Returns the corresponding Julian
# Day Number if they do, nil if they don't.
#
# +m+ and +d+ can be negative, in which case they count
# backwards from the end of the year and the end of the
# month respectively. No wraparound is performed, however,
# and invalid values cause an ArgumentError to be raised.
- # A date falling in the period skipped in the Day of Calendar
+ # A date falling in the period skipped in the Day of Calendar
# Reform adjustment is not valid.
#
# +sg+ specifies the Day of Calendar Reform.
@@ -580,7 +580,7 @@ class Date
# backwards from the end of the year and the end of the
# month respectively. No wraparound is performed, however,
# and invalid values cause an ArgumentError to be raised.
- # can be negative
+ # can be negative
#
# +y+ defaults to -4712, +m+ to 1, and +d+ to 1; this is
# Julian Day Number day 0.
@@ -605,7 +605,7 @@ class Date
# backwards from the end of the year and the end of the
# week respectively. No wraparound is performed, however,
# and invalid values cause an ArgumentError to be raised.
- # A date falling in the period skipped in the Day of Calendar
+ # A date falling in the period skipped in the Day of Calendar
# Reform adjustment is not valid.
#
# +sg+ specifies the Day of Calendar Reform.
@@ -659,7 +659,7 @@ class Date
# according to a specified format.
#
# +str+ is a String holding a date representation.
- # +fmt+ is the format that the date is in. See
+ # +fmt+ is the format that the date is in. See
# date/format.rb for details on supported formats.
#
# The default +str+ is '-4712-01-01', and the default
@@ -678,7 +678,7 @@ class Date
# Create a new Date object by parsing from a String,
# without specifying the format.
#
- # +str+ is a String holding a date representation.
+ # +str+ is a String holding a date representation.
# +comp+ specifies whether to interpret 2-digit years
# as 19XX (>= 69) or 20XX (< 69); the default is not to.
# The method will attempt to parse a date from the String
@@ -723,7 +723,7 @@ class Date
# *NOTE* this is the documentation for the method new0(). If
# you are reading this as the documentation for new(), that is
- # because rdoc doesn't fully support the aliasing of the
+ # because rdoc doesn't fully support the aliasing of the
# initialize() method.
# new() is in
# fact an alias for #civil(): read the documentation for that
@@ -731,9 +731,9 @@ class Date
#
# Create a new Date object.
#
- # +ajd+ is the Astronomical Julian Day Number.
+ # +ajd+ is the Astronomical Julian Day Number.
# +of+ is the offset from UTC as a fraction of a day.
- # Both default to 0.
+ # Both default to 0.
#
# +sg+ specifies the Day of Calendar Reform to use for this
# Date object.
@@ -817,13 +817,7 @@ class Date
private :hour, :min, :sec, :sec_fraction
- def zone
- ['Z',
- format('%+.2d%02d',
- (@of / (1.to_r/24)).to_i,
- (@of.abs % (1.to_r/24) / (1.to_r/1440)).to_i)
- ][@of<=>0]
- end
+ def zone() strftime('%Z') end
private :zone
@@ -921,7 +915,7 @@ class Date
# Compare this date with another date.
#
- # +other+ can also be a Numeric value, in which case it is
+ # +other+ can also be a Numeric value, in which case it is
# interpreted as an Astronomical Julian Day Number.
#
# Comparison is by Astronomical Julian Day Number, including
@@ -975,7 +969,7 @@ class Date
def << (n) self >> -n end
# Step the current date forward +step+ days at a
- # time (or backward, if +step+ is negative) until
+ # time (or backward, if +step+ is negative) until
# we reach +limit+ (inclusive), yielding the resultant
# date at each step.
def step(limit, step) # :yield: date
@@ -991,13 +985,13 @@ class Date
# Step forward one day at a time until we reach +max+
# (inclusive), yielding each date as we go.
def upto(max, &block) # :yield: date
- step(max, +1, &block)
- end
+ step(max, +1, &block)
+ end
# Step backward one day at a time until we reach +min+
# (inclusive), yielding each date as we go.
def downto(min, &block) # :yield: date
- step(min, -1, &block)
+ step(min, -1, &block)
end
# Return a new Date one day after this one.
@@ -1057,7 +1051,7 @@ end
#
# Get the hour-of-the-day of the time. This is given
# using the 24-hour clock, counting from midnight. The first
-# hour after midnight is hour 0; the last hour of the day is
+# hour after midnight is hour 0; the last hour of the day is
# hour 23.
#
# === min()
@@ -1165,7 +1159,7 @@ class DateTime < Date
# +of+ is the offset from UTC as a fraction of a day (defaults to 0).
# +sg+ specifies the Day of Calendar Reform.
#
- # +y+ defaults to -4712, +m+ to 1, and +d+ to 1; this is Julian Day
+ # +y+ defaults to -4712, +m+ to 1, and +d+ to 1; this is Julian Day
# Number day 0. The time values default to 0.
def self.civil(y=-4712, m=1, d=1, h=0, min=0, s=0, of=0, sg=ITALY)
unless (jd = valid_civil?(y, m, d, sg)) and
@@ -1221,7 +1215,7 @@ class DateTime < Date
# according to a specified format.
#
# +str+ is a String holding a date-time representation.
- # +fmt+ is the format that the date-time is in. See
+ # +fmt+ is the format that the date-time is in. See
# date/format.rb for details on supported formats.
#
# The default +str+ is '-4712-01-01T00:00:00Z', and the default
@@ -1239,7 +1233,7 @@ class DateTime < Date
# Create a new DateTime object by parsing from a String,
# without specifying the format.
#
- # +str+ is a String holding a date-time representation.
+ # +str+ is a String holding a date-time representation.
# +comp+ specifies whether to interpret 2-digit years
# as 19XX (>= 69) or 20XX (< 69); the default is not to.
# The method will attempt to parse a date-time from the String
@@ -1266,9 +1260,7 @@ class DateTime < Date
a = i.to_a[0..5].reverse
jd = civil_to_jd(*(a[0,3] << sg))
fr = time_to_day_fraction(*(a[3,3])) + i.usec.to_r/86400000000
- d = Time.gm(*i.to_a).to_i - i.to_i
- d += d / d.abs if d.nonzero?
- of = (d / 60).to_r/1440
+ of = i.utc_offset.to_r/86400
new0(jd_to_ajd(jd, fr, of), of, sg)
end
diff --git a/lib/date/format.rb b/lib/date/format.rb
index f00f60ab47..d3d8d17511 100644
--- a/lib/date/format.rb
+++ b/lib/date/format.rb
@@ -1,5 +1,5 @@
-# format.rb: Written by Tadayoshi Funaba 1999-2003
-# $Id: format.rb,v 2.9 2003-04-19 19:19:35+09 tadf Exp $
+# format.rb: Written by Tadayoshi Funaba 1999-2004
+# $Id: format.rb,v 2.12 2004-01-19 05:43:28+09 tadf Exp $
class Date
@@ -501,8 +501,14 @@ class Date
when '%x'; o << strftime('%m/%d/%y')
when '%Y'; o << '%.4d' % year
when '%y'; o << '%02d' % (year % 100)
- when '%Z'; o << zone
- when '%z'; o << zone # ID
+ when '%Z'; o << (if offset.zero? then 'Z' else strftime('%z') end)
+ when '%z' # ID
+ o << if offset < 0 then '-' else '+' end
+ of = offset.abs
+ hh, fr = of.divmod(1.to_r/24)
+ mm = fr / (1.to_r/1440)
+ o << '%02d' % hh
+ o << '%02d' % mm
when '%%'; o << '%'
when '%+'; o << strftime('%a %b %e %H:%M:%S %Z %Y') # TZ
when '%1'; o << '%d' % jd
diff --git a/sample/cal.rb b/sample/cal.rb
index e17c5e2a3e..fa20352f71 100644
--- a/sample/cal.rb
+++ b/sample/cal.rb
@@ -1,111 +1,154 @@
#! /usr/bin/env ruby
-# cal.rb: Written by Tadayoshi Funaba 1998-2002
-# $Id: cal.rb,v 2.4 2002-06-08 00:40:29+09 tadf Exp $
+# cal.rb: Written by Tadayoshi Funaba 1998-2004
+# $Id: cal.rb,v 2.7 2004-01-10 23:52:51+09 tadf Exp $
require 'date'
-require 'getopts'
-
-$tab =
-{
- 'cn' => true, # China
- 'de' => 2342032, # Germany (protestant states)
- 'dk' => 2342032, # Denmark
- 'es' => 2299161, # Spain
- 'fi' => 2361390, # Finland
- 'fr' => 2299227, # France
- 'gb' => 2361222, # United Kingdom
- 'gr' => 2423868, # Greece
- 'hu' => 2301004, # Hungary
- 'it' => 2299161, # Italy
- 'jp' => true, # Japan
- 'no' => 2342032, # Norway
- 'pl' => 2299161, # Poland
- 'pt' => 2299161, # Portugal
- 'ru' => 2421639, # Russia
- 'se' => 2361390, # Sweden
- 'us' => 2361222, # United States
- 'os' => false, # (old style)
- 'ns' => true # (new style)
-}
-
-$cc = 'gb'
-
-def usage
- warn 'usage: cal [-c iso3166] [-jmty] [[month] year]'
- exit 1
-end
-
-def pict(y, m, sg)
- d = (1..31).detect{|d| Date.valid_date?(y, m, d, sg)}
- fi = Date.new(y, m, d, sg)
- fi -= (fi.jd - $k + 1) % 7
- ve = (fi..fi + 6).collect{|cu|
- %w(S M Tu W Th F S)[cu.wday]
- }
- ve += (fi..fi + 41).collect{|cu|
- if cu.mon == m then cu.send($da) end.to_s
+class Cal
+
+ START =
+ {
+ 'cn' => true, # China
+ 'de' => 2342032, # Germany (protestant states)
+ 'dk' => 2342032, # Denmark
+ 'es' => 2299161, # Spain
+ 'fi' => 2361390, # Finland
+ 'fr' => 2299227, # France
+ 'gb' => 2361222, # United Kingdom
+ 'gr' => 2423868, # Greece
+ 'hu' => 2301004, # Hungary
+ 'it' => 2299161, # Italy
+ 'jp' => true, # Japan
+ 'no' => 2342032, # Norway
+ 'pl' => 2299161, # Poland
+ 'pt' => 2299161, # Portugal
+ 'ru' => 2421639, # Russia
+ 'se' => 2361390, # Sweden
+ 'us' => 2361222, # United States
+ 'os' => false, # (old style)
+ 'ns' => true # (new style)
}
- ve = ve.collect{|e| e.rjust($dw)}
-
- gr = group(ve, 7)
- gr = trans(gr) if $OPT_t
- ta = gr.collect{|xs| xs.join(' ')}
-
- ca = %w(January February March April May June July
- August September October November December)[m - 1]
- ca = ca + ' ' + y.to_s if not $OPT_y
- ca = ca.center($mw)
-
- ta.unshift(ca)
-end
+ DEFAULT_START = 'gb'
+
+ def initialize
+ opt_j; opt_m; opt_t; opt_y; opt_c
+ end
+
+ def opt_j(flag=false) @opt_j = flag end
+ def opt_m(flag=false) @opt_m = flag end
+ def opt_t(flag=false) @opt_t = flag end
+ def opt_y(flag=false) @opt_y = flag end
+
+ def opt_c(arg=DEFAULT_START) @start = START[arg] end
+
+ def set_params
+ @dw = if @opt_j then 3 else 2 end
+ @mw = (@dw + 1) * 7 - 1
+ @mn = if @opt_j then 2 else 3 end
+ @tw = (@mw + 2) * @mn - 2
+ @k = if @opt_m then 1 else 0 end
+ @da = if @opt_j then :yday else :mday end
+ end
+
+ def pict(y, m)
+ d = (1..31).detect{|d| Date.valid_date?(y, m, d, @start)}
+ fi = Date.new(y, m, d, @start)
+ fi -= (fi.jd - @k + 1) % 7
+
+ ve = (fi..fi + 6).collect{|cu|
+ %w(S M Tu W Th F S)[cu.wday]
+ }
+ ve += (fi..fi + 41).collect{|cu|
+ if cu.mon == m then cu.send(@da) end.to_s
+ }
+
+ ve = ve.collect{|e| e.rjust(@dw)}
+
+ gr = group(ve, 7)
+ gr = trans(gr) if @opt_t
+ ta = gr.collect{|xs| xs.join(' ')}
+
+ ca = %w(January February March April May June July
+ August September October November December)[m - 1]
+ ca = ca + ' ' + y.to_s if not @opt_y
+ ca = ca.center(@mw)
+
+ ta.unshift(ca)
+ end
+
+ def group(xs, n)
+ (0..xs.size / n - 1).collect{|i| xs[i * n, n]}
+ end
+
+ def trans(xs)
+ (0..xs[0].size - 1).collect{|i| xs.collect{|x| x[i]}}
+ end
+
+ def stack(xs)
+ if xs.empty? then [] else xs[0] + stack(xs[1..-1]) end
+ end
+
+ def block(xs, n)
+ stack(group(xs, n).collect{|ys| trans(ys).collect{|zs| zs.join(' ')}})
+ end
+
+ def unlines(xs)
+ xs.collect{|x| x + "\n"}.join
+ end
+
+ def monthly(y, m)
+ unlines(pict(y, m))
+ end
+
+ def addmon(y, m, n)
+ y, m = (y * 12 + (m - 1) + n).divmod(12)
+ return y, m + 1
+ end
+
+ def yearly(y)
+ y.to_s.center(@tw) + "\n\n" +
+ unlines(block((0..11).collect{|n| pict(*addmon(y, 1, n))}, @mn)) + "\n"
+ end
+
+ def print(y, m)
+ set_params
+ if @opt_y then yearly(y) else monthly(y, m) end
+ end
-def group(xs, n)
- (0..xs.size / n - 1).collect{|i| xs[i * n, n]}
end
-def trans(xs)
- (0..xs[0].size - 1).collect{|i| xs.collect{|x| x[i]}}
-end
+if __FILE__ == $0
-def unite(xs)
- if xs.empty? then [] else xs[0] + unite(xs[1..-1]) end
-end
+ require 'getopts'
-def block(xs, n)
- unite(group(xs, n).collect{|ys| trans(ys).collect{|zs| zs.join(' ')}})
-end
+ def usage
+ warn 'usage: cal [-c iso3166] [-jmty] [[month] year]'
+ exit 1
+ end
-def unlines(xs)
- xs.collect{|x| x + "\n"}.join
-end
+ usage unless getopts('jmty', "c:#{Cal::DEFAULT_START}")
-usage unless getopts('jmty', "c:#{$cc}")
+ y, m = ARGV.values_at(1, 0).compact.collect{|x| x.to_i}
+ $OPT_y ||= (y and not m)
-y, m = ARGV.values_at(1, 0).compact.collect{|x| x.to_i}
-$OPT_y ||= (y and not m)
+ to = Date.today
+ y ||= to.year
+ m ||= to.mon
-to = Date.today
-y ||= to.year
-m ||= to.mon
+ usage unless m >= 1 and m <= 12
+ usage unless y >= -4712
+ usage if Cal::START[$OPT_c].nil?
-usage unless m >= 1 and m <= 12
-usage unless y >= -4712
-usage if (sg = $tab[$OPT_c]).nil?
+ cal = Cal.new
-$dw = if $OPT_j then 3 else 2 end
-$mw = ($dw + 1) * 7 - 1
-$mn = if $OPT_j then 2 else 3 end
-$tw = ($mw + 2) * $mn - 2
+ cal.opt_j($OPT_j)
+ cal.opt_m($OPT_m)
+ cal.opt_t($OPT_t)
+ cal.opt_y($OPT_y)
+ cal.opt_c($OPT_c)
-$k = if $OPT_m then 1 else 0 end
-$da = if $OPT_j then :yday else :mday end
+ print cal.print(y, m)
-print(if not $OPT_y
- unlines(pict(y, m, sg))
- else
- y.to_s.center($tw) + "\n\n" +
- unlines(block((1..12).collect{|m| pict(y, m, sg)}, $mn)) + "\n"
- end)
+end