Archive:
Subtopics:
Comments disabled |
Wed, 22 Jun 2016
The Greek clock
Some years ago I suggested, as part of the Perl Quiz of the Week, that people write a greektime program that printed out the time according to a clock that divided the hours in this way. You can, of course, spend a lot of time and effort downloading and installing CPAN astronomical modules to calculate the time of sunrise and sunset, and reading manuals and doing a whole lot of stuff. But if you are content with approximate times, you can use some delightful shortcuts. First, let's establish what the problem is. We're going to take the conventional time labels ("12:35" and so forth) and adjust them so that half of them take up the time from sunrise to sunset and the other half go from sunset to sunrise. Some will be stretched, and some squeezed. 01:00 in this new system will no longer mean "3600 seconds after midnight", but rather "exactly 7/12 of the way between sunset and sunrise". To do this, we'll introduce a new daily calendar with the following labels:
We'll assume that noon (when the sun is directly overhead) occurs at 12:00 and that midnight occurs at 00:00. (Or 24:00, which is the same thing.) This is pretty close to the truth anyway, although it is screwed up by such oddities as time zones and the like. On the equinoxes, the sun rises around 06:00 and sets around 18:00, again ignoring time zones and the like. (If you live at the edge of a time zone, especially a large one like U.S. Central Time, local civil noon does not occur at solar noon, so these calculations require adjustments.) On the equinoxes the normal calendar corresponds to the Greek one, because the day and the night are each exactly twelve standard hours long. (The day from 06:00 to 18:00, and the night from 18:00 to 06:00 the following day.) In the winter, the sun rises later and sets earlier; in the summer it rises earlier and sets later. So let's take 06:00 to be the label for the time of sunrise in the Greek clock all year round; 18:00 is similarly the time of sunset in the Greek clock all year round. With these conventions, it turns out that it's rather easy to calculate the approximate time of sunrise for any day of the year. You need two magic numbers, A and d. The number d is the number of days that have elapsed since the vernal equinox, which is around 19 March (or 19 September, if you live in the southern hemisphere.) The number A is a bit trickier, and I will return to it shortly. Once you have the two numbers, you just plug into the formula:
$$\text{Sunrise} = \text{06:00} - A \sin {2\pi d\over 365.2422}$$ The tricky part is the magic number A; it depends on your latitude. At the equator, it is 0. And you can probably calculate it directly from the latitude, if you happen to know your latitude. I do know my latitude (Philadelphia is conveniently located at almost exactly 40° N) but I failed observational astronomy classes twice, so I don't know how to do the necessary calculation.(Actually it occurs to me now that !!A = 360 \text{ min}\times (1-\cos L)!!, should work, where L is the absolute latitude. For the equator (!!L = 90^\circ!!), this gives 0, as it should, and for Philadelphia it gives !!360\text{ min}\cdot (1- \cos 40^\circ) \approx 84.22\text{ min}!!, which is just about right.) However, there's another trick you can use even if you don't know your latitude. If you know the time of sunset on the summer solstice, you can calculate A quite easily:
$$A = {\text{ Sunset on summer solstice}} - \text{18:00}$$ Does that really help? If it were October, it might not. But the summer solstice is today. So all you have to do is to look out the window in the evening and notice when the sun seems to be going down. Then plug the time into the formula. (Or you can remember what happened yesterday, or wait until tomorrow; the time of sunset hardly changes at all this time of year, by only a few seconds per day. Or you could look at the front page of a daily newspaper, which will also tell you the time of sunset.)The sun went down here around 20:30 today, but that is really 19:30 because of daylight saving time, so we get A = 19:30 - 18:00 = 90 minutes, which happily agrees with the 84.22 we got earlier by a different method. Then the time of sunrise in Philadelphia d days after the vernal equinox is $$\text{Sunrise} = \text{06:00} - 90\text{ min}\cdot \sin {2\pi d\over 365.2422}$$ Today is June 21, which is (counts on fingers) about 31+30+31 = 92 days after the vernal equinox which was around March 21. So notice that the formula above involves !!\sin{2\pi\cdot 92\over 365.2422} \approx \sin{\frac\pi 2} = 1!! because 92 is just about one-fourth of 365.2422—that is, today is just about a quarter of a year after the vernal equinox. So the formula says that sunrise ought to be about 04:30, or, because of daylight saving time, that's 05:30 local civil time. This time of year the night is only 9 standard hours long, so the Greek nighttime hour is !!\frac9{12}!! standard hours long, or 45 minutes. Right now it's 22:43 daylight time, which is 133 standard minutes past sundown, or just about 3 Greek nighttime hours. So the Greek time is close to 9 PM. In another 2:15 standard hours another 3 Greek hours will have elapsed and it will be Greek midnight; this coincides with standard midnight, which is 01:00 local civil time because of daylight saving. Here's code for greektime that you can run where you to find out the current Greek time. I hereby place this program in the public domain. #!/usr/bin/perl # # Calculate local time in fictitious Greek clock # http://blog.plover.com/calendar/Greek-clock.html # Author: Mark Jason Dominus (mjd@plover.com) # This program is in the public domain. # my $PI = atan2(0, -1); use Getopt::Std; my %opt; getopts('l:s:', \%opt) or usage(); my $A; if ($opt{l} =~ /\d/) { $A = 360 * 60 * (1-cos(radians($opt{l}))); } elsif ($opt{s} =~ /:/) { my ($hr, $mn) = split /:/, $opt{s}; $A = (($hr - 18) * 60 + $mn) * 60; } else { usage(); } my $time = time; my $days_since_equinox = ($time - 1047950185)/86400; my $days_per_year = 365.2422; my $sunrise_adj = $A * sin($days_since_equinox / $days_per_year * 2 * $PI ); my $length_of_daytime = 12 * 3600 + 2 * $sunrise_adj; my $length_of_nighttime = 12 * 3600 - 2 * $sunrise_adj; my $time_of_sunrise = 6 * 3600 - $sunrise_adj; my $time_of_sunset = 18 * 3600 + $sunrise_adj; my ($gh, $gm) = time_to_greek($time); my ($h, $m) = (localtime($time))[2,1]; printf "Standard: %2d:%02d\n", $h, $m; printf " Greek: %2d:%02d\n", $gh, $gm; sub time_to_greek { my ($epoch_time) = shift; my $time_of_day; { my ($h, $m, $s, $dst) = (localtime($epoch_time))[2,1,0,8]; $time_of_day = ($h-$dst) * 3600 + $m * 60 + $s; } my ($greek, $hour, $min); if ($time_of_day < $time_of_sunrise) { # change early morning into night $time_of_day += 24 * 3600; } if ($time_of_day < $time_of_sunset) { # day my $diff = $time_of_day - $time_of_sunrise; $greek = 6 + ($diff / $length_of_daytime) * 12; } else { # night my $diff = $time_of_day - $time_of_sunset; $greek = 18 + ($diff / $length_of_nighttime) * 12; } $hour = int($greek); $min = int(60 * ($greek - $hour)); ($hour, $min); } sub radians { my ($deg) = @_; return $deg * 2 * $PI / 360; } sub usage { print STDERR "Usage: greektime [ -l latitude ] [ -s summer_solstice_sunset ] One of latitude or sunset time must be given. Latitude should be in degrees north of the equator. (Negative for southern hemisphere) Sunset time should be given in the form '19:37' in local STANDARD time. (Southern hemisphere should use the WINTER solstice.) "; exit 2; }This article has been in the works since January of 2007, but I missed the deadline on 18 consecutive solstices. The 19th time is the charm! [ Addendum 20160711: Sean Santos has some corrections to my formula for A. ] [Other articles in category /calendar] permanent link |