Time::Local

18 views
Skip to first unread message

Gaal Yahas

unread,
Jul 5, 2005, 9:39:48 AM7/5/05
to perl6-l...@perl.org, aut...@urth.org
I've added localtime to pugs (r5233, 5236), to address Dave Rolsky's needs
for DateTime; but I'm noticing S29 doesn't spec this and nearby builtins
yet. I'd like to raise the questions I encountered / stipulations I've
made. Please let me know if I'm in error or update S29 if I am not.

Regarding Time::Local fields, it's an object now, so the order of things
matters less now than it did in p5. The fields I've made available
naturally follow GHC's CalendarTime type[1]. The important deviations
from p5 are:

* .year is the Gregorian year, no 1900 offeset or anything like that.

(Haskell doesn't promise accuracy in the readable version of
pre-Gregorian dates, which I think is okay for us as well, as long
as the opaque internal representation remains consistent. That's part
of where libraries such as DateTime can help.)

* .month and .wday are one-based. Sunday == 1. Haskell has them as
enums which avoids off-by one confusion completely; I made them like
I did because that's like humans think of them.

* .picoseconds - we don't promise this granularity is available by the
system, but I don't suppose we'll ever need anything finer than that
:-)

* Once we sort out context and want in pugs, I can return a List when
one is expected, instead of an object. Then the order of fields
becomes important and I'm inclined to go with year first, like the
Haskell module, so that least significant things come last. This is the
reverse of p5 Time::Local. When timelocal and timegm are implemented,
they will of course use whatever order their inverses use.

As for the function signatures:

multi sub localtime(Rat $?when = time) returns Time::Local { ... }
multi sub localtime(Int $sec, Int ?$pico = 0) returns Time::Local {...}

The first form uses the second, but might be less precise.

[1] http://haskell.org/ghc/docs/latest/html/libraries/base/System.Time.html#t%3ACalendarTime

--
Gaal Yahas <ga...@forum2.org>
http://gaal.livejournal.com/

Larry Wall

unread,
Jul 5, 2005, 11:16:54 AM7/5/05
to perl6-l...@perl.org
On Tue, Jul 05, 2005 at 04:39:48PM +0300, Gaal Yahas wrote:
: As for the function signatures:

:
: multi sub localtime(Rat $?when = time) returns Time::Local { ... }
: multi sub localtime(Int $sec, Int ?$pico = 0) returns Time::Local {...}
:
: The first form uses the second, but might be less precise.

I don't think either of those are good human engineering. I would
like the preferred Perl 6 form to simply be:

multi sub localtime(Num $?when = time) returns Time::Local { ... }

The time function always returns the time in floating point. In fact,
all numeric times are Num in Perl 6. Then you don't have to worry
about whether picosecond resolution is good enough. Time and
duration objects can, of course, do whatever they like internally,
and among themselves, but someone who says sleep($PI) should get a
$PI second sleep. Our computers are capable of floating point these
days, and I consider any other numeric time format to be cultural
baggage. I particularly loathe any kind of two integer format.

Sorry about the rant, but you seem to have pushed one of my hot buttons...

Larry

Gaal Yahas

unread,
Jul 5, 2005, 12:28:25 PM7/5/05
to perl6-l...@perl.org
On Tue, Jul 05, 2005 at 08:16:54AM -0700, Larry Wall wrote:
> I don't think either of those are good human engineering. I would
> like the preferred Perl 6 form to simply be:
>
> multi sub localtime(Num $?when = time) returns Time::Local { ... }

Done.

I take it that the rest is okay? If so I'll submit a doc patch to S29.

Gaal Yahas

unread,
Jul 5, 2005, 1:23:44 PM7/5/05
to Dave Rolsky, perl6-l...@perl.org
On Tue, Jul 05, 2005 at 11:41:23AM -0500, Dave Rolsky wrote:
> >Regarding Time::Local fields, it's an object now, so the order of things
>
> Should that be Time::localtime? In P5 there are Time::localtime &
> Time::gmtime, which are thin OO facades over the language builtins. Then
> there's the module Time::Local, which is entirely different.

Hmm, I agree. I used Time::Local because that's what the draft Synopsis
put them in, but Time is a better fit.

> All of those provide useful functionality, and probably Time::Local should
> be part of the language, _or_ localtime & gmtime should be in a library.

Not my call, but I think we can add timelocal and timegm soon. They're
mostly cleverly-caching facades to Time.new anyway, no? Drop by on #perl6
if you want to hack on the Prelude side of this.

Dave Rolsky

unread,
Jul 5, 2005, 12:41:23 PM7/5/05
to Gaal Yahas, perl6-l...@perl.org
On Tue, 5 Jul 2005, Gaal Yahas wrote:

> Regarding Time::Local fields, it's an object now, so the order of things

Should that be Time::localtime? In P5 there are Time::localtime &

Time::gmtime, which are thin OO facades over the language builtins. Then
there's the module Time::Local, which is entirely different.

All of those provide useful functionality, and probably Time::Local should

be part of the language, _or_ localtime & gmtime should be in a library.

> * .year is the Gregorian year, no 1900 offeset or anything like that.

Yes!

> * .month and .wday are one-based. Sunday == 1. Haskell has them as
> enums which avoids off-by one confusion completely; I made them like
> I did because that's like humans think of them.

And yes again!

> * .picoseconds - we don't promise this granularity is available by the
> system, but I don't suppose we'll ever need anything finer than that
> :-)

The more granularity the better, really. DateTime right now supports
nanoseconds, which was a semi-arbitrary choice that seemed granular
enough. Picoseconds is even better. Anyone who needs more probably has
some sort of special hardware providing their data anyway, and will need a
special interface to it (hand waving).

> * Once we sort out context and want in pugs, I can return a List when
> one is expected, instead of an object. Then the order of fields
> becomes important and I'm inclined to go with year first, like the
> Haskell module, so that least significant things come last. This is the
> reverse of p5 Time::Local. When timelocal and timegm are implemented,
> they will of course use whatever order their inverses use.

I'd agree that this makes the most sense.


-dave

/*===================================================
VegGuide.Org www.BookIRead.com
Your guide to all that's veg. My book blog
===================================================*/

Dave Whipp

unread,
Jul 5, 2005, 1:55:14 PM7/5/05
to perl6-l...@perl.org
Larry Wall wrote:

> The time function always returns the time in floating point.

I don't understand why time() should return a numeric value at all.
Surely it should return a DateTime (or Time) object. Using epochs in a
high level language seems like a really bad thing to be doing. If I want
"duration since epoch" then I should subtract the epoch from the time --
resulting in a duration (which may indeed be a floating point value).

my DateTime $epoch is constant = DateTime "2000-01-01 00:00:00";
my Num $seconds_since_epoch = time - $epoch;


> In fact,
> all numeric times are Num in Perl 6. Then you don't have to worry
> about whether picosecond resolution is good enough. Time and
> duration objects can, of course, do whatever they like internally,
> and among themselves, but someone who says sleep($PI) should get a
> $PI second sleep.

For the sleep function, it seems reasonable to accept either a DateTime
or a Duration, which would sleep either until the requested time, or for
the requested duration.

> Sorry about the rant, but you seem to have pushed one of my hot buttons...

Ditto

> Larry

Juerd

unread,
Jul 5, 2005, 2:17:09 PM7/5/05
to Ingo Blechschmidt, perl6-l...@perl.org
Ingo Blechschmidt skribis 2005-07-05 20:08 (+0200):
> FWIW, I agree, but I'd like to propose standard overloadings:
> say ~$time; # "Di 05 Jul 2005 20:01:42 CEST"

Or perhaps not. In fact, rather not. Please let stringification be the
ISO standard, and otherwise certainly sortable: year first, then month,
then mday.

2005-07-05T20:01:42+0200


Juerd
--
http://convolution.nl/maak_juerd_blij.html
http://convolution.nl/make_juerd_happy.html
http://convolution.nl/gajigu_juerd_n.html

Ingo Blechschmidt

unread,
Jul 5, 2005, 2:08:33 PM7/5/05
to perl6-l...@perl.org
Hi,

Dave Whipp wrote:
> Larry Wall wrote:
>> The time function always returns the time in floating point.
>
> I don't understand why time() should return a numeric value at all.
> Surely it should return a DateTime (or Time) object. Using epochs in a
> high level language seems like a really bad thing to be doing. If I
> want "duration since epoch" then I should subtract the epoch from the
> time -- resulting in a duration (which may indeed be a floating point
> value).

FWIW, I agree, but I'd like to propose standard overloadings:
my $time = time; # some kind of Date/Time object


say ~$time; # "Di 05 Jul 2005 20:01:42 CEST"

say +$time; # seconds since the Perl 6 epoch
# (2000-01-01 according to [1])

> For the sleep function, it seems reasonable to accept either a
> DateTime or a Duration,

or a number of seconds,

> which would sleep either until the requested time, or for the
> requested duration.


--Ingo

[1]
http://groups.google.de/group/perl.perl6.internals/msg/a572113dc089481b

--
Linux, the choice of a GNU | Elliptic paraboloids for sale.
generation on a dual AMD |
Athlon! |

Ingo Blechschmidt

unread,
Jul 5, 2005, 2:33:43 PM7/5/05
to perl6-l...@perl.org
Hi,

Juerd wrote:
> Ingo Blechschmidt skribis 2005-07-05 20:08 (+0200):
>> FWIW, I agree, but I'd like to propose standard overloadings:
>> say ~$time; # "Di 05 Jul 2005 20:01:42 CEST"
>
> Or perhaps not. In fact, rather not. Please let stringification be the
> ISO standard, and otherwise certainly sortable: year first, then
> month, then mday.
>
> 2005-07-05T20:01:42+0200

WRT to sorting: The Date/Time/whatever class should overload
&infix:«<=>», so sorting really works -- if you sort those ISO strings,
you'll probably get wrong results, as the timezone diff isn't taken
into account.

I don't have a strong opinion on the default format of the
stringification.

Could/should we use .as for this, to leave the choice to the programmer?

say time.as("%H:%M:%S"); # 20:26:36

Note though that it's inconsistent:
say "hi".as("%H:%M:%S"); # error
say time.as("%H:%M:%S"); # works


--Ingo

--
Linux, the choice of a GNU | "The future is here. It's just not widely
generation on a dual AMD | distributed yet." -- William Gibson
Athlon! |

Juerd

unread,
Jul 5, 2005, 2:22:07 PM7/5/05
to Dave Rolsky, Gaal Yahas, perl6-l...@perl.org
Dave Rolsky skribis 2005-07-05 11:41 (-0500):

> >* .month and .wday are one-based. Sunday == 1. Haskell has them as
> > enums which avoids off-by one confusion completely; I made them like
> > I did because that's like humans think of them.
> And yes again!

No. Humans don't USE numbers for week days! So beginning at 1 makes no
sense, except for humans who like creating lists like (undef, <Sunday
Monday ...>). In fact, I would prefer <Saturday Sunday Monday ...> to
not having any 0 :)

Now, for months, yes it does make lots of sense.

Dave Whipp

unread,
Jul 5, 2005, 4:39:09 PM7/5/05
to perl6-l...@perl.org
Douglas P. McNutt wrote:

> At 10:55 -0700 7/5/05, Dave Whipp wrote:
>
>>I don't understand why time() should return a numeric value at all.
>
> Some of us like to use epoch time, as an integer, to create unique file names which sort "right" in a shell or GUI.
>

You can use "{time - $epoch}" or "{time.as<%d>}" or "{int time}". (That
last one is not "{+time}", because that would be a floating-point value,
not an integer).

Douglas P. McNutt

unread,
Jul 5, 2005, 4:31:19 PM7/5/05
to perl6-l...@perl.org
At 10:55 -0700 7/5/05, Dave Whipp wrote:
>I don't understand why time() should return a numeric value at all.

Some of us like to use epoch time, as an integer, to create unique file names which sort "right" in a shell or GUI.

--

--> From the U S of A, the only socialist country that refuses to admit it. <--

Darren Duncan

unread,
Jul 5, 2005, 6:20:31 PM7/5/05
to perl6-l...@perl.org
All,

In the spirit of forward thinking and adaptability (and
internationalization), I believe a core Time/Date object should be
calendar agnostic and simply store some value that is easily
convertable to any date + time on any calendaring system. I say
forward thinking because this system will be forwards compatible with
calendaring systems that don't yet exist, and backwards compatible
with older calendars we haven't bothered to account for yet.

I believe that at its core said object should simply store a count of
rigorously defined time units relative to a rigorously defined epoch.
What the epoch is and what the time unit is will need to be
officially defined (eg, Jan 1, 2000; counting in fractions of
seconds). The object should not store anything other than this
single numerical value internally (smart caching of conversions
aside).

Save all human-desired representations to something that is computed
on request, such as using a getter method named after the desired
format; and setting would do the reverse. This can work with values
in any calendaring system.

With this system, date calculations and storage are trivially easy,
and Perl's built-in date/time function would simply return that
number or said object. All the complexity is in the getter/setter
methods that are specific to what details a user wants, such as the
day of week or an ISO formatted string. In fact, all of that actual
conversion stuff would be what modules are good for. Perl internally
just has to know about the one number.

-- Darren Duncan

Dave Whipp

unread,
Jul 5, 2005, 6:36:16 PM7/5/05
to perl6-l...@perl.org
Darren Duncan wrote:
> The object
> should not store anything other than this single numerical value
> internally (smart caching of conversions aside).

I think we can all either agree with that, or dont-care it. The internal
implementation is an implementation issue (or library). It doesn't need
to be defined by the language. The one important thing is that that
language shouldn't define semantics that require more than this single
value (e.g. we shouldn't associate the epoch with the object).

Craig DeForest

unread,
Jul 5, 2005, 6:59:48 PM7/5/05
to perl6-l...@perl.org, Darren Duncan

Quoth Darren Duncan on Tuesday 05 July 2005 04:20 pm,
> I believe that at its core [the time/date] object should simply store a
count of
> rigorously defined time units relative to a rigorously defined epoch.
> What the epoch is and what the time unit is will need to be
> officially defined (eg, Jan 1, 2000; counting in fractions of
> seconds). The object should not store anything other than this
> single numerical value internally (smart caching of conversions
> aside).


Agree agree...

Hmmm.... Straight seconds-counting has the flavor of international atomic
time (TAI) to it, which suggests using the TAI (rather than UNIX) epoch.

Using the TAI epoch of 1958-01-01 00:00:00 has several advantages:
- TAI is recognized by international standards-setting bodies (BIPM).
- Perl6 will then shake out the 31-bit time rollover a full 12 years before
the rest of the UNIX-speaking world. :-)
- TAI is sufficiently different from UNIX time to make implementors think
carefully about their time conversion software. This is important because
some UNIX implementations handle leap-seconds and others don't, and this is a
nice chance to get everything Right the first time.
- TAI-to-UT conversion modules can easily ingest leap-second announcements
without further conversion to a different time base (see, e.g.,
ftp://62.161.69.5/pub/tai/publication/leaptab.txt). This is important
because, without proper maintenance of the leap-second table, all of our
perl6 calendar programs will run an hour late a mere 500 years from now.

Dave Whipp

unread,
Jul 5, 2005, 6:48:47 PM7/5/05
to perl6-l...@perl.org
Dave Whipp wrote:

> You can use "{time - $epoch}" or "{time.as<%d>}" or "{int time}". (That
> last one is not "{+time}", because that would be a floating-point value,
> not an integer).

I was thinking: an epoch is just a time, and "int time" is a duration --
the number of seconds since the current epoch. So, the following should
work:

for 1 .. 2 -> {
use epoch time();
sleep 6;
say int time;
}

This should print something close to "6", twice.

But something niggled me: does the value of the RHS of a "use" get
evaluated at run time, or compile time? In perl5, that could definitely
would only execute the C<use> once.

I could see 3 possible behaviors:

1. C<use> sets the epoch for each iteration of the loop, thus calling
time() one per iteration

2. C<use> executes just once, at compile time. Thus seconds iteration
prints approximately "12"

3. C<use> does a compile-time binding of the epoch to the time()
function. So each iteration prints "0".


Which actually happens?

Darren Duncan

unread,
Jul 5, 2005, 6:59:01 PM7/5/05
to perl6-l...@perl.org
Actually, there was a big oversight in my last message. It does not
handle approximate or relative dates, such as when you don't know the
details.

My previous proposal should be restricted specifically to the
situations where you know the date/time to a high precision, to the
second. So my previous proposal would still work for general tasks
where the date/time you are storing in the object is generated by a
clock, such as the computer's clock or a network time server etc, and
is perfectly appropriate for what Perl's built-in "get current
date/time" returns.

I should also clarify that when I say "rigorously defined epoch",
that also specifies a location (such as, "Jan 1, 2000, at Greenwich
(sp?)"). Any mess related to time zones would be accounted for only
during any calendar conversion used for storage or retrieval.

For the other side, where the dates are imprecise, it actually would
be useful to store them internally in calendar specific and human
terms, basically matching whatever the source was. For example, you
would store a date/time like "early May of 1743" this way; if all you
know is that the date was in "early May", then what you're storing is
fully accurate. Shoe-horning this into a specific day etc just for
storage makes the data less accurate because someone reading the
storage value presumes we knew for sure it was that day etc when in
fact we didn't. Another example of an imprecise and relative date is
"in the 4th year of Xerxes reign". If you didn't know when on our
calendar that Xerxes ruled, you can't exactly convert this to a
Gregorian calendar; you must store it in the terms that I mentioned
for highest accuracy.

Now of course, for such imprecise things, the simplest storage method
is to just use a character string. Where it gets more complicated is
if you want to do math or calculations with this imprecise info;
that's one place that date/time such modules would really be useful
and have their work cut for them.

BTW, my main programming project (unreleased) is a
genealogy/history/anything database type application, of an
unprecedented focus and feature set, so I've thought a lot about
these sorts of issues for being the most accurate and trustworthy
possible.

-- Darren Duncan

Craig DeForest

unread,
Jul 5, 2005, 7:03:28 PM7/5/05
to perl6-l...@perl.org, Darren Duncan
Quoth Craig DeForest on Tuesday 05 July 2005 04:59 pm,
> ...This is important

> because, without proper maintenance of the leap-second table, all of our
> perl6 calendar programs will run an hour late a mere 500 years from now.
Uh, sorry -- "...an hour fast a mere 500 years from now."

Darren Duncan

unread,
Jul 5, 2005, 7:04:42 PM7/5/05
to perl6-l...@perl.org

What I'm saying is that the epoch for a high-precision-knowledge date
is effectively hard-coded into Perl as a "standard" and users do not
specify it or override it at any time. If this is accepted, then all
that's left to discuss for these types of dates is what list of
conversion methods there are and accepted input/output formats.
Which perhaps is the point. The main reason implementation would
have a say is if Perl's built-in functions do not return the
Date/Time object, but some scalar information instead like Perl 5.
But I say it should return the object. -- Darren Duncan

Sam Vilain

unread,
Jul 5, 2005, 7:09:50 PM7/5/05
to Darren Duncan, perl6-l...@perl.org
Darren Duncan wrote:
> Actually, there was a big oversight in my last message. It does not
> handle approximate or relative dates, such as when you don't know the
> details.

FWIW, this is handled by DateTime::Incomplete, and also will be natively
supported by Date::Gregorian.

You're describing with this and other messages very much how the `Date'
distribution in pugs is being designed. I'd very much appreciate input
on that interface.

Sam.

Dave Rolsky

unread,
Jul 5, 2005, 4:41:49 PM7/5/05
to perl6-l...@perl.org
On Tue, 5 Jul 2005, Juerd wrote:

> No. Humans don't USE numbers for week days! So beginning at 1 makes no
> sense, except for humans who like creating lists like (undef, <Sunday
> Monday ...>). In fact, I would prefer <Saturday Sunday Monday ...> to
> not having any 0 :)

This should be separated into day() and day_name(). It's hardly obvious
that day() should return a string, much less a bit of English!

As for 0 vs 1 as the index, I think this is a bit of a red herring. If
you're constantly using this as an array index you're operating at too low
a level (IMO). If all your programs start with:

my @DayNames = qw( Sunday Monday Tuesday ... );

I think you have a bigger problem than simply adjusting for a 1-indexed
day number ;)

Juerd

unread,
Jul 5, 2005, 7:42:28 PM7/5/05
to Dave Rolsky, perl6-l...@perl.org
Dave Rolsky skribis 2005-07-05 15:41 (-0500):

> As for 0 vs 1 as the index, I think this is a bit of a red herring. If
> you're constantly using this as an array index you're operating at too low
> a level (IMO). If all your programs start with:
> my @DayNames = qw( Sunday Monday Tuesday ... );
> I think you have a bigger problem than simply adjusting for a 1-indexed
> day number ;)

I think the problem one has is much bigger even if a day *number* is
ever displayed. Then beginning with 1 because that's where most humans
begin counting, is wrong. It's a technical thing, and that should be
kept as simple as possible, and as technical as possible, for easier
compatibility with existing technical things.

Calling Sunday 1 and not having a 0 would certainly upset and offend me.

My weeks begin on Mondays, as do most people's weeks here. At the same
time, I can accept any day as the first day if that first day is 0,
because 0 is technical and internal anyway, not meant for humans.

I'm sure lots of people would want an index 1 to be Sunday, if there is
no index 0. This all is solved simply by NOT skipping 0, and using an
arbitrarily chosen day for the first. Or, well, for compatibility,
Sunday :)

Computers and Perl count from 0. People count from 1. If something
begins at 1, it is expected to be a people's thing. And with week days,
this just doesn't work, as not everyone's week starts at the same day.

Sam Vilain

unread,
Jul 5, 2005, 8:18:37 PM7/5/05
to Craig DeForest, perl6-l...@perl.org, Darren Duncan
Craig DeForest wrote:
> Using the TAI epoch of 1958-01-01 00:00:00 has several advantages:
> - TAI is recognized by international standards-setting bodies (BIPM).
> - Perl6 will then shake out the 31-bit time rollover a full 12 years before

I like this in principle, however I wonder of the merits of professing to
return something of more accuracy than can actually ever be realistically
assured from any of the platforms Perl runs.

For a start, to convert from the available time source - the system clock
- to TAI, you need to know;

a) current adjustments, or when the lack of adjustments is considered
valid up to (after that date, of course, if the list of adjustments
is not updated, getting the time or converting from a time to a date
on a calendar is an exception).

b) whether or not the system clock is automatically correcting for
leap seconds, ie when ntpd is running and sync'ed up.

In any case, I'll add "to_TAI" as one of the marshalling methods for
Date objects in Date.pm

I guess it comes down to what guarantees we decide to make on the nature
of time(). If a leap second passes while the script is running, can the
value returned by time() regress?

In fact, do we even need a fixed epoch? Why not just free-wheel it and
make 0 the time the script started, get it to count seconds, and let
interfaces for the system clock / orson database solve the hard problems.

Sam.

Zowie

unread,
Jul 5, 2005, 8:47:41 PM7/5/05
to Sam Vilain, perl6-l...@perl.org, Darren Duncan

On Jul 5, 2005, at 6:18 PM, Sam Vilain wrote:

> Craig DeForest wrote:
>
>> Using the TAI epoch of 1958-01-01 00:00:00 has several advantages:
>> - TAI is recognized by international standards-setting bodies
>> (BIPM).
>> - Perl6 will then shake out the 31-bit time rollover a full 12

>> years before ...


>>
> I like this in principle, however I wonder of the merits of
> professing to
> return something of more accuracy than can actually ever be
> realistically
> assured from any of the platforms Perl runs.
>

Hmmm.... Actually, ntpd achieves that sort of accuracy -- but if I
understand
correctly it anchors the UTC time to the standard, and allows the UNIX
seconds count (which often does not account for new leap seconds, though
some gmtime versions account for old ones) to drift or jump whenever
a leap
second goes by. The problem is then that interval calculations that
include the
leap second are off by one second. That probably doesn't bother most
people
but is an endless cause of hassle in scientific applications.

There is also a certain joy that comes from noticing that a tool was
designed by pedants:
it's great that cal(1) handles the Gregorian reformation correctly
(or at least, in one
of several arguably correct ways) even though most of us don't deal
with dates in 1752.

So, er, I guess I'm arguing that time/date stamps, if kept in numeric
counting-ticks form,
should follow TAI in some easily definable way, which probably means
keeping track
of leap seconds in a table that can be updated easily. Even if the
only interface most
people use is through UTC or civil time via the equivalent of gmtime
(), IWBNI the
underlying engines knew enough to work well for those people who do
care about
representing time at such high precision that leap seconds matter.
If the code is
implemented with enough care to do that right, then the natural epoch
to use is probably
1958, though as you pointed out the epoch itself is much less
important than the decision
about what kind of time to track.

Cheers,
Craig

Larry Wall

unread,
Jul 5, 2005, 9:48:46 PM7/5/05
to perl6-l...@perl.org
On Tue, Jul 05, 2005 at 06:47:41PM -0600, zowie wrote:

: Hmmm.... Actually, ntpd achieves that sort of accuracy -- but if


: I understand correctly it anchors the UTC time to the standard,
: and allows the UNIX seconds count (which often does not account for
: new leap seconds, though some gmtime versions account for old ones)
: to drift or jump whenever a leap second goes by. The problem is
: then that interval calculations that include the leap second are off
: by one second. That probably doesn't bother most people but is an
: endless cause of hassle in scientific applications.

I think it would be wonderful to anchor our internal time to atomic
time, even if our epoch isn't 1958. It's more important for our
seconds to stay accurate than our timestamps, and we can make the
approximate interfaces do the right thing if they know they're
supposed to be approximate. The only problem is that we don't
actually have atomic time available to most of our computers right now.
Eventually we will, and I think it would be wonderful if were ready
for that transition when it happens. Maybe even to the extent of
pretending to be TAI-based by default even if we're not yet. We'll
be wrong part of the time regardless of which way we pick.

<rant>
But I really, really wish UTC hadn't decided to add a leap second
this year. It really wouldn't have hurt many folks to let midnight
drift a few seconds and then do a major seconds correction at the
end of the century, say. And it would have solved a lot of other
problems. Oh well...
</rant>

: So, er, I guess I'm arguing that time/date stamps, if kept in numeric


: counting-ticks form, should follow TAI in some easily definable way,
: which probably means keeping track of leap seconds in a table that
: can be updated easily. Even if the only interface most people use
: is through UTC or civil time via the equivalent of gmtime (), IWBNI
: the underlying engines knew enough to work well for those people
: who do care about representing time at such high precision that leap
: seconds matter. If the code is implemented with enough care to do
: that right, then the natural epoch to use is probably 1958, though
: as you pointed out the epoch itself is much less important than the
: decision about what kind of time to track.

I agree. time(2000) - time(1958) should just be a TAI constant.
(Actually, it's a constant in UTC as well--it's just the POSIXly
view of time that must die eventually. Slewing the clock for
leap seconds is Just Wrong, and someday we'll fix it. Let's design
with the assumption it will be fixed someday.)

Larry

Larry Wall

unread,
Jul 5, 2005, 10:16:25 PM7/5/05
to perl6-l...@perl.org
On Tue, Jul 05, 2005 at 03:48:47PM -0700, Dave Whipp wrote:
: Dave Whipp wrote:
:
: >You can use "{time - $epoch}" or "{time.as<%d>}" or "{int time}". (That
: >last one is not "{+time}", because that would be a floating-point value,
: >not an integer).

Or {time.int}, presumably.

: I was thinking: an epoch is just a time, and "int time" is a duration --

: the number of seconds since the current epoch. So, the following should
: work:
:
: for 1 .. 2 -> {
: use epoch time();
: sleep 6;
: say int time;
: }
:
: This should print something close to "6", twice.
:
: But something niggled me: does the value of the RHS of a "use" get
: evaluated at run time, or compile time? In perl5, that could definitely
: would only execute the C<use> once.

I would not necessarily assume that "use" is the best interface for
setting what is essentially a lexically scoped variable.

: I could see 3 possible behaviors:


:
: 1. C<use> sets the epoch for each iteration of the loop, thus calling
: time() one per iteration

The pragma could arrange to install something in the runtime code
at that point, but it would take extraordinary measures and be
completely unexpected.

: 2. C<use> executes just once, at compile time. Thus seconds iteration
: prints approximately "12"

Or much more than that, given separate compilation.

: 3. C<use> does a compile-time binding of the epoch to the time()

: function. So each iteration prints "0".

: Which actually happens?

Am I allowed to vote for none of the above? :-)

Actually what should happen is most like 2, I suspect.

Coming at it from a different angle, I'm thinking we should try to
get rid of built-in none-ary functions like time anyway, and parse them
to expect an argument, on the assumption that this will simplify
MMD. (In fact, that's a good reason to get rid of the entire
"named unary" precedence level and treat them all as list operators
for parsing purposes.) So if we're allowing an optional argument
to time(), then it makes sense to allow time($epoch), where time
can default to a particular epoch, or even to the epoch defined in
the caller's lexical scope. I'd like time(2000) to be the standard
default, but time(1958) shouldn't be too hard to arrange.

We could set that default pragmatically, but pragmatically speaking,
we should just set the epoch as a lexical variable that is visible
to the default value for the parameter. Then the caller can
even do something like:

temp $_epoch_ = 1970;

$x = time(); # sub time (?$epoch = $CALLER::_epoch_)

I'm not suggesting that's the proper name for the lexical variable.
In fact, we haven't got any convention for forced-lexicals in Perl
6 yet, other than, $_ and $/ are two examples of them, and $?FOO is
a compile-time lexical, and $=FOO is file-scoped in some fashion.
At one point I was thinking $*FOO would let the variable itself
decide if it was lexical or global, on the assumption that $_ is just
short for $*_. But maybe that's a Bad Idea. How do we decide which
variables are forced lexicals? More specifically, how to we request
the compiler to force other variables to be lexical, and poke them
into our lexical pads automatically for us? I think the epoch is
one of those, however we spell it. Then different modules can run
with different epochs, as long as all absolute times are passed
as objects.

Larry

Dave Rolsky

unread,
Jul 6, 2005, 12:52:09 PM7/6/05
to perl6-l...@perl.org
On Wed, 6 Jul 2005, Juerd wrote:

> I think the problem one has is much bigger even if a day *number* is
> ever displayed. Then beginning with 1 because that's where most humans
> begin counting, is wrong. It's a technical thing, and that should be
> kept as simple as possible, and as technical as possible, for easier
> compatibility with existing technical things.
>
> Calling Sunday 1 and not having a 0 would certainly upset and offend me.
>
> My weeks begin on Mondays, as do most people's weeks here. At the same
> time, I can accept any day as the first day if that first day is 0,
> because 0 is technical and internal anyway, not meant for humans.
>
> I'm sure lots of people would want an index 1 to be Sunday, if there is
> no index 0. This all is solved simply by NOT skipping 0, and using an
> arbitrarily chosen day for the first. Or, well, for compatibility,
> Sunday :)
>
> Computers and Perl count from 0. People count from 1. If something
> begins at 1, it is expected to be a people's thing. And with week days,
> this just doesn't work, as not everyone's week starts at the same day.

On reflection, I realized it doesn't matter too much to me. In the end,
I'm likely to need a higher-level interface than this to do something
interesting (like print a day _name_ or calculate the second Sunday of the
month) and that interface will just use the information Perl's builtins
give it.

Nicholas Clark

unread,
Aug 15, 2005, 10:07:29 AM8/15/05
to zowie, Sam Vilain, perl6-l...@perl.org, Darren Duncan
On Tue, Jul 05, 2005 at 06:47:41PM -0600, zowie wrote:

> There is also a certain joy that comes from noticing that a tool was
> designed by pedants:
> it's great that cal(1) handles the Gregorian reformation correctly
> (or at least, in one
> of several arguably correct ways) even though most of us don't deal
> with dates in 1752.

I disagree:


$ LC_ALL=es_ES cal 9 1752
septiembre de 1752
do lu ma mi ju vi sá
1 2 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30


Spain adopted the Gregorian Calendar in 1582. Surely setting my locale to
Spain should make the Julian/Gregorian jump show up in 1582, not 1752?


I think that this demonstrates how tricky all this mess is.

Nicholas Clark

Mark Reed

unread,
Aug 15, 2005, 10:44:19 AM8/15/05
to perl6-l...@perl.org
On 2005-08-15 10:07, "Nicholas Clark" <ni...@ccl4.org> wrote:
> Spain adopted the Gregorian Calendar in 1582. Surely setting my locale to
> Spain should make the Julian/Gregorian jump show up in 1582, not 1752?

Arguably so, but I don't think there's anywhere in the POSIX localization
data structures to store that information. There's a huge variety of
adoption dates, from Oct 5/15, 1582 (Most Catholic countries of Western
Europe) to March 10/23, 1924 (Greek civil usage).

Plus, even within its limited US/historical UK application, the cal(1)
program is still (admittedly so on its own man page) inaccurate for dates
prior to 1751, because it uses January 1 as the first day of the year.
While that was true in the original design of the calendar as instituted by
Caesar in 45 BC, and has been true in England and her colonies since 1751,
at some point way back when England had started counting the year change on
March 25. That was a gradual change with no clear transition date, so
matching historical practice exactly is pretty much impossible for a large
chunk of Isle history.

Mark A. Biggar

unread,
Aug 15, 2005, 1:07:57 PM8/15/05
to perl6-l...@perl.org

The actual situation is even worse. You can even use Gregorian dates
for all of 20th history as Russia didn't convert from Julian until 1920.

There is not much you can do to simply store historical dates on a computer:

1) keap all dates Gregoian even those before 1582 when the Gregorian
calendar was first used by Catholic Europe. This was right in the
middle of King Henry VIII's disagreement with the Catholic church so
England didn't convert until 1752 (the cal refernce above). Given that
Englands colonies converted at the same time this explains the confusion
over the Washington's birthday holiday where some states used Feb 11
(Julian Calendar) and some used Feb 22 (Gregorian calendar), as Feb 12
is Lincon's Birthday, for the national version of the holiday it was
decided to just call some Monday in Feb President's Day and do it all
the same day. Also, do you use a year 0 or not, which is an interesting
problem?

2) keep all dates as the people at that place and time in history would
have recorded them, but that is hard as you loose comparability and lots
of recorded historic date are Reign dated or things like N years sence
the founding of Rome, etc.

3) use Astronomical Dates which are kept as the number of days sense
noon Jan-1-4713 BC.

4) keep soe dates Julian Calandar and some Gregorian, but which switch
over do you use.

--
ma...@biggar.org
mark.a...@comcast.net

Mark Reed

unread,
Aug 15, 2005, 1:31:22 PM8/15/05
to perl6-l...@perl.org
On 2005-08-15 13:07, "Mark A. Biggar" <ma...@floorboard.com> wrote:
> 3) use Astronomical Dates which are kept as the number of days sense
> noon Jan-1-4713 BC.

More specifically, that's the astronomical Julian Day, or JD, and JD 0 began
at noon Universal Time (a.k.a. GMT) on January 1, 4713 BC in the Julian
calendar. Sometimes this is called the Julian Astronomical Day, or JAD, to
distinguish it from various other misappropriations of the term "julian
day/date".

More generally, astronomers use the Gregorian calendar like the rest of us,
but often extend it into the past before its adoption, ignoring the Julian
calendar switchover. They also tend to use 0 and negative years AD/CE in
lieu of BC(E) numbering. On that basis, JD 0 began at noon on Nov 24,
-4713.

Julian Days make a good neutral format for storing dates (and, with
fractional components, times), but they are a bit cumbersome. If you don't
actually need the range they provide (because you're only dealing with
dates near the present), it might be regarded as overkill to store the
current time as e.g. 2453598.225995. In order to get 1-second resolution,
the JD requires the same number of significant figures that's required to
get millisecond resolution with time_t.

Doug McNutt

unread,
Aug 15, 2005, 3:04:58 PM8/15/05
to perl6-l...@perl.org
At 13:31 -0400 8/15/05, Mark Reed wrote:
>More specifically, that's the astronomical Julian Day, or JD, and JD 0 began
>at noon Universal Time (a.k.a. GMT) on January 1, 4713 BC in the Julian
>calendar. Sometimes this is called the Julian Astronomical Day, or JAD, to
>distinguish it from various other misappropriations of the term "julian
>day/date".

If anyone gets serious about Julian dates there is also the Modified Julian Date, MJD, used by the US military and others. It differs from the JAD above by a large well-defined integer plus 1/2. The result is a day that begins at midnight and starts at a more recent date that I don't remember. It's not Jan 0, 1970 though.

There is also ephemeris time which is the absolute clock that makes Newtonian mechanics come out correctly regardless of changes in the rotational speed of planet Earth. Don't even think about supporting that.

--

--> Halloween == Oct 31 == Dec 25 == Christmas <--

Larry Wall

unread,
Aug 15, 2005, 1:56:59 PM8/15/05
to perl6-l...@perl.org
Perl 6 will natively think of dates as number of floating point TAI
seconds from the year 2000. You can build any kind of date interface
on top of that, but we're going for simplicity and predictability.

If UTC goes ahead with with additional leap seconds, we will NOT use
Posix stretchy seconds to represent them. I'm personally rooting
for everyone to abandon leap seconds for civil time. Civil leap
adjustments really ought to be scheduled more than six months in
advance. Once a century would be about right.

But POSIX stretchy seconds must die.

Larry

Mark Reed

unread,
Aug 15, 2005, 4:19:45 PM8/15/05
to perl6-l...@perl.org
On 2005-08-15 13:56, "Larry Wall" <la...@wall.org> wrote:
> I'm personally rooting for everyone to abandon leap seconds for civil time.

While you're at it, why not wish for DST to go away (or to become permanent
year-round, whichever)? Heck, toss in world peace, too. :)

> But POSIX stretchy seconds must die.

So Say We All.

Mark Reed

unread,
Aug 15, 2005, 4:08:25 PM8/15/05
to Doug McNutt, perl6-l...@perl.org

On 2005-08-15 15:04, "Doug McNutt" <doug...@macnauchtan.com> wrote:

> At 13:31 -0400 8/15/05, Mark Reed wrote:
> If anyone gets serious about Julian dates there is also the Modified Julian
> Date, MJD, used by the US military and others. It differs from the JAD above
> by a large well-defined integer plus 1/2.

The (then) most recent even multiple of 100,000 was chosen for it: MJD 0 =
JD 2,400,000.5.

> The result is a day that begins at
> midnight and starts at a more recent date that I don't remember. It's not Jan
> 0, 1970 though.

November 17, 1858. Which, while not Jan 1, 1970, is still time zero for
another operating system some of you may have heard of: VMS.

There's also something called the Truncated Julian Day/Date, or TJD, which
NASA used to use: it was essentially the last four digits of the MJD, so
that TJD 0 was MJD 40000, aka May 24, 1968. But once MJD 50000 rolled
around (on Oct 10, 1995), the TJD became ambiguous. Besides, while saving a
decimal digit of storage per log entry was significant when NASA was trying
to get computers light enough to launch in the 1960s, it's not exactly an
earth-shattering storage win today. So the TJD is best avoided. In fact,
forget I mentioned it. :)


Mark Reed

unread,
Aug 15, 2005, 4:41:03 PM8/15/05