Skip to content

Instantly share code, notes, and snippets.

@gfldex
Created February 26, 2012 16:40
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save gfldex/1917526 to your computer and use it in GitHub Desktop.
Save gfldex/1917526 to your computer and use it in GitHub Desktop.
http://www.haskell.org/ghc/docs/7.4-latest/html/libraries/haskell98-2.0.0.1/Time.html
http://en.wikipedia.org/wiki/Gregorian_calendar
http://en.wikipedia.org/wiki/Leap_year
http://en.wikipedia.org/wiki/Leap_second
http://en.wikipedia.org/wiki/Unix_time
# we have 3 different official international clocks right now:
say now.IAT; # International Atomic Time
say now.GPS; # == IAT - 19s;
say now.UTC; # moving away from IAT by 1s every 18 month on average over a decade, that may or may not change
# lets decide what forum posts to display
my $last-visit = $session.last-visit;
my @post-to-display := @posts.grep: ($last-visit - .posted-at) < 24h;
# h would be a postfix:<h> that converts Int -> Hour
# having something like Calendar::postfix:<m> is handy because a calendaric
# minute can be 59 | 60 | 61 sec.
# The whole leap second thing is a pain in rear, quite fankly. No wonder why
# they are discussing to give up on it. Neither International Atomic Time nor
# GPS time got a leap second (or satelites would fall out of the sky). So
# to convert GPS time (there are embedded systems that fetch time via GPS)
# to UTC requires a lookup in a static table. One can't predict if a year needs
# a leap second further then 6 month ahead. Don't ask what happens if NTP comes
# into play, that depends on implementation. Microsoft seams not to care to care.
# Now lets have a look when and how this can cause tears.
my $tom = Person.new(birth => Date.new('2012-01-29'));
my $birthday_party = $top.birth
+ 365 * 24 * 60 * 60 # one year later
+ 3 * 24 * 60 * 60; # that would be 3 days later with SI minutes
say "Tom's 1th birthday party will be at ", $birthday_party.day-short-name;
# This can either result in "Th" or in "Fr" depending on if January of 2013 got a
# leap second or not.
# One can get around those problems by doing arithmetics with dates by
# decomposing Intervals into minutes, hours and seconds and being really carefull
# what they are added on. Just adding seconds to some more seconds relative to
# some Unix epoch will result in tears because of missed birthday parties.
# But back on track how some nice handling of Temporals (that should not be
# Temporals but Calendarics) could look like.
# we want to go skating!
say "Lets go skating!" if today ~~ all( January | Sunday );
# we have a meeting every monday, so we need any monday that is a workday for this year
# A Year would have a member @days (lazy list) that takes leap years into account
my $current-year = Date.Year(2012);
for $current-year.days ~~ Monday -> $day {
next if Calendaric::holiday($day, :region('Saxony')); # we have different holidays for different countries in Germany because of historic religious preference (don't ask)
say $day.local-time + 9h + 15m, 'is a meeting'; # let's hope the OS is setup properly
}
# One might want to convert Gregorian Dates into Chinese dates because if you
# get the wedding day wrong in China, your willy will fall off in the first
# night and then bad things will happen.
sub today ( --> Day ) { Day.new(now) }
if today ~~ Calendar::Gregorian {
say today.traditinal-chinese;
}
# There are days in the Julian calendar that do not exist in the Gregorian and
# vice versa, so the following could fail
if $user ~~ Historian {
say today, ' would be ' today.julian;
}
# Since there are years with missing days, being able not to care would be nice.
# The best way to do so would be to have a Iterator that knows how to handle those cases.
my $day-of-birth = Date.new('1978-03-01');
for $day-of-birth.years -> $d {
last if $d.year > $day-of-birth.year + 120y;
say "Yay, birthday party is ", $d.weeday-name, ' the ', $d.day-of-month, '!';
}
# Another solution would be a mutable postfix:<++> on the year part
my $d_it = $day-of-birth.clone;
while( $d_it.year++ < (1978+120)y ){ # we will start in 1979 in this case
say "Yay, birthday party is ", $d_it.weeday-name, ' the ', $d_it.day-of-month, '!';
}
# Having Exceptions is handy by handling Dates because one can create invalid
# Dates fairly easy with seamingly sane arithmetics. Thanks to leap seconds and
# years we have to make a difference between counting seconds (for profiling)
# or if we handle Date and Time.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment