#!/usr/bin/perl -w use strict; use Time::Local; # Number of horizontal calendars to draw. use constant CALENDAR_COUNT => 2; # Color bitmasks. use constant CURRENT_MONTH => 1; use constant CURRENT_DAY => 2; use constant FULL_MOON => 4; my ($x, $y, $z, $mday, $month, $year, $wday, @current, @t, @colors, $i, $j, $k, $l, @c, @age); my @palette = ( "\e[90;40m", "\e[37;40m", "\e[30;47m", "\e[30;47m", "\e[90;40m", "\e[96;40m", "\e[30;106m", ); sub LocalTime() { return localtime $l; } sub Align() { ($x, $y, $z, $mday, $month, $year) = LocalTime; $l = timelocal 0, 0, 0, $k ? $mday : 1, $month, $year; } sub Output($$) { print $_[0] if $_[1]; } @t = (time); if( !$#ARGV ) { if( $ARGV[0] !~ /^(\d+)-(\d+)-(\d+)$/ || !defined($t[0] = eval { timelocal(0, 0, 0, $3, $2 - 1, $1 - 1900) }) ) { die "Unable to parse $ARGV[0] as YYYY-MM-DD\n"; } } for($i = 0; $i < CALENDAR_COUNT; $i++) { $l = $t[$i]; ($x, $y, $z, $mday, $month, $year) = LocalTime; push @current, [$year, $month, $i ? -1 : $mday]; $k = 0; for(Align;; Align) { ($x, $y, $z, $mday, $month, $k, $wday) = LocalTime; last if !$wday; $l -= 43200; } $t[$i] = $l; @c = @age = (); for($j = 0; $j < 6 * 7; $j++) { ($x, $y, $z, $mday, $month, $year, $wday, $k) = LocalTime; $k += $year * 365 + int(~-$year / 4) - int(~-$year / 100) + int(($year + 299) / 400); use constant PERIOD => 29.530588853; push @age, $k - int($k / PERIOD) * PERIOD; push @c, ($month - $current[$i][1] ? 0 : $mday - $current[$i][2] ? CURRENT_MONTH : CURRENT_DAY); $l += 86400 + 43200; Align; } for($j = 0; $j < 6 * 7 - 1; $j++) { $c[$j] |= FULL_MOON if $age[$j] <= 15.5 && $age[$j + 1] > 15.5; push @c, 0; } push @colors, [@c]; Output " ", $i; printf "\e[97;40m\e[4m %04d-%02d" . (" " x 26) . "\e[0m", $current[$i][0] + 1900, $current[$i][1] + 1; push @t, $t[$i] + 86400 * 6 * 7; } Output "\n", 1; for($j = 0; $j < 7; $j++) { for($i = 0; $i < CALENDAR_COUNT; $i++) { Output " ", $i; for($k = 0; $k < 7; $k++) { $x = $colors[$i][$j * 7 + $k]; $y = $j * 7 + $k > 6 ? $colors[$i][$j * 7 + $k - 7] : 0; $z = $x | $y; $z = $z - (CURRENT_MONTH | CURRENT_DAY | FULL_MOON) ? $z : CURRENT_DAY | ($x - CURRENT_DAY && $y - CURRENT_DAY ? FULL_MOON : 0); Output "$palette[$z] \e[0m ", 1; } } Output "\n", 1; if( $j < 6 ) { for($i = 0; $i < CALENDAR_COUNT; $i++) { $l = $t[$i]; Output " ", $i; for($wday = 0; $wday < 7; $wday++) { ($x, $y, $z, $mday) = LocalTime; printf '%s %2d '."\e[0m ", $palette[$colors[$i][$j * 7 + $wday]], $mday; $l += 86400 + 43200; Align; } $t[$i] = $l; } Output "\n", 1; } }