date.rb - date and time library
Author: Tadayoshi Funaba 1998-2006
Documentation: William Webber <william@williamwebber.com>
This file provides two classes for working with dates and times.
The first class, Date, represents dates. It works with years, months, weeks, and days. See the Date class documentation for more details.
The second, DateTime, extends Date to include hours, minutes, seconds, and fractions of a second. It provides basic support for time zones. See the DateTime class documentation for more details.
In common usage, the date is reckoned in years since or before the Common
Era (CE/BCE, also known as AD/BC), then as a month and day-of-the-month
within the current year. This is known as the Civil
Date, and abbreviated as civil
in the Date class.
Instead of year, month-of-the-year, and day-of-the-month, the date can
also be reckoned in terms of year and day-of-the-year. This is known as
the Ordinal Date, and is abbreviated as
ordinal
in the Date class. (Note that
referring to this as the Julian date is incorrect.)
The date can also be reckoned in terms of year, week-of-the-year, and
day-of-the-week. This is known as the Commercial
Date, and is abbreviated as commercial
in the
Date class. The commercial week runs Monday
(day-of-the-week 1) to Sunday (day-of-the-week 7), in contrast to the civil
week which runs Sunday (day-of-the-week 0) to Saturday (day-of-the-week 6).
The first week of the commercial year starts on the Monday on or before
January 1, and the commercial year itself starts on this Monday, not
January 1.
For scientific purposes, it is convenient to refer to a date simply as a
day count, counting from an arbitrary initial day. The date first chosen
for this was January 1, 4713 BCE. A count of days from this date is the
Julian Day Number or
Julian Date, which is abbreviated as
jd
in the Date class. This is in
local time, and counts from midnight on the initial day. The stricter
usage is in UTC, and counts from midday on the initial day. This is
referred to in the Date class as the
Astronomical Julian Day
Number, and abbreviated as ajd
. In the Date class, the Astronomical Julian Day Number
includes fractional days.
Another absolute day count is the Modified
Julian Day Number, which
takes November 17, 1858 as its initial day. This is abbreviated as
mjd
in the Date class. There is also
an Astronomical Modified
Julian Day Number, which
is in UTC and includes fractional days. This is abbreviated as
amjd
in the Date class. Like the
Modified Julian Day Number (and unlike the Astronomical Julian Day Number),
it counts from midnight.
Alternative calendars such as the Chinese Lunar Calendar, the Islamic Calendar, or the French Revolutionary Calendar are not supported by the Date class; nor are calendars that are based on an Era different from the Common Era, such as the Japanese Imperial Calendar or the Republic of China Calendar.
The standard civil year is 365 days long. However, the solar year is fractionally longer than this. To account for this, a leap year is occasionally inserted. This is a year with 366 days, the extra day falling on February 29. In the early days of the civil calendar, every fourth year without exception was a leap year. This way of reckoning leap years is the Julian Calendar.
However, the solar year is marginally shorter than 365 1/4 days, and so the Julian Calendar gradually ran slow over the centuries. To correct this, every 100th year (but not every 400th year) was excluded as a leap year. This way of reckoning leap years, which we use today, is the Gregorian Calendar.
The Gregorian Calendar was introduced at different times in different
regions. The day on which it was introduced for a particular region is the
Day of Calendar
Reform for that region. This is abbreviated as
sg
(for Start of Gregorian calendar) in the Date class.
Two such days are of particular significance. The first is October 15, 1582, which was the Day of Calendar Reform for Italy and most Catholic countries. The second is September 14, 1752, which was the Day of Calendar Reform for England and its colonies (including what is now the United States). These two dates are available as the constants Date::ITALY and Date::ENGLAND, respectively. (By comparison, Germany and Holland, less Catholic than Italy but less stubborn than England, changed over in 1698; Sweden in 1753; Russia not till 1918, after the Revolution; and Greece in 1923. Many Orthodox churches still use the Julian Calendar. A complete list of Days of Calendar Reform can be found at www.polysyllabic.com/GregConv.html.)
Switching from the Julian to the Gregorian calendar involved skipping a number of days to make up for the accumulated lag, and the later the switch was (or is) done, the more days need to be skipped. So in 1582 in Italy, 4th October was followed by 15th October, skipping 10 days; in 1752 in England, 2nd September was followed by 14th September, skipping 11 days; and if I decided to switch from Julian to Gregorian Calendar this midnight, I would go from 27th July 2003 (Julian) today to 10th August 2003 (Gregorian) tomorrow, skipping 13 days. The Date class is aware of this gap, and a supposed date that would fall in the middle of it is regarded as invalid.
The Day of Calendar Reform is relevant to all date representations involving years. It is not relevant to the Julian Day Numbers, except for converting between them and year-based representations.
In the Date and DateTime classes, the Day of Calendar Reform or
sg
can be specified a number of ways. First, it can be as the
Julian Day Number of the Day of Calendar Reform. Second, it can be using
the constants Date::ITALY or Date::ENGLAND; these are in fact the Julian
Day Numbers of the Day of Calendar Reform of the respective regions.
Third, it can be as the constant Date::JULIAN, which means to always use
the Julian Calendar. Finally, it can be as the constant Date::GREGORIAN,
which means to always use the Gregorian Calendar.
Note: in the Julian Calendar, New Years Day was March 25. The Date class does not follow this convention.
DateTime objects support a simple
representation of time zones. Time zones are
represented as an offset from UTC, as a fraction of a day. This offset is
the how much local time is later (or earlier) than UTC. UTC offset 0 is
centred on England (also known as GMT). As you travel east, the offset
increases until you reach the dateline in the middle of the Pacific Ocean;
as you travel west, the offset decreases. This offset is abbreviated as
of
in the Date class.
This simple representation of time zones does not take into account the common practice of Daylight Savings Time or Summer Time.
Most DateTime methods return the date and the time in local time. The two exceptions are ajd() and amjd(), which return the date and time in UTC time, including fractional days.
The Date class does not support time zone offsets, in that there is no way to create a Date object with a time zone. However, methods of the Date class when used by a DateTime instance will use the time zone offset of this instance.
def print_sundays(d1, d2) d1 +=1 while (d1.wday != 0) d1.step(d2, 7) do |date| puts "#{Date::MONTHNAMES[date.mon]} #{date.day}" end end print_sundays(Date::civil(2003, 4, 8), Date::civil(2003, 5, 23))
def secs_to_new_year(now = DateTime::now()) new_year = DateTime.new(now.year + 1, 1, 1) dif = new_year - now hours, mins, secs, ignore_fractions = Date::day_fraction_to_time(dif) return hours * 60 * 60 + mins * 60 + secs end puts secs_to_new_year()