Calendar: Difference between revisions

Content added Content deleted
m (Fixed IBM 1403 link to wikipedia)
(→‎{{header|Ruby}}: Adjust output for different widths. New problem with Curses.)
Line 477: Line 477:


=={{header|Ruby}}==
=={{header|Ruby}}==
{{improve|Ruby|<code>Curses.close_screen</code> has an awful side effect: it writes some escape sequences to stdout, which is awful when one pipes stdout to another program. Should stop using Curses, and instead use shell command <code>tput cols</code>.}}
{{Template:Needs-review}}

{{incomplete|Ruby|The width is always 130 characters. The program needs more code to adjust the calendar for different widths.}}
<code>Date</code> class, from the standard library, knows how many days in a month, and which day is Sunday, for both Julian and Gregorian calendars. This program uses <code>Date</code> class, plus its own assumptions, to create the calendar. This program assumes that every year has 12 months and starts with January 1, and every month fits in 6 weeks starting with Sunday.

<lang ruby>require 'date'
<lang ruby>require 'date'


# Creates a calendar of _year_. Returns this calendar as a multi-line
def cal(year)
# string fit to _columns_.
def cal(year, columns)

# Start at January 1.
#
# Date::ENGLAND marks the switch from Julian calendar to Gregorian
# calendar at 1752 September 14. This removes September 3 to 13 from
# year 1752. (By fortune, it keeps January 1.)
#
date = Date.new(year, 1, 1, Date::ENGLAND)

# Collect calendars of all 12 months.
months = (1..12).collect do |month|
months = (1..12).collect do |month|
rows = [Date::MONTHNAMES[month].center(20), "Su Mo Tu We Th Fr Sa"]
rows = [Date::MONTHNAMES[month].center(20), "Su Mo Tu We Th Fr Sa"]


# Make array of 42 days, starting with Sunday.
days = []
days = []
date = Date.new(year, month, 1, Date::ENGLAND)
date.wday.times { days.push " " }
date.wday.times { days.push " " }
while date.month == month
while date.month == month
Line 498: Line 512:
end
end


# Calculate months per row (mpr).
rows = ["[Snoopy]".center(130), "#{year}".center(130)]
# 1. Divide columns by 22 columns per month, rounded down. (Pretend
months.each_slice(6) do |half|
# to have 2 extra columns; last month uses only 20 columns.)
rows.push " "
# 2. Decrease mpr if 12 months would fit in the same months per
half[0].each_index do |i|
# column (mpc). For example, if we can fit 5 mpr and 3 mpc, then
rows.push(half.map {|a| a[i]}.join " ")
# we use 4 mpr and 3 mpc.
mpr = (columns + 2).div 22
mpr = 12.div((12 + mpr - 1).div mpr)

# Use 20 columns per month + 2 spaces between months.
width = mpr * 22 - 2

# Join months into calendar.
rows = ["[Snoopy]".center(width), "#{year}".center(width)]
months.each_slice(mpr) do |slice|
slice[0].each_index do |i|
rows.push(slice.map {|a| a[i]}.join " ")
end
end
end
end
Line 508: Line 534:
end
end



case ARGV.length
ARGV.length == 1 or raise "usage: #{$0} year"
when 1

puts cal(Integer(ARGV[0]))
# Guess width of terminal device.
else
# 1. Obey environment variable COLUMNS.
raise "usage: #{$0} year"
# 2. Try to get columns from Curses library.
end</lang>
# 3. Assume 80 columns.
columns = Integer(ENV["COLUMNS"]) \
rescue (require 'curses'
Curses.close_screen # Measure screen, so Curses.cols != 0.
Curses.cols) \
rescue 80

puts cal(Integer(ARGV[0]), columns)</lang>


=={{header|Tcl}}==
=={{header|Tcl}}==