Calendar (cal) using Ruby

# ruby
#
# cal.rb
# unix like utility to display a month or a year at a time

require 'optparse'

# types
ProgramOptions = Struct.new(:byMonth, :byYear)
DayStruct = Struct.new(:year, :month, :day, :weekday)

# global vars
daysInAMonth = %w{-1 31 28 31 30 31 30 31 31 30 31 30 31 -1}
options = ProgramOptions.new(true, false)
month = Time.now.month
year = Time.now.year
days = Array.new

def isLeap(year)
	isLeapYear = ((year % 400) == 0)
	isLeapYear |= ((year % 4) == 0)

	if (isLeapYear) then
		isLeapYear &= ((year % 100) != 0)
	end
	isLeapYear
end

def firstDayOfMonth(month, year)
	fd = Time.local(year, month, 1,0,0,0,0)
end

def handleArgs(args)
	optHandler = OptionParser.new

	optHandler.on("-m", "--month", Integer, "Display calendar by month") { options.byMonth = true; ARGV.delete("-m"); ARGV.delete("--month") }
	optHandler.on("-y", "--year",Integer, "Display calendar by year") { options.byYear = true; options.byMonth = false; ARGV.delete("-y"); ARGV.delete("--year") }
	optHandler.on("-h", "--help",nil,"Display this help") { puts optHandler; exit }

	optHandler.parse(args)
end

def printTitle(yy, mm)
	puts " "*10 + Time.local(yy,mm,1,0,0,0,0).strftime("%b %Y")
	weekDays = %w{Sun Mon Tue Wed Thu Fri Sat}
	puts " " + weekDays.join(" ")
end

def fillDayDataStruct(wday, daysThisMonth, yy, mm)
	indx = 0
	days = Array.new
	(1..wday.to_i).each { |d|
		oneDay = DayStruct.new(0,0,0,indx)
		days.push oneDay
		indx = indx.succ
	}

	(1..daysThisMonth.to_i).each { |d|
		oneDay = DayStruct.new(yy, mm, d, Time.local(yy,mm,d,0,0,0,0).strftime("%w"))
		days.push oneDay
	}
	days
end

def printCalendar(days)
	indx = 0
	while (indx <= days.size-1) do	
		if (days[indx].month == 0) then
			print "    "
		else
			printf "%4d", days[indx].day
			puts if (days[indx].weekday.to_i == 6)
		end
		indx = indx.succ
	end
end

def monthCalendar(mon, yy, da) 
	localTime = Time.local(yy, mon, 1,0,0,0,0)
	weekDay = localTime.strftime("%w")
	monthString = localTime.strftime("%b")

	# udpate dayArray depending on year being leap or not
	if (isLeap(yy)) then
		daysInAMonth[2] = 29
	end
	
	daysThisMonth = da[mon]

	printTitle(yy,mon)
	days = fillDayDataStruct(weekDay, daysThisMonth, yy, mon)
	printCalendar(days)
	puts
end

# ===== main =====
if (ARGV.size > 0) then
	begin
		month = ARGV[0].to_i
		if (month > 12) then
			options.byYear = true
			options.byMonth = false
			year = month
		end
	rescue
		STDERR.puts "Unable to convert argument to month"
		exit
	end
else
	month = Time.now.month
end

if (ARGV.size > 1) then
	begin
		year = ARGV[1].to_i
	rescue
		STDERR.puts "Unable to convert argument to year"
		exit
	end
else
	year = Time.now.year
end

if (options.byMonth) then
	year = Time.now.year.to_i
	monthCalendar(month, year, daysInAMonth)
end

if (options.byYear) then
	year = month
	(1..12).each { |mon|
		monthCalendar(mon, year, daysInAMonth)
	}
end
# eof : cal.rb

rubycal.txt · Last modified: 2014/10/26 01:52 (external edit)
CC Attribution-Share Alike 3.0 Unported
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0