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:
 
=={{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'
 
# 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, month1, 1, Date::ENGLAND)
 
# Collect calendars of all 12 months.
months = (1..12).collect do |month|
rows = [Date::MONTHNAMES[month].center(20), "Su Mo Tu We Th Fr Sa"]
 
# Make array of 42 days, starting with Sunday.
days = []
date = Date.new(year, month, 1, Date::ENGLAND)
date.wday.times { days.push " " }
while date.month == month
Line 498 ⟶ 512:
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(130width), "#{year}".center(130width)]
months.each_slice(6mpr) do |halfslice|
halfslice[0].each_index do |i|
rows.push(halfslice.map {|a| a[i]}.join " ")
end
end
Line 508 ⟶ 534:
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}}==