Rename the readme.
Start adding the readme.
Add some example files.
Use calendar.rb
to keep current with the birthdays, anniversaries, events, weekly reminders, and the like, that matter to you. It's easy.
# File: ~/.calendar/calendar
# Include other files like this:
#include <birthdays>
#include <anniversaries>
#include <events>
#include <tasks>
# You can define custom functions for tricky situations,
# and load those like this:
#require <custom-functions.rb>
pay_day: Payday
Add birthdays like this:
# File: ~/.calendar/birthdays
# The syntax here is:
# DD/MM: Event description
01/10: Donald Knuth (1938)
04/26: Hal Ableson (1947)
06/08: Frank Lloyd Wright (1867)
The file for one-off events looks like this:
# File: ~/.calendar/events
# The syntax here is:
# YYYY-MM-DD: Event description
2023-09-18: Your family arrives
# Times are optional.
2023-09-16 15:00: Neighborhood block party
# Descriptions can span multiple lines with leading whitepace.
2023-09-15: Grand opening party
at The Wine Cellar
There are various ways of specifying recurring events:
# File: ~/.calendar/tasks
# The syntax for these is:
# *DD: Description
*01: First of the month
# MM*: Description
01*: Every day of January
# {weekday}: Description
Sunday: GTD Weekly Review
# YYYY-MM-DD -> [0-9][dwy]
2023-09-04 -> 2w: From 2023-09-04, repeat every two weeks
You can use custom functions to specify more complex recurrence rules. For example: payday at my company is on the 10th and 25th of every month, unless that day falls on a weekend, in which case it's the prior Friday.
# File: ~/.calendar/custom-events.rb
# pay_day :: Time -> Time
def pay_day(this_date)
if (this_date.day <= 25)
next_date = this_date
if (date.day < 10)
next_date = Time.new(this_date.year, this_date.month, 10)
elsif (this_date.day < 25)
next_date = Time.new(this_date.year, this_date.month, 25)
end
if (next_date.sunday?)
next_date = next_date - (86400 * 2)
elsif (next_date.saturday?)
next_date = next_date - 86400
end
if (next_date <= this_date)
return pay_day(this_date + 86400)
else
return next_date
end
end
if (this_date.month == 12)
return pay_day(Time.new((this_date.year + 1), 1, 1))
else
return pay_day(Time.new(this_date.year, (this_date.month + 1), 1))
end
end
Custom functions like this all have the same signature and serve the same purpose: receive a Time
object representing a reference date, and return a Time
object indicating the next occurrence of the event following that date. So writing them and testing them is super simple.
# Also in file: ~/.calendar/custom-functions.rb
# [
# Time.new(2023,8,9),
# Time.new(2023,8,10),
# Time.new(2023,8,11),
# Time.new(2023,8,25),
# Time.new(2023,9,10),
# Time.new(2023,12,30)
# ].each do |date|
# puts "Payday for #{date} -> #{pay_day(date)}"
# end
Now, see what happened in January:
$ ./calendar.rb -s 2023-01-01 -e 2023-01-31
Jan 01: First of the month
Jan 01: Every day of January
Jan 01: GTD Weekly Review
Jan 02: Every day of January
Jan 03: Every day of January
...skipping some of those...
Jan 08: GTD Weekly Review
Jan 10: Donald Knuth (1938)
Jan 10: Every day of January
Jan 10: Payday
Jan 15: GTD Weekly Review
Jan 22: GTD Weekly Review
Jan 25: Payday
Jan 29: GTD Weekly Review
Jan 30: Every day of January
Jan 31: Every day of January
And in September:
$ ./calendar.rb -s 2023-09-01 -e 2023-09-30
Sep 01: First of the month
Sep 03: GTD Weekly Review
Sep 04: From 2023-09-04, repeat every two weeks
Sep 08: Payday
Sep 10: GTD Weekly Review
Sep 15: Grand opening party at The Wine Cellar
Sep 16 15:00: Neighborhood block party
Sep 17: GTD Weekly Review
Sep 18: Your family arrives
Sep 18: From 2023-09-04, repeat every two weeks
Sep 24: GTD Weekly Review
Sep 25: Payday