NAME
Date::Tolkien::Shire - Convert dates into the Shire Calendar.
SYNOPSIS
use Date::Tolkien::Shire;
my $dts = Date::Tolkien::Shire->new( time );
print $dts->on_date();
DESCRIPTION
This is an object-oriented module to convert dates into the Shire Calendar as presented in the Lord of the Rings by J. R. R. Tolkien. It includes converting epoch time to the Shire Calendar (you can also get epoch time back), comparison operators, and a method to print a formatted string that does something to the effect of on this date in history -- pulling events from the Lord of the Rings.
The biggest use I can see in this thing is in a startup script or possibly to keep yourself entertained in an otherwise boring app that includes a date. If you have any other ideas/suggestions/uses, etc., please let me know. I am curious to see how this gets used (if it gets used that is).
METHODS
Note: I have tried to make these as friendly as possible when an error occurs. As a consequence, none of them die, croak, etc. All of these return 0 on error, but as 0 can be a valid output in a couple cases (the day of the month for a holiday, for example), the error method should always be checked to see if an error has occurred. As long as you set a date before you try to use it, you should be ok.
new
$shiredate = Date::Tolkien::Shire->new;
$shiredate = Date::Tolkien::Shire->new(time);
$shiredate = Date::Tolkien::Shire->new($another_shiredate);
The constructor new()
can take zero or one parameter. Either a new object can be created without setting a specific date (the zero-parameter version), or an object can be created and the date set to either a current shire date, or an epoch time such as is returned by the time function. For specifics on setting dates, see the 'set_date' function.
This constructor also takes optional arguments as name/value pairs. The optional arguments are:
- accented
-
If this value is true (in the Perl sense), on_date() will produce accented output, as will strftime() if given a template that includes the events on the date represented by the object.
- traditional
-
If this value is true (in the Perl sense), on_date() and strftime() will produce traditional rather than common weekday names. This option does not affect the output of weekday() or trad_weekday().
error
$the_error = $shiredate->error;
$the_error = Date::Tolkien::Shire->error;
This returns a null string if everything in the previous method call was as it should be, and a string contain a description of what happened if an error occurred.
today
$shiredate = Date::Tolkien::Shire->today();
This convenience constructor returns an object set to midnight the morning of the current local day.
The optional arguments for new() may also be used here.
from_shire
$shiredate = Date::Tolkien::Shire->from_shire(
year => 1419,
month => 3,
day => 25,
);
$shiredate = Date::Tolkien::Shire->from_shire(
year => 1419,
holiday => 3,
);
This convenience constructor just wraps a call to new()
followed by a call to set_shire()
.
The optional arguments for new() may also be used here.
set_date
This method takes either the seconds from the start of the epoch (like what time()
returns) or another shire date object, and sets the date of the object in question equal to that date. If the object previously contained a date, it will be overwritten. Local time, rather than UTC, is used in converting from epoch date.
Please see the note below on calculating the year if you're curious how I arrived by that.
set_rata_die
$shiredate->set_rata_die( $datetime->utc_rd_values() );
This method takes a date in days since December 31 of Gregorian year 0, and sets the date of the invocant to that date. Only the first argument is used, but others, if provided, should be consistent with the output of the DateTime utc_rd_values()
, to save trouble in the (probably unlikely) event that I add time-of-day functionality to this package.
set_shire
$shiredate->set_shire(
year => 1418,
month => 3,
day => 25,
);
$shiredate->set_shire(
year => 1419,
holiday => 3,
);
This method sets the object's date to the given date in the Shire calendar. The named arguments are year
, month
, day
, and holiday
, and all are numeric. The year
argument is required; all others are optional. You may not specify both month
and holiday
. If month
is specified, day
defaults to 1
; otherwise holiday
defaults to 1
.
This method returns the invocant. Errors are indicated by setting the $ERROR
variable.
set_accented
This method takes a Boolean value which determines whether on_date() should produce accented output. It returns the invocant.
set_traditional
This method takes a Boolean value which determines whether on_date() should use traditional rather than common names for the days of the week. It returns the invocant.
time_in_seconds
$epoch_time = $shire_date->time_in_seconds
Returns the epoch time (with 0 for hours, minutes, and seconds) of a given shire date. This relies on the library Time::Local, so the caveats and error handling with that module apply to this method as well.
epoch
This is currently a synonym for time_in_seconds(). But if I ever implement time-of-day functionality (far from certain) this method will include that, whereas time_in_seconds() will remain as of midnight.
weekday
$day_of_week_name = $shiredate->weekday;
This method returns the day of the week using the more modern names in use during the War of the Ring and given in the Lord of the Rings Appendix D. If the day in question is not part of any week (Midyear's day and the Overlithe), then an empty string is returned.
weekday_number
$day_of_week_number = $shiredate->weekday_number;
This method returns the number of the day of the week of the date in question, or 0
if the day is not part of any week (i.e. Midyear's day
or the Overlithe
). Note that 0
is also returned on an error (date not set), so the careful programmer who uses this method will check $ERROR
if 0
is returned.
trad_weekday
$day_of_week = $shiredate->trad_weekday
This method returns the day of the week using the archaic forms, the oldest forms found in the Yellowskin of Tuckborough (also given in Appendix D). If the day in question is not part of any week (Midyear's day and the Overlithe), then an empty string is returned.
month
$month_name = $shiredate->month;
This method returns the month name of the date in question, or an empty string if the day is a holiday, since holidays are not part of any month.
day
$day_of_month = $self->day;
This method returns the day of the month of the day in question, or 0
in the case of a holiday, since they are not part of any month. Since 0
is also returned on an error (date not set), the careful programmer will check $ERROR
if 0
is returned.
holiday
$holiday_name = $shiredate->holiday;
If the day in question is a holiday, returns the holiday name: "1 Yule"
, "2 Yule"
(first day of the new year), "1 Lithe"
, "Midyear's day"
, "Overlithe"
, or "2 Lithe"
. If the day is not a holiday, an empty string is returned.
year
$shire_year = $shiredate->year;
Returns the year of the shire date in question. See the note on year calculation below if you want to see how I figured this.
accented
This method returns a true value if on_date() is to produce accented output.
traditional
This method returns a true value if on_date() is to use traditional rather than current weekday names.
Overloaded Operators
The following comparison operators are available:
$shiredate1 < $shiredate2
$shiredate1 lt $shiredate2
$shiredate1 <= $shiredate2
$shiredate1 le $shiredate2
$shiredate1 > $shiredate2
$shiredate1 gt $shiredate2
$shiredate1 >= $shiredate2
$shiredate1 ge $shiredate2
$shiredate1 == $shiredate2
$shiredate1 eq $shiredate2
$shiredate1 != $shiredate2
$shiredate1 ne $shiredate2
$shiredate1 <=> $shiredate2
$shiredate1 cmp $shiredate2
You can only compare on shire date to another (no apples to oranges here). In this context both the numeric and string operators perform the exact same function. Like the standard operators, all but <=> and cmp return 1 if the condition is true and the null string if it is false. <=> and cmp return -1 if the left operand is less than the right one, 0 if the two operands are equal, and 1 if the left operand is greater than the right one.
Additionally, you can view a shire date as a string:
# prints something like 'Monday 28 Rethe 7465'
print $shiredate;
as_string
$shire_date_as_string = $shire_date->as_string;
Returns the given shire date as a string, similar in theory to scalar localtime
. This is the method used to implement the stringification overload.
on_date
$historic_events = $shire_date->on_date
or you may want to try something like
my $shiredate = Date::Tolkien::Shire->new( time );
print "Today is " . $shiredate->on_date . "\n";
This method returns a string containing important events that happened on this day and month in history, as well as the day itself. It does not give much more usefulness as far as using dates go, but it should be fun to run during a startup script or something. At present the events are limited to the crucial years at the end of the third age when the final war of the ring took place and Sauron was permanently defeated. More dates will be added as I find them (if I find them maybe I should say). All the ones below come from Appendix B of the Lord of the Rings. At this point, these are only available in English.
Note here that the string is formatted. This is to keep things simple when using it as in the example above. Note that in this example you are actually ending with a double newline, as the first newline is part of the return value.
If you don't like how this is formatted, complain at me and if I like you I'll consider changing it :-)
If accented() is true, this method returns accented output. If traditional() is true, this method uses traditional rather than common weekday names.
strftime
This is a re-implementation imported from Date::Tolkien::Shire::Data. It is intended to be reasonably compatible with the same-named DateTime method, but has some additions to deal with the peculiarities of the Shire calendar.
See __format() in Date::Tolkien::Shire::Data for the documentation, since that is the code that does the heavy lifting for us.
If accented() is true, this method returns accented output. If traditional() is true, this method uses traditional rather than common weekday names.
NOTE: YEAR CALCULATION
http://www.glyphweb.com/arda/f/fourthage.html references a letter sent by Tolkien in 1958 in which he estimates approximately 6000 years have passed since the War of the Ring and the end of the Third Age. (Thanks to Danny O'Brien from sending me this link). I took this approximate as an exact and calculated back 6000 years from 1958 and set this as the start of the 4th age (1422). Thus the fourth age begins in our B.C 4042.
According to Appendix D of the Lord of the Rings, leap years in the hobbits' calendar are every 4 years unless it is the turn of the century, in which case it is not a leap year. Our calendar uses every 4 years unless it is 100 years unless it is 400 years. So, if no changes had been made to the hobbits' calendar since the end of the third age, their calendar would be about 15 days further behind ours now then when the War of the Ring took place. Implementing this seemed to me to go against Tolkien's general habit of converting dates in the novel to our equivalents to give us a better sense of time. My thoughts, at least right now, is that it is truer to the spirit of things for March 25 today to be about the same as March 25 was back then. So instead, I have modified Tolkien's description of the hobbits' calendar so that leap years occur once every 4 years unless it is 100 years unless it is 400 years, so that it matches our calendar in that regard. These 100 and 400 year intervals occur at different times in the two calendars, however. Thus the last day of our year is sometimes 7 Afteryule, sometimes 8, and sometimes 9.
BIBLIOGRAPHY
Tolkien, J. R. R. Return of the King. New York: Houghton Mifflin Press, 1955.
http://www.glyphweb.com/arda/f/fourthage.html
BUGS
Epoch time. Since epoch time was used as the base for this module, and the only way to currently set a date is from epoch time, it borks on values that epoch time doesn't support (currently values before 1902 or after 2037). The module should automatically expand in available dates directly with epoch time support on your system.
Support is by the author. Please file bug reports at https://rt.cpan.org/Public/Dist/Display.html?Name=Date-Tolkien-Shire, https://github.com/trwyant/perl-Date-Tolkien-Shire/issues, or in electronic mail to the author.
AUTHOR
Tom Braun <tbraun@pobox.com>
Thomas R. Wyant, III wyant at cpan dot org
COPYRIGHT AND LICENSE
Copyright (c) 2001-2003, 2006 Tom Braun. All rights reserved.
Copyright (C) 2017-2021 Thomas R. Wyant, III
The calendar implemented on this module was created by J.R.R. Tolkien, and the copyright is still held by his estate. The license and copyright given herein applies only to this code and not to the calendar itself.
This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. For more details, see the full text of the licenses in the directory LICENSES.
This program is distributed in the hope that it will be useful, but without any warranty; without even the implied warranty of merchantability or fitness for a particular purpose.