low-level date modules
I've written a couple of Perl modules that do low-level date stuff, way below the high-level DateTime concept. I'd appreciate a review of my modules by the date experts on this list. The modules are Date::JD, which does conversions between several flavours of Julian Date, and Date::ISO8601, which implements the ISO 8601 calendrs in terms of Chronological Julian Day Numbers. They can be found at <http://search.cpan.org/~zefram/>. Thanks. -zefram
Re: low-level date modules
Joshua Hoblitt wrote: >Is all that stuff just a reinvention of the wheel? Yes, but this time it's round. >What's the value add >over DateTime and the zillions of other date/time modules already on CPAN? Three things: API isolation; arithmetic-friendly (and calendar-neutral) interface; unlimited range. The Date::ISO8601 module implements those calendars *in isolation*. It's suitable to plug into anything that wants to use those calendars as part of something else. Modules such as DateTime implement these calendars, but that implementation comes along with mandatory processing of time of day and timezone. DateTime offers no object that represents merely an abstract date. Secondly, most calendar-handling modules offer functions that, for example, take a (year, month, day) tuple and a number of days and return a (year, month, day) tuple that identifies the date so many days later. This way of doing date arithmetic is the wrong way round. Date::ISO8601 treats the (year, month, day) tuple as merely a surface encoding of the date, which is what it is, and not as the natural form of the underlying data. Using CJDN, a linear count of days, as the basic format for representing dates lets the user do the arithmetic directly. It also avoids forcing the user to deal with one calendar and its (year, month, day) tuples when ey might only be interested in a different calendar, such as the (year, week, day) calendar from ISO 8601. Finally, my modules allow use of bignums, avoiding range limitations. Several date-handling modules on CPAN actually impose arbitrary limits on the dates they will handle. The ones that don't, apart from mine, break when the dates overflow the native integer format. Additionally, for Date::JD I've never seen a CPAN module with that functionality at all. >I have to admit I haven't really looked at your code in depth but I >don't see how you can accurately be calculating TT/etc. without doing an >interpolation of IERS data. Er, you can't be talking about Date::ISO8601 and Date::JD here. I guess you're talking about my Time::TT and Time::TAI? These do indeed convert between different realisations of TT by interpolating BIPM data. Quite a different subject area from what (it seems) this mailing list is concerned with, but a good example of why one might want to use more than one model of time-of-day with a calendar module. -zefram
Re: low-level date modules
Joshua Hoblitt wrote: >Oops - I made a typo. Replace TT with UT1. I haven't written any code that tackles UT1 yet. My interests lie firmly in atomic (and platonic) timekeeping. Watching a planet rotate is too much like getting my hands dirty. Though I did write Time::UTC, because I wanted to handle civil time and there was nothing on CPAN that handled leap seconds correctly. By the way, thanks everyone for writing DateTime::TimeZone. I'm glad I didn't have to write *that* one myself. (I fucking hate timezones, but I do want my desktop clock program to display regional civil time rather than unadulterated UTC.) -zefram
Re: low-level date modules
Eugene van der Pijll wrote: >is any instance where DateTime gets it wrong, please let us know. There's leap seconds, but I presume that's intentional. AFAIK DateTime operates correctly within its designed limits. >priorities of DT have always been 1) correctness 2) ease of use 3) >efficiency, in that order. I think. That's refreshing to hear. I have the same priority list. >Last weekend I finally did something about it. I've created a new >version of DateTime, where I have split the module in DT::Date and >DT::Time. Cool. I think there's a lot of abstraction inversion in DateTime, and this sort of rearrangement is the right direction to rectify that. It would be nice to mix and match date and time-of-day models. >I think DateTime::Format::Epoch contains most of the functionality of >your Date::JD. I think there'll be resolution issues, and possibly time-of-day model problems. The biggest problem is the timezone stuff, though. And, as I said, DateTime has no concept matching what a CJDN (or a JDN) represents. >Those modules are certainly on-topic on this mailing list, Ah, I was mistaken then. I'd be interested in suggestions people can make about those too. I've tried to make them all interoperate nicely. -zefram
Re: low-level date modules
Joshua Hoblitt wrote: >Entirely accidental, I assure you! Oh dear. There are two fundamental problems with DateTime's handling of leap seconds: one pertaining to the future, and one pertaining to the past. For future times, DateTime implicitly assumes that there will never be another leap second. This assumption is incorrect. It is fundamental to the definition of UTC that more leap seconds will be announced from time to time. It is impossible to have a complete list of leap seconds. DateTime's assumption that its leap second list is complete is so fundamentally incorrect that I took it to be a deliberate design decision. Unknown leap seconds are quite a complication in dealing with future dates: ignoring them is a possible way to cope, but not one that I recommend. For past times, DateTime has a time-of-day model where the same time scale which contains leap seconds extends infinitely far backwards with no leaps before 1972. UTC actually had leaps (but not of whole seconds), and a variable rate, prior to 1972, going back to 1961. Prior to 1961 there is no UTC. An accurate representation of UTC can't do anything with times earlier than 1961, or 1972 if its scope is limited to the leap second version. So it's not clear what time scale you intend to use prior to 1972. Once again I took it to be a design decision to fudge the issue and invent a time scale of convenience. >But you know this as you've had to implement leapseconds in >Time::UTC too. Yes. I grok UTC. I'm also on the mailing list discussing the future of leap seconds, btw. Debate has raged there for several years with no conclusion in sight. Recently there's been some ontological discussion that might form a basis on which to frame the debate properly. I think we'll need some similar work on ontology here if DateTime is to have a more sophisticated concept of time-of-day. >Uh, what about the ->jd() & ->mjd() DateTime.pm methods? Mmm. There's a trivial issue that they're subject to floating point rounding which limits the resolution to about 80 us. And a not-quite-so-trivial issue that the structure of the floating point operations is liable to introduce errors from multiple rounding. The biggie, though, is the handling of leap seconds. JDs don't really work properly with UTC, of course, so having a ->jd method without further explanation, when you have a UTCish time-of-day model, seems unwise. There is no tradition (AFAIK) of calculating the fractional JD the way you do, with the JD incrementing at a different rate for the whole leap-second-containing day. The official formulae that use JD (usually MJD actually) with UTC have it increase always at the standard rate of 1/86400 per second. In that model it undergoes a discontinuity at the end of a leap, decrementing by 1/86400 at the end of a positive leap second. A bit like what the POSIX time_t is specified to do (not what it usually does in practice). See <http://maia.usno.navy.mil/ser7/tai-utc.dat> which uses this model of MJD. The other way to derive a JD from UTC is to use UTC-SLS <http://www.cl.cam.ac.uk/~mgk25/time/utc-sls/>, which changes rate for the last 1000 s of a UTC day. I wrote a module which implements this. -zefram
Re: low-level date modules
Eugene van der Pijll wrote: > It's enough for my needs anyway. Dangerous words. There certainly are users that need greater precision. I recommend Math::BigRat, which you'll have noticed I'm quite a fan of. Bignums mean never having to think how big your floats are. >I don't understand why you say DT does not know about CJDNs. Did you notice that JD refers to Universal Time but CJD is timezone-relative? That's one of the things that Date::JD makes work right. In DateTime this issue gets into the floating timezone, which looks like a right can of worms. I think the floating timezone is trying to make DateTime do too many things in one class. It's schizophrenic. >DT is built around the very similar concept of RDN, rata die. I'm familiar with RD. I found the book too muddled for my liking. Interesting stuff if one can think past the details, though. But the interface to the DateTime class seems to be more concerned with the Gregorian calendar than RD. I don't see a way to construct a DateTime from RD there, just the Gregorian (year, month, day) tuple. Looks like another abstraction inversion to me: what's a specific calendar doing in such a fundamental class? >of DT::Calendars is always done by transforming to RD's and back, How do you convert between two non-Gregorian calendars using DateTime? It looks to me like the way the calendar modules subclass DateTime mean that you can only deal with one non-Gregorian calendar at once. Am I misunderstanding it? > my hobby is genealogy, and I'm already happy if I >get the year right. ;-) Heh. That's tricky enough, for the Middle Ages, with so many competing dates to start the year. -zefram
Re: low-level date modules
Eugene van der Pijll wrote: >For every future leap second, there will be a version of DT that >handles it correctly. That the current implementation can not, is only >an implentation problem :-). Having the implementation thus permanently buggy seems like a bad idea. Also, the version of DT that someone is using might not even know about leap seconds that have already happened. You'll get different answers from different versions, not just at different times. >Seriously, for problems like "2030-06-30T23:59:59Z + 1 second = ", >you need to make an assumption about future leap seconds. I think the only correct approach is to assume nothing and answer "I don't know". > That is a >decision that may not be appreciated by the users of our modules that >are not as familiar with leap seconds as you. I think to do date arithmetic around possible future leap seconds you need to either represent the uncertainty or have the user say what assumptions to make. It would be nice to be able to represent the time of a hypothetical future leap second, if I want to guess about when they might be and schedule events for them. Generally I think this falls under the rubric of giving DT a more sophisticated model of time-of-day. > We should not perhaps be calling our time scale >"utc"; but that would again be hard to explain to ordinary users. How times change. When the POSIX time_t stuff was being written, the knowledgeable people on the committee who wanted to write in terms of "UTC" were (for a while) overruled by those who didn't want to confuse readers with unfamiliar acronyms. They wanted to stick with their nice, familiar (and wrong) "GMT". I think you should at least document how your time scale goes. It'd be better to give DT knowledge of multiple time scales. >At the *end* of a leap second? That seems counterintuitive, but if you >say so... This would mean that the jd value of time points during the >leap seconds appear to belong to the next day. Yes, it works that way. See, if I represent a UTC time as a tuple of (mjdn, ssm), where ssm is "seconds since midnight", the calculation goes MJD[UTC] = mjdn + ssm/86400 The discontinuity is at the end of the day. Also think about a negative leap: the discontinuity is there also at the end of the day, only 86399 s since midnight. We don't wait until 86400 s since midnight, 1 s after midnight of the next day, to jump the MJD. There actually were negative leaps in the rubber seconds era. Btw, in the rubber seconds era the ssm used in this calculation is UTC seconds, not TAI seconds. >By the way, it seems that my DT::F::E::JD module gets this right. Since, as I said, it's a slightly ill-defined concept anyway, "right" is not so much any particular behaviour, but rather documenting exactly what you do. Anything that mixes JD and UTC really needs to document how it maps between them. -zefram
Re: low-level date modules
Rick Measham wrote: >I'm still trying to convince people that you can't just add 24*60*60 to >time() to add a day .. That's one of the things you *can* do, unless you're starting in a leap second (in which case time() is ambiguous). time() increases exactly 86400 per UTC day, regardless of day length. -zefram
Re: low-level date modules
Eugene van der Pijll wrote: >But have you looked at the DT::Format::Epoch example in my first mail yet? Your example of usage made it clearer. I'm not sure what to make of it yet. I need to ponder it some more. There's a basic difference in our approaches to JDs here. You've implemented CJD as a calendar, a way to denote points in time that are abstractly represented by DateTime objects. That's a good thing to do, once you've got DTs. What I did with Date::JD was at an entirely different level: it has no canonical date format at all, and converts between JD flavours as peers. Yours makes more conceptual sense for users of calendar-like modules; Date::JD is intended purely as glue *between* calendar modules. I'm not sure a comparison is appropriate. Anyway, glad to see that DT::F::Epoch can do that. I didn't realise it was that flexible. >If you care about leap seconds, just stay far away from the floating >timezone. I noticed that bit. >The only reason DateTime.pm (the module) seems to be the fundamental >class of DateTime (the project) is the name; it has no central role, >although there are a number of modules (e.g. formatting modules) that >have been written especially for DT.pm, because it is the most commonly >used. Curious. Is there actually any class with a central role of representing dates/times? >Every DT::Calendar module has two required functions: one that returns >the RD and the number of elapsed seconds in the day; and one that >accepts these values and converts them to a new object. What does the object actually represent? -zefram
Re: low-level date modules
Rick Measham wrote: > how can you be >happy with adding 86400 seconds for a day (even in UTC) when leapseconds >make it ambiguous? Oh, I'm not happy with it. time_t is not suitable for serious timekeeping. It's just that if one *is* using time_t then that's how it works. -zefram
Re: low-level date modules
Eugene van der Pijll wrote: >Importantly, there are no "calendar-less" datetime objects. One may see >this as an important difference between your approach and DateTime's; >one may also see it as an implementation detail. I think it's a very important architectural issue. To my mind a date (or date+time) exists quite independently of calendars. Each calendar is merely a way of representing these dates. The DateTime way makes it look like the expression of the date is part of its identity. Of course, if one has the right mental model, that it is the RDN that directly encodes the abstract date identity, then it becomes clear that what the DateTime (or DateTime::Calendar::Whatever) represents is not really the date but some calendar-specific aspects of date representation. Something you left out of your description: the date data in a DateTime can be modified. Here once again the object is not representing a date per se. If I consider the date that in ISO 8601 is represented as "2006-07-18", it is meaningless to say that I "change its month to August". That date is irrevocably in the Gregorian month July. Yet DateTime lets me do $dt = DateTime->new(year => 2006, month => 7, day => 18); $dt->set_month(8); print "$dt\n"; => 2006-08-18T00:00:00 Of course I haven't changed 2006-07-18; all I've changed is the content of a modifiable part of the DateTime object. So a DateTime actually represents a *variable*, typed to hold a date (and time), viewed from a distinctly Gregorian viewpoint. My feeling on variables is that Perl already has a pretty good implementation of them, and so building this facility into the DateTime class is reinventing the wheel. And this one looks square: it doesn't seem to be possible to modify the entire content of the variable in one go except by a ->set call with eight parameters. I don't want to single out DateTime for criticism on this point, though. A lot of classes all over the place do the same thing. Even Math::BigRat, which I curse every time I manage to accidentally modify one. Anyway, having rambled a bit there, the point was that this is another of the bits of baggage that comes with DateTime that I'd rather do without. Which is why I started writing much plainer date-handling modules. And a bonus point which falls out of this thread of discussion: I like very clear documentation, and particularly a clear concept of what an object represents. So I think it'd be good if we could come up with sentences starting "An object of this type represents ..." to go at the top of each class's documentation. -zefram
Re: low-level date modules
Joshua Hoblitt wrote: >How is it buggy? In the same sense that it'll be fixed by a future version's knowledge of each future leap second. You not-seriously suggested that the incompleteness of the leap second list was merely a bug that would be fixed in a future version. In reality it's not a bug for the list to be incomplete. It's a bug for it to treat the list as complete. >So what are you proposing? Modeling future leapseconds? There are so many ways to model them. Over the long term (centuries) it's possible to forecast approximately how many leap seconds will have occurred by then. Stating actual dates for them is right out, though. There are purposes for which this kind of estimate is useful. But I think it's a pretty specialised requirement. >I would really like to hear your solution to this problem. I don't have a solution, sorry. Only some vague thoughts. I think DateTime should probably provide more than one way to handle unknown leap seconds. The user ought to be able to say "do this calculation assuming an average of one leap second every 500 days over this period". The user also ought to be able to say "I need an exact answer, so complain if the answer depends on leap seconds that you don't know about". I think on correctness grounds the default behaviour should not make any assumptions at all about unknown leap seconds. And I think it all needs to be documented, whatever the behaviour is. -zefram
Re: low-level date modules
Dave Rolsky wrote: >>Which is why I started writing much plainer date-handling modules. > >Modules which while interesting are unlikely to be comprehensible to most >folks. Are they really *incomprehensible* to most people? But I didn't aim them at "most people" as you describe them. I wrote the modules for programmers who know what they're doing or are willing to learn. >As an aside, I've gotta say I'm really disappointed that you went to the >trouble of writing all this code _before_ talking to anyone on this list. Sorry about that. I was initially under the impression that this mailing list was strictly concerned with DateTime and its existing architecture, rather than with date/time issues in general. I got pointed here from the modules mailing list, when I tried to register Date::JD. -zefram
Re: month_name() returns UTF-8 or Latin-1?
Dave Rolsky wrote: > 97-111-251-116 That's not a well-formed UTF-8 sequence. It *is* correct Latin-1 or Unicode, encoding a sequence of four characters. > IS UTF8 That refers to the internal UTF-8 flag on the string. That means it's internally represented using UTF-8, which usually means that the string being represented is Unicode, not UTF-8. -zefram
Re: simple calculation frustrations
Matthew wrote: >But! Then the time changed and now the calculations are off by 1 hour. Not at all! The calculations will continue to give you precise one-week intervals. It's just that with the change in timezone offset these intervals are no longer *described* using the same time of day. OK, so you want the other behaviour. I suggest that instead of storing an actual timestamp you should store a broken-down time: week number, day of week, local time of day, and (most important) timezone rule. You can put those together in DateTime to find out what point in time they refer to. Increment the week number as required. Watch out for times of day that get repeated or skipped at offset changes. These are different times of day in different timezones. -zefram
Re: simple calculation frustrations
Dave Rolsky wrote: >Pretty much all DBMS's (ok, not SQLite) have support for datetime as a >data type. Worms. Can thereof. A datetime type is not a primary feature of a DBMS, so it's probably not had much attention paid to it. Until recently, MySQL's datetime type allowed dates such as 2006-04-31. Even if it's implemented correctly, it'll implement some arbitrarily selected date model that's not particularly likely to match your need. In this case, timezone behaviour is the issue, and not very many datetime types handle multiple timezones in the way desired. Using a DBMS's datetime type also loses you portability, of course. >The advantage to this is that your datetime data is stored in a consistent >way, so if you ever need to compare datetimes for some reason, you know >that they'll compare sanely. I think what he wants to store isn't actually a date, as in a point in time. Looks like he wants to store a time of week, timezone-relative, along with a timezone spec. The incrementing loop he came in with is just answering the question "when will that time of week next occur?". -zefram
Re: is YYYY-MM-DD HH:MM:SS an ISO8601 format?
Joshua Hoblitt wrote: >Thoughts or comments on this bug that was just filed on DT::F::ISO8601 >would be appreciated. The summary: "-MM-DD HH:MM:SS" is not accept >by DT::F::ISO8601 and I don't believe it's a valid 8601 format. Your analysis is correct. Default ISO 8601 rules require date and time-of-day portions to be separated by a "T" or "t". So "2006-11-15T11:04:40" and "20061115t110440" are valid. Only by prior agreement may the separator be omitted. The "prior agreement" expression means that it's not standard, and formally has the status of any other non-standard variation that one might invent. Leaving out the separator is technically as non-conforming as putting the time-of-day portion first. However, the standard committee is suggesting that omitting the separator is a particularly reasonable variation. When the need (a tight space constraint) exists, this is the approved way to adapt the rules. The same expression is used for variations such as five-digit years, to address other situations that the basic standard doesn't cover. Omitting the separator is presumably meant to allow the format "20061115110440", not "2006-11-1511:04:40". The latter would be silly, saving a character in one place at the expense of conformance while retaining other unnecessary separators. The common practice of replacing the "T" with a space isn't mentioned in the standard at all, AFAIR. This is presumably because it is a gratuitous variation: it doesn't save space or satisfy any other syntactic or semantic requirement. It also breaks the consistent feature that ISO 8601 formats consist only of printing characters, never spaces. It is commonly done simply for human familiarity, to more closely resemble pre-standard date conventions. I think applications that want to use such non-standard variations can do their own conversions. Interesting comparison: MySQL allows *any* non-digit character for the "T" separator, and indeed for all the other separators. It can do this because it requires a particular sequence of elements: four-digit year, month, day of month, hour, minute, second. Any application that needs to accept different element sequences needs to look at the prefix and separators. -zefram
Re: is YYYY-MM-DD HH:MM:SS an ISO8601 format?
David Cantrell wrote: >Isn't the timezone also required? No. Particular applications of ISO 8601 may require it, but ISO 8601 itself does not. The standard allows great freedom in the choice of elements, and concerns itself with how to represent the desired combination of elements. Mechanism, not policy. -zefram
Re: Trouble with time
Rafael Morales wrote: >Why the seconds and milliseconds do not change ?? How can I do it to >work fine ??? Your program looks up the current time once, at the start. It then repeatedly prints out that one time. $time never changes. You want to move the call to time() inside the loop, so that it looks up the current time each time round: while(1) { my $dt = DateTime->from_epoch( epoch => time() ); my $time = $dt->strftime( '%Y-%m-%d %H:%M:%S.%3N' ); print "$time\n"; } -zefram
Re: Trouble with time
Stupid trick to make it do the magic Rafael expected: #!/usr/bin/perl use warnings; use strict; { package Tied_Strftime; sub TIESCALAR { my($class, $fmt) = @_; return bless(\$fmt, $class); } sub FETCH { use DateTime; use Time::HiRes qw(time); return DateTime->from_epoch(epoch => time)->strftime(${$_[0]}); } } tie my $time, "Tied_Strftime", "%Y-%m-%d %H:%M:%S.%3N"; while(1) { print "$time\n"; } #-zefram
Re: Fwd: DateTime::Calendar::Christian::Liturgical
Rick Measham wrote: >I wrote a lot of this a few years back (1). But came a across a huge >problem: The more I researched, the more difficult it became. Not only >does every country use a different liturgical calendar, but every >Province and possibly down to parish. (Where the local Saint's day can >replace an 'Ordinary' Sunday) Sounds like a job for subclassing. >* You'll need to provide options for determining your dates based on >rules (Is Epiphany on Jan 6 or on Thursday?) And mixins. -zefram
Re: Indic calendars
Jaldhar H. Vyas wrote: >On this auspicious day of Poshi Poonam (full moon of the month of Pausha) >I would like to announce that I'm working on implementing various >Calendars traditionally used in India for the DateTime API. I didn't realise there were several. I was fascinated by the lunisolar one described in Calendrical Calculations. >So I was planning on using the following namespaces: ... >Does this seem ok? Looks good to me. -zefram
Re: Indic calendars
Jaldhar H. Vyas wrote: >Unfortunately the one described there doesn't really match up to anyone >used in real life. Not all that surprising. I found an awful lot of errors in that book on the stuff that I know about. -zefram
Re: changing Daylight Savings Times (DST) in 2007
Aravind J wrote: >Do we have any patch for the Perl Date & Time module for new Daylight > Savings Times (DST) changes in 2007 as per Energy Policy Act of 2005 The latest DateTime::TimeZone, version 0.57, reflects this change. -zefram
Re: changing Daylight Savings Times (DST) in 2007
[EMAIL PROTECTED] wrote: > What was the first version of the >Olson tz database to incorporate the legislated 2007 North American >Daylight Saving Time changes? 2005l. > Is it correct to say that DateTime has >been DST2007-ready since 2005? Since version 0.38, released 2005-11-21. -zefram
Re: ANNOUNCE: DateTime::TimeZone 0.58
Matthew wrote: >How can I ensure that all our linux servers are up to date with the >2007a Olson database? The quick way for a single server is: # perl -MCPAN -e'install DateTime::TimeZone' >everyone out there have to update their zoneinfo to accommodate the new >time changes? No. You need to update if you're likely to process timestamps that are affected by the latest updates. Whether you're affected depends on what version you're currently on and (obviously) what kind of work you do. Unfortunately there doesn't seem to be much of a changelog for the Olson database. It won't hurt to upgrade anyway. -zefram
Re: changing Daylight Savings Times (DST) in 2007
Monty, James T wrote: >This isn't obvious from the CHANGES files; in fact, it seems to >contradict them. Which file do you speak of? I based my answer on the timezone list archive <ftp://elsie.nci.nih.gov/pub/tzarchive.gz>, which pointed at 2005l, and the DT::TZ Changes file <http://search.cpan.org/src/DROLSKY/DateTime-TimeZone-0.58/Changes>, which said that 2005n went into 0.38. -zefram
Re: changing Daylight Savings Times (DST) in 2007
Aha, I have discovered an error in the Changes file. It says "based on version 2005i of the Olson database" for both 0.36 and 0.37, but those two versions actually have different rules for America/New_York. 0.37 has the new 2007+ rule, whereas 0.36 does not. I suspect that 0.37 is actually based on version 2005l. Anyway, for your FAQ: based on brief examination of the module files, the first released version of DT::TZ that has the 2007+ US rule is 0.37, dated 2005-08-22. -zefram
Re: recurring system
Matthew wrote: > To me, this seems amazingly inefficient. If my weekly recurring >original event start date was Aug 1, 2006, the perl would have to loop >26 times to find the next event (in this case, Jan 23). > >Can anyone offer a better solution to this? Yes: determine the day-of-week of the original event, and the week containing tomorrow, then put them together. With my Date::ISO8601 module this looks like: use Date::ISO8601 qw(ymd_to_cjdn cjdn_to_ywd ywd_to_cjdn present_ymd); my $today_cjdn = ymd_to_cjdn(2007,1,16); my $initial_cjdn = ymd_to_cjdn(2006,8,1); (undef, undef, my $repeat_dow) = cjdn_to_ywd($initial_cjdn); my($next_y, $next_w, $today_dow) = cjdn_to_ywd($today_cjdn + 1); if($today_dow > $repeat_dow) { ($next_y, $next_w, undef) = cjdn_to_ywd($today_cjdn + 8); } print present_ymd(ywd_to_cjdn($next_y, $next_w, $repeat_dow)), "\n"; I expect the same algorithm can be implemented using DateTime, but I'm not a regular user of that, sorry. -zefram
Re: not correct timezone
abhishek jain wrote: >perl -e 'use DateTime;print DateTime->now()->hms()'; > >i want to print the correct time but it is dispaying the previous timezone's >time. It's using the universal timezone (UTC), not paying attention to *any* timezone setting. You have to tell it to use a timezone: perl -e 'use DateTime;print DateTime->now(time_zone => "local")->hms()'; -zefram
syntax to specify time scales
ht also be useful to allow the variable-length ISO 8601 period duration format, so "+3m" (for +00:03) and "+76.3s" (for +00:01:16.3) would also be allowed. There doesn't seem to be any parsing trouble in store there. Getting more obscure: as a workaround for the limitation of the Olson database, it might be useful to specify a base timezone and add onto that the offset rules from a geographical civil timezone. Legal London civil time is essentially UT1 + offset_rule_of(Europe/London). Should we have a syntax for that? Similarly, what about generating a new base time scale by offsetting an existing one? GPS time is TAI - 19s, so perhaps similar cases should be specifiable in this manner. But the syntax must be conspicuously different from that used to add a timezone offset, because this offset is part of the base time scale, not a timezone. Finally, there are situations where only a base time scale is to be specified, and timezones are not permitted. Displaying an MJD is such a situation. Congratulations if you've made it this far through this message. My experimental code is at http://www.fysh.org/~zefram/time/purchron For a multi-scale display, do $ purchron '(fixed,UTC:)_(ymdhms,UTC,9,-1)/___(fixed,GPST:)_(ymdhms,GPST,9,-1)/(fixed,TAI:)_(ymdhms,TAI,9,-1)/(fixed,TT%28TAI%29:)_(ymdhms,TT_TAI,9,-1)' -zefram
Re: syntax to specify time scales
m too onerous. And I hope that time scales that are just fixed offsets from other time scales will not proliferate. >I like it. I would like to reach a point where we can implement this in >DateTime. There are some considerations for that which you probably don't want to influence DateTime. In a real-time clock program, overhead is important. You'll notice that purchron does some bignum stuff with the libraries, but that's all relegated to the non-RT thread which researches stuff in advance. All the calculations in the main thread are done in open-coded native integer arithmetic, to get the new display frame out as quickly as possible. I'm quite pleased that I get acceptable performance from pure Perl, without having to resort to C. What you should aspire to with DateTime is first to do all those calculations, with a suitably abstracted interface. Don't compromise on the abstraction or functionality of DateTime to get its performance up to what purchron achieves. For my own libraries, I'm finding that I'm implementing several things in real-time and non-real-time versions. purchron is where all the real-time stuff goes, though I might make another library out of that some day. -zefram
Re: syntax to specify time scales
Rick Measham wrote: >my $riyadh_lmt = DateTime::TimeZone::LMT->new( >longitude => 46 + (43 / 60) + (27 / 3600) >); How much error in time conversions is introduced by the floating point rounding? >A thought: it might be good to somehow include the ability to load other >TZ modules from a string. Eg. time_zone => "LMT/46d43m27s" would look >for LMT/46d43m27s.pm and failing that, drop back to looking for LMT.pm >and pass it's constructor the '46d43m27s'. I'd say don't do that with "/", which should be reserved for hierarchical naming. Maybe parens, though. But you don't need it for LMT if the generic offset capability is implemented: you can always do LMT as a "UT1+..." spec. -zefram
Re: syntax to specify time scales
Eugene van der Pijll wrote: > it's the difference >between GPS and TAI(GPS) that is fixed, right? Forgot to reply to this earlier. Yes, strictly speaking the equation is TAI(GPS) = GPST + 19 s I've been using the term "GPS time" slightly loosely, to refer to what we might call GPST(TAI), defined as GPST(TAI) = TAI - 19 s TAI(GPS) stays within about 10 ns of TAI. In purchron the difference between GPST and GPST(TAI) is swamped by the uncertainty with which TAI is known, so I think I'm justified in dropping the "(TAI)" there. -zefram
Re: syntax to specify time scales
ses, I think we only want the database for the first class of name (pure geographical). If we're extending the timezone namespace then we can decide for ourselves what to do for backward compatibility. Conveniently, the pure geographical names follow a fairly restrictive syntax: no digits, no "+", no "-" in the first component. >User interface could be better, Which aspect of it? User friendliness was certainly not a major consideration in writing it, but I'm open to suggestions. >When do you plan to implement UT1 (using the published values, some >interpolation and extrapolation, and some (no doubt inaccurate) equation >for the deceleration of the earth's rotation? ;-) I certainly do plan to do the astronomical time scales. I'm gradually researching sources of TT<=>UT1 data. The IERS publishes measured daily values of UT1-UTC, and each week publishes daily extrapolated values for the next year. That gives me recent history and near-term future. For long-term future we have good models of the secular deceleration: it's pretty linear. Phase lock is lost, but interval calculations will work. Medium-term future I'm concerned about, because IERS has the knowledge to extrapolate years out but doesn't publish either the models or the predictions AFAICT. For the past, going back a couple of centuries, actual measurements exist, but I don't know where to find them. For earlier recorded history there are some very isolated measurements from eclipse records, also requiring research. In prehistory we've got archaeological and geological evidence of LOD, but of course no phase synchronisation. I'd like to put all this knowledge behind a consistent interface. So tt_to_ut1() and ut1_to_tt() functions will hide the complexity of multiple data sources. Also want tai_to_ut1() and ut1_to_tai(), for greater precision in the TAI era. (UT1-TT(TAI) is known somewhat better than UT1-TT, because of the uncertainty in TT(TAI)-TAI.) I really want to have explicit uncertainty bounds as part of this interface. I ought to add them to the Time::TT conversions too: they're conspicuously missing, but unfortunately the uncertainty data is also conspicuously missing from the data files that it downloads from BIPM. The real-time version of UT1 in purchron only needs to look at IERS forecasts. Ideally I'd like to do that by using the non-real-time tai_to_ut1() in the background and then doing piecewise linear interpolation in the display generator. But since handling the IERS forecasts alone is much simpler than the full UT1 module, I might do the IERS bit on its own in purchron first. -zefram
Re: syntax to specify time scales
For reference, the POSIX definition of $TZ syntax is at <http://www.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap08.html>. In summary, POSIX defines the meaning of $TZ strings matching $posix_tz below: $abbrev = qr#[A-Za-z]{3,}|\<[-+0-9A-Za-z]{3,}\>#; $offset = qr#[-+]?([01]?\d|2[0-4])(:[0-5]\d(:[0-5]\d)?)?#; $rule_date = qr#J0*([1-9]|\d\d|[12]\d|3([0-5]\d|6[0-5])) |0*(\d|\d\d|[12]\d|3([0-5]\d|6[0-5])) |M0*([1-9]|1[0-2])\.0*[1-5]\.0*[0-6]#x $rule_time = qr#([01]?\d|2[0-3])(:[0-5]\d(:[0-5]\d)?)?#; $rule_dt = qr#${rule_date}(/${rule_time})?#o; $posix_tz = qr#${abbrev}${offset} (${abbrev}(${offset})?(,${rule_dt},${rule_dt})?)?#xo; (Some of the syntax isn't stated with full clarity in the standard, so a bit of interpretation went into the above.) It also states that any string starting with ":" has implementation-defined meaning. Interaction with the Olson syntaxes: * all Olson syntaxes that include a "/" are disjoint from POSIX ($posix_tz can include a "/", but if so then there must be a digit earlier in the string, which Olson never does) * the US ones such as "EST5EDT" are backward compatibility hacks for the same syntax that POSIX also allows for backward compatibility (POSIX doesn't actually define when DST is taken to start and end if the rule is not explicitly given) * the short names qr#GMT[-+]?0# overlap with POSIX and are interpreted the same by both * other short names are disjoint from POSIX Olson's fixed offsets from UT, with names like "Etc/GMT-5", don't appear at the top level presumably because they clash with POSIX syntax. POSIX would interpret "GMT-5" as meaning a timezone 5 hours *ahead* of UTC, and bearing the name "GMT". Rick: you suggested allowing a timezone string to give a module name and constructor argument. Interpreting POSIX timezone strings might be a good application of this idea. -zefram
Re: syntax to specify time scales
Eugene van der Pijll wrote: > Lord Tanlaw refers to the UK as the only >industrialized country that has its legal time based on GMT. But there >are probably a lot of former colonies that have not changed their time >laws. Found a source for more on this. <http://www.ucolick.org/~sla/leapsecs/ onlinebib.html> has a section about it, with many links. It explicitly lists some countries where legal time is based on UTC: France, Germany, Hong Kong, Korea, Netherlands, New Zealand, Sweden, and Switzerland. It also explicitly lists some that are based on GMT: the European Union, Ireland, Namibia, United Kingdom, United States (former colony!), and the canadian provinces Ontario, Saskatchewan, and Quebec. So the noble Lord was in error on that point. The context for that bibliography page is the debate over whether leap seconds should continue. One of the problems that would occur if UTC were to have no more leaps is that UTC+offset would cease to be a good approximation of legal time in countries where legal time is GMT+offset. It's essentially impossible to get all the countries in the world to legislate on anything. I also searched the Olson database. As we know it doesn't directly address this topic, but I looked for offsets that were not in integral minutes. A fractional-minute offset is a dead giveaway for use of solar time, because UTC can't accept such offsets. The database doesn't list any timezone with a current offset involving fractional minutes. The last usage of such an offset that it records was in Liberia, and ceased on 1972-05-01. The database doesn't actually say much about Saudi Arabia; the apparent-solar-time files are presented without real explanation. I'd like to introduce for consideration the concept of explicitly vague Universal Time. The term "UT" on its own is ambiguous: it refers to UT1, UT2, UTC, UT0, UTC-SLS, and others, collectively. If one is working at the minute level or above, the differences between the flavours of UT are insignificant, so merely specifying "UT" suffices. Unix timestamps that predate precise UTC synchronisation are ambiguous in just this way, and so Unix time in that era is best understood as being based on "UT", rather than UTC or GMT specifically. This seems to be the best way to think about DateTime's current time scale too, when working outside the range of known leap seconds. I think this vague UT is what we should consider Olson timezones to be based on, not UTC. I asked the tz mailing list about base time scales a while ago, and their answer supported this interpretation. In the present era they consider the timezones to be based on "UTC" (that's the term they use), but they don't really think about the meaning of that, and they have no answer for what time scale they're based on prior to UTC's existence. It's the usual problem with interdisciplinary timekeeping: three or four orders of magnitude difference is enough to prevent most meaningful dialogue. With that interpretation of the Olson database, an implementation is free to use the database's offsets with whatever form of UT it finds most convenient: most likely UTC. Until the database does properly address the issue, let's not perceive information that's not there. -zefram
Re: syntax to specify time scales
UT" in the above paragraph is complicated. Nautical timekeeping has been precise enough to distinguish between UTC and UT1 for longer than UTC has existed. Sub-second timekeeping is essential for precise astronomical navigation. These timezones were originally based specifically on GMT (UT1). The DUT1 correction is published in order to allow nautical use of UTC, so modern practice probably does use UTC. ISO 8601 "Z" represents the base time scale. An offset in hours and minutes may be specified with the syntax qr/[-+]\d\d:\d\d/ (except that "-00:00" is prohibited). The standard mentions UTC in some places, but isn't actually specific to that. The textual formats are applicable to any use of the 24-hour clock. -zefram
Re: missing something..part 2
Matthew wrote: >I see all the Etc/GMT+X inside my /usr/share/zoneinfo/Etc/ so what's up? DateTime::TimeZone doesn't look in /usr/share/zoneinfo. It has its own version of the zoneinfo database, in the form of Perl modules, but it doesn't include the Etc pseudo-zones. >Are the Etc/GMT+X the proper "generic" time zones to use if your >country/region isn't specified? Sort of. Not quite. If your timezone isn't in the database, you should mail the database maintainers to get it added. If you want to use a fixed offset from GMT/UTC/UT/whatever as your timezone, Etc/GMT+X is the hack to use in the zoneinfo database, but DateTime::TimeZone has a better mechanism for this. To get 5 hours behind UT, which is what Etc/GMT+5 does, pass in the timezone name "-05:00". Note the change of sign: for historical reasons the signs in the Etc/GMT+X names are the opposite of the actual offset. -zefram
Re: missing something..part 2
Matthew wrote: > Hehe. I'm the DBA. And I've updated everything to most recent stuff, >but the boss man wants "generic time zones" in our list "just in case" a >customer can't find his or doesn't realize his city is listed differently. Unlikely to ever occur. As far as anyone knows, the Olson zoneinfo database contains all currently-distinct timezones. (It explicitly aims to include all timezones that have been distinct at any time since 1970.) You might want to play with the tzselect(8) program, which guides one through selecting a geographical timezone from the database. -zefram
SysV timezones in DT::TZ
I've knocked together an implementation of SysV/POSIX timezone specifications for DateTime. Code is at <http://www.fysh.org/~zefram/tmp/SystemV.pm>. This is my first go at implementing anything in the guts of DT, so experts here please check that I'm using the interfaces correctly. I don't quite follow what the semantics are meant to be when a DT object has its timezone changed. I'm not clear on which DateTime methods a timezone object can rely on, in the arguments it is given to the _for_datetime methods. I need to do Gregorian arithmetic even if the DateTime isn't Gregorian. I used only ->utc_rd_values and ->local_rd_values, and then called out to my Date::ISO8601 module to do the date arithmetic. Is it OK for me to put this on CPAN? -zefram
Re: SysV timezones in DT::TZ
I wrote: >I've knocked together an implementation of SysV/POSIX >timezone specifications for DateTime. Code is at ><http://www.fysh.org/~zefram/tmp/SystemV.pm>. No comments from anyone, and only two people have downloaded the code. I presume, then, that those who looked at the code were happy with it, and everyone else at least has no objection to the concept. I'm also now working on a tzfile(5) reader in DT::TZ form. I'll publish that shortly; it's operational but the code's just a bit rough at the moment. The motivation for these modules is that I think the DT::TZ ensemble ought to be able to do everything that libc does to interpret $TZ settings. It's a digression from the question of $TZ syntax. (Most of the stuff I work on is a digression from something.) -zefram
$TZ parsing
Summary of <[EMAIL PROTECTED]>: various parsers of $TZ allow these syntaxes: glibc Olson Solaris HP-UX DT:TZ y0 y y y n y0 n n y n: y y y n n/ y y y n n:/ y y y n y y y y n n: n n n n yfloating n n n n yZ n n n n n1 Note 0: glibc does a subset of POSIX-extended SysV syntax, not the whole thing. Note 1: looks like DT::TZ might have been meant to accept an offset here, but in fact it is rejected. An offset is accepted in the "name" constructor argument, but not in $TZ. The handling of leading ":" is interesting. All the parsers that accept it at all have at least one syntax that is accepted both with and without it. So, although POSIX specifies it as introducing completely implementation-defined syntax, the tendency is for it to allow a different subset of syntaxes; the discernible meaning of a $TZ string is unaffected by a leading ":". I think generally DT::TZ would be better if it parsed $TZ in a manner more like the various libcs. At the moment the Olson names are the only syntax that it has in common with them. As I've mentioned, I'm developing modules that will handle SysV syntax and tzfiles, so these could be used to parse the other kinds of $TZ string. I think a leading ":" should also be accepted and ignored, for compatibility with the libcs that accept it for some syntaxes. -zefram
Re: SysV timezones in DT::TZ
I wrote: >I'm also now working on a tzfile(5) reader in DT::TZ form. Trial code is at <http://www.fysh.org/~zefram/tmp/Tzfile.pm>. If there are no objections, I'll put DT::TZ::SystemV on CPAN at the coming weekend, and DT::TZ::Tzfile the next weekend. -zefram
Re: SysV timezones in DT::TZ
DateTime::TimeZone::SystemV is now on CPAN. -zefram
Re: in search of a method of determining time and date info in various parts of the world
Virden, Larry W. wrote: >But how do I turn the user supplied date and time into the time for the >various timezones, and figure out whether daylight savings time is in >effect? DateTime can do this: #!/usr/bin/perl use warnings; use strict; use DateTime; use DateTime::TimeZone; my $dt = DateTime->new(year => 2006, month => 3, day => 13, hour => 13, time_zone => "America/New_York"); foreach (qw( America/New_York America/Los_Angeles America/Denver America/Chicago Europe/Zurich Europe/London Asia/Jerusalem Asia/Tokyo Europe/Moscow Australia/Melbourne )) { my $tz = DateTime::TimeZone->new(name => $_); $dt->set_time_zone($tz); print $dt->iso8601, " ", $_, " (", $tz->is_dst_for_datetime($dt) ? "DST" : "std", ")\n"; } -zefram
Re: SysV timezones in DT::TZ
DateTime::TimeZone::Tzfile is now on CPAN. -zefram
revision of DT::TZ name parsing
Attached is a patch that revises timezone name parsing in DT::TZ. The changes: Anything that looks like a System V timezone string is treated as such, via DT::TZ::SystemV. This interpretation overrides some of the zones and links in the Olson database, and a couple that were in DT::TZ only. In each case, of course, the overridden names existed for ad hoc backwards compatibility with System V. A filename (beginning with "/") is accepted as a timezone name, and the file is parsed by DT::TZ::Tzfile. (To consider: how should this facility behave on non-Unix systems? It would be nice to keep leading "/" as the signal to the parser that a filename is coming up. So the main options are (a) parse a Unix-like filename and translate to local form and (b) accept "/" followed by a local-form filename.) A leading ":" is accepted and ignored in any timezone name except for the meta-name "local". This provides compatibility of $TZ parsing with the various libcs. If a timezone name can't be parsed at all, the error comes from DT::TZ rather than DT::TZ::OffsetOnly. This makes the message less confusing, and is a cleaner arrangement. Embedded "::"s are not allowed in place of "/" in Olson zone names. That was an undocumented capability that didn't apply to link names. In $TZ, *any* name other than "local" is accepted, as the documentation already stated. Previously a character set limitation was applied which prevented the use of the numerical offset syntax. The handful of non-SysV single-part zone (not link) names in the Olson database are implemented differently. Formerly the EU ones were filtered out and the rest (the US ones) were accepted as first-class zones. Now the US ones, which are all fixed offsets, are implemented as aliases to System V strings, and the rest (the EU ones) are thrown away. Little difference in behaviour, but internally cleaner. Now no single-part Olson zone names are used as such. The documentation about name parsing is now more accurate. -zefram
Re: revision of DT::TZ name parsing
I wrote: >Attached is a patch that revises timezone name parsing in DT::TZ. Except that I forgot to attach it. D'oh. Really attached this time. After applying the patch you'll need to do a "./tools/parse_olson --clean". -zefram diff -ur dttz-0.59/Build.PL dttz-mod0/Build.PL --- dttz-0.59/Build.PL 2007-01-18 15:57:56.0 + +++ dttz-mod0/Build.PL 2007-02-10 18:04:20.0 + @@ -27,6 +27,8 @@ requires=> { 'Params::Validate' => 0.72, 'Class::Singleton' => 1.03, 'Pod::Man'=> 1.14, + 'DateTime::TimeZone::SystemV' => 0.000, + 'DateTime::TimeZone::Tzfile' => 0.000, }, build_requires => { 'Module::Build' => 0 }, sign=> 1, diff -ur dttz-0.59/lib/DateTime/TimeZone/Local.pm dttz-mod0/lib/DateTime/TimeZone/Local.pm --- dttz-0.59/lib/DateTime/TimeZone/Local.pm2007-01-18 15:57:56.0 + +++ dttz-mod0/lib/DateTime/TimeZone/Local.pm2007-02-11 11:01:58.246367883 + @@ -237,7 +237,7 @@ return 0 unless defined $_[0]; return 0 if $_[0] eq 'local'; -return $_[0] =~ m,^[\w/\-\+]+$, ? 1 : 0; +return 1; } diff -ur dttz-0.59/lib/DateTime/TimeZone/OlsonDB.pm dttz-mod0/lib/DateTime/TimeZone/OlsonDB.pm --- dttz-0.59/lib/DateTime/TimeZone/OlsonDB.pm 2007-01-18 15:57:56.0 + +++ dttz-mod0/lib/DateTime/TimeZone/OlsonDB.pm 2007-02-11 10:48:55.524500689 + @@ -111,8 +111,6 @@ $name = shift @items; } -return if $name =~ /[WCME]ET/ && ! $self->{backwards_compat}; - @obs{ qw( gmtoff rules format until ) } = @items; if ( $obs{rules} =~ /\d\d?:\d\d/ ) diff -ur dttz-0.59/lib/DateTime/TimeZone.pm dttz-mod0/lib/DateTime/TimeZone.pm --- dttz-0.59/lib/DateTime/TimeZone.pm 2007-01-18 15:57:56.0 + +++ dttz-mod0/lib/DateTime/TimeZone.pm 2007-02-11 11:00:36.820591025 + @@ -6,10 +6,6 @@ $VERSION = '0.59'; use DateTime::TimeZoneCatalog; -use DateTime::TimeZone::Floating; -use DateTime::TimeZone::Local; -use DateTime::TimeZone::OffsetOnly; -use DateTime::TimeZone::UTC; use Params::Validate qw( validate validate_pos SCALAR ARRAYREF BOOLEAN ); use constant INFINITY => 100 ** 1000 ; @@ -24,8 +20,6 @@ use constant IS_DST => 5; use constant SHORT_NAME => 6; -my %SpecialName = map { $_ => 1 } qw( EST MST HST EST5EDT CST6CDT MST7MDT PST8PDT ); - sub new { my $class = shift; @@ -33,66 +27,81 @@ { name => { type => SCALAR } }, ); -if ( exists $DateTime::TimeZone::LINKS{ $p{name} } ) +if ( $p{name} eq 'local' ) { -$p{name} = $DateTime::TimeZone::LINKS{ $p{name} }; +require DateTime::TimeZone::Local; +return DateTime::TimeZone::Local::local_time_zone(); } -elsif ( exists $DateTime::TimeZone::LINKS{ uc $p{name} } ) + +my $name = $p{name}; +$name =~ s/\A://; + +if ( exists $DateTime::TimeZone::LINKS{ $name } ) { -$p{name} = $DateTime::TimeZone::LINKS{ uc $p{name} }; +$name = $DateTime::TimeZone::LINKS{ $name }; } - -unless ( $p{name} =~ m,/, - || $SpecialName{ $p{name} } - ) +elsif ( exists $DateTime::TimeZone::LINKS{ uc $name } ) { -if ( $p{name} eq 'floating' ) -{ -return DateTime::TimeZone::Floating->new; -} - -if ( $p{name} eq 'local' ) -{ -return DateTime::TimeZone::Local::local_time_zone(); -} - -if ( $p{name} eq 'UTC' || $p{name} eq 'Z' ) -{ -return DateTime::TimeZone::UTC->new; -} - -return DateTime::TimeZone::OffsetOnly->new( offset => $p{name} ); +$name = $DateTime::TimeZone::LINKS{ uc $name }; } -my $subclass = $p{name}; -$subclass =~ s/-/_/g; -$subclass =~ s{/}{::}g; -my $real_class = "DateTime::TimeZone::$subclass"; - -die "The timezone '$p{name}' in an invalid name.\n" -unless $real_class =~ /^\w+(::\w+)*$/; - -unless ( $real_class->can('instance') ) +if ( $name eq 'UTC' || $name eq 'Z' ) { -eval "require $real_class"; +require DateTime::TimeZone::UTC; +return DateTime::TimeZone::UTC->new; +} +elsif ( $name =~ m#\A[-\w]+(?:/[-\w]+)+\z# ) +{ +my $subclass = $name; +$subclass =~ s/-/_/g; +$subclass =~ s{/}{::}g; +my $real_class = "DateTime::TimeZone::$subclass"; -if ($@) +unless ( $real_class->can('i
API for multiple time scales
I've published some code at http://www.fysh.org/~zefram/time/time_scale_expt which is where I am with regard to processing diverse time scales. I'll do something akin to that in purchron when it's all settled, and I'd like to do something similar in non-real-time Perl modules too. Comments are very welcome. I've been working on the API more than the previously-discussed naming issues. Hence the names used in the published code are all very tentative. -zefram
Re: ANNOUNCE: DateTime 0.60
Matthew wrote: >Should I also be updating my /usr/share/zoneinfo/ and my MySQL tables >with the new Olson db so that everything is current? In principle yes, but not for DateTime's sake. DateTime::TimeZone doesn't use those sources of timezone data. If you were on 2007a then there's no need to upgrade at all: the only change is the update of the copy of Bulletin C in a comment in the leapseconds file. No actual data has changed. -zefram
Re: revision of DT::TZ name parsing
Dave Rolsky wrote: >First, I don't want to make these new modules requirements. What I'd >prefer to do is just load them if they exist and use them. No one (that I >recall) has asked for Posix or binary file support, so making them >dependencies seems like overkill. OK. But it seems a pity that a default install won't be able to parse all $TZ settings that are valid for libc. Actually there have been two DT::TZ users who wanted their System V timezone strings handled (see bottom of this message). >Given that, I don't want to change the handling of these names. This would >be a backwards-incompatible change as it is, since in the Olson database a >name like EST5EDT uses the US rules, meaning it includes many historical >changes. Fair enough. Using US rules is a valid interpretation of "EST5EDT" as a System V string anyway. >This should probably use File::Spec->file_name_is_absolute() to figure >this out. None of the currently valid names are absolute file names on any >system (I think). That would be a bad idea: it would mean that unknown filename syntaxes constrain what system-independent syntaxes we can use in the future. It's theoretically totally unworkable. Anyway, among what we do know, on the Mac any string that doesn't start with ":" is a valid absolute filename. I found a better way: URI::file can translate between filename syntaxes. We can specify that the $TZ setting is a Unix-style filename, and it gets translated as appropriate. On Windows you can do "/c:/etc/localtime" and the file C:\etc\localtime is used, and "/etc/localtime" translates to the not-quite-absolute \etc\localtime. >It seems like a leading colon for other things (like "EST5EDT") would be >an error. Of course, removing it isn't a big deal. I addressed this issue in my survey of $TZ parsing. glibc and HP-UX both accept System V strings both with and without leading ":". glibc, Olson, and Solaris all accept filenames (including Olson names) both with and without ":". Basically, the consensus $TZ syntax is the same both with and without ":". Consistently ignoring the leading ":" is where the trend is heading. >1. Make SystemV & Tzfile entirely optional. >2. Use the Olson versions of existing SystemV names (follows from 1) >3. Use File::Spec->file_name_is_absolute to determine if a name could be a >path to a tz file. Patch attached does 1 and 2, and does filename translation instead of 3. I extended 2 to the non-SysV single-part Olson names that my previous patch implemented as links to SysV strings. There were also two SysV-style strings that were never in Olson, but which DT::TZ had as links to Olson zones. These are "AKST9AKDT" and "JST-9". They were added to satisfy particular DT::TZ users who were using these $TZ settings. As they're not in Olson, I reckon these should be treated as any ordinary SysV string, so this patch has no grandfathering for them. Those users will have to install DT::TZ::SystemV. Grandfathering for them is easily added if you really want to. In other respects it's equivalent to the previous patch. As before you'll need to rerun tools/parse_olson, to pick up the changes to TimeZoneCatalog.pm. -zefram diff -ur dttz-0.6101/lib/DateTime/TimeZone/Local.pm dttz-mod1/lib/DateTime/TimeZone/Local.pm --- dttz-0.6101/lib/DateTime/TimeZone/Local.pm 2007-02-18 15:54:12.0 + +++ dttz-mod1/lib/DateTime/TimeZone/Local.pm2007-02-19 19:30:30.018396544 + @@ -92,7 +92,7 @@ return 0 unless defined $_[0]; return 0 if $_[0] eq 'local'; -return $_[0] =~ m{^[\w/\-\+]+$}; +return 1; } diff -ur dttz-0.6101/lib/DateTime/TimeZone/OlsonDB.pm dttz-mod1/lib/DateTime/TimeZone/OlsonDB.pm --- dttz-0.6101/lib/DateTime/TimeZone/OlsonDB.pm2007-02-18 15:54:11.0 + +++ dttz-mod1/lib/DateTime/TimeZone/OlsonDB.pm 2007-02-19 00:02:04.0 + @@ -111,8 +111,6 @@ $name = shift @items; } -return if $name =~ /[WCME]ET/ && ! $self->{backwards_compat}; - @obs{ qw( gmtoff rules format until ) } = @items; if ( $obs{rules} =~ /\d\d?:\d\d/ ) diff -ur dttz-0.6101/lib/DateTime/TimeZone.pm dttz-mod1/lib/DateTime/TimeZone.pm --- dttz-0.6101/lib/DateTime/TimeZone.pm2007-02-18 15:54:12.0 + +++ dttz-mod1/lib/DateTime/TimeZone.pm 2007-02-19 20:19:13.383139216 + @@ -6,10 +6,6 @@ $VERSION = '0.6101'; use DateTime::TimeZoneCatalog; -use DateTime::TimeZone::Floating; -use DateTime::TimeZone::Local; -use DateTime::TimeZone::OffsetOnly; -use DateTime::TimeZone::UTC; use Params::Validate qw( validate validate_pos SCALAR ARRAYREF BOOLEAN ); use constant INFINITY => 100 ** 1000 ; @@ -24,7 +20,8 @@ use constant IS_DST =&
nautical timezones for DT::TZ
Bonus patch: this adds handling of the nautical single-letter timezone names to DT::TZ::OffsetOnly and DT::TZ. Very simple feature, bound to be useful to someone. -zefram diff -ur dttz-mod1/lib/DateTime/TimeZone/OffsetOnly.pm dttz-mod2/lib/DateTime/TimeZone/OffsetOnly.pm --- dttz-mod1/lib/DateTime/TimeZone/OffsetOnly.pm 2007-02-18 15:54:12.0 + +++ dttz-mod2/lib/DateTime/TimeZone/OffsetOnly.pm 2007-02-19 22:13:36.809631560 + @@ -11,6 +11,14 @@ use DateTime::TimeZone::UTC; use Params::Validate qw( validate SCALAR ); +my %letter_offset = ( + A => +1, B => +2, C => +3, D => +4, E => +5, F => +6, + G => +7, H => +8, I => +9, K => +10, L => +11, M => +12, + N => -1, O => -2, P => -3, Q => -4, R => -5, S => -6, + T => -7, U => -8, V => -9, W => -10, X => -11, Y => -12, + Z => 0, +); + sub new { my $class = shift; @@ -18,7 +26,8 @@ } ); my $offset = -DateTime::TimeZone::offset_as_seconds( $p{offset} ); +$p{offset} =~ /\A[A-IK-Z]\z/ ? 3600 * $letter_offset{$p{offset}} : +DateTime::TimeZone::offset_as_seconds( $p{offset} ); die "Invalid offset: $p{offset}\n" unless defined $offset; @@ -100,9 +109,13 @@ =head2 DateTime::TimeZone::OffsetOnly->new ( offset => $offset ) -The value given to the offset parameter must be a string such as -"+0300". Strings will be converted into numbers by the -C function. +Three forms are accepted for the offset parameter. It may be an offset in +hours, minutes, and optional seconds, each two digits, with no separators +and optional leading sign, for example "+0300". It may be an offset in +hours (one or two digits), minutes (two digits), and optional seconds +(two digits), with ":" separators and optional leading sign, for example +"-1:01:06". Or it may be a single capital letter other than "J", in +which case it is interpreted as a nautical timezone name. =head2 $tz->offset_for_datetime( $datetime ) diff -ur dttz-mod1/lib/DateTime/TimeZone.pm dttz-mod2/lib/DateTime/TimeZone.pm --- dttz-mod1/lib/DateTime/TimeZone.pm 2007-02-19 20:19:13.383139216 + +++ dttz-mod2/lib/DateTime/TimeZone.pm 2007-02-19 22:08:10.911550810 + @@ -95,7 +95,8 @@ require DateTime::TimeZone::Tzfile; return DateTime::TimeZone::Tzfile->new( $filename ); } -elsif ( $name =~ /\A[-+]?(?:\d\d?:\d\d(?::\d\d)?|\d{4}(?:\d\d)?)\z/ ) +elsif ( $name =~ /\A(?:[-+]?(?:\d\d?:\d\d(?::\d\d)?|\d{4}(?:\d\d)?)| + [A-IK-Z])\z/x ) { require DateTime::TimeZone::OffsetOnly; return DateTime::TimeZone::OffsetOnly->new( offset => $name ); @@ -606,6 +607,13 @@ =item * +If the name is a single capital letter, other than "J", it is treated as +a nautical timezone name, and a C object +is returned. (The case of "Z" is also handled by one of the rules above. +It means the same thing either way.) + +=item * + If the name is "floating", then a C object is returned. A floating time zone does have I offset, and is always the same time. This is
Re: revision of DT::TZ name parsing
Dave Rolsky wrote: >This is actually more bizarre then just having a leading colon, I think. As previously mentioned, a leading colon is no good for signalling syntax. If you want to go that route, pick some other leading character to signal a native filename. Bizarreness discussed below. >It might be preferable to require an actual file URI with scheme >(file:///etc/local/time or file://C:\foo\bar) I pondered doing something like this. With the leading "/", it would be easy to interpret the whole string as a URI path and translate that into local syntax. Both of the examples that I gave would come out the same. The disadvantage is that things like "/a%20b" then wouldn't act like Unix filenames on Unix. URI syntax has the major advantage of being already familiar to a great many users across all OSes. "file:///c:/foo/bar" gets done on Windows, for example. For this reason I think any form of "/"-delimited syntax is not hugely strange to Windows users. By the way, I just tried, and "/c:\foo\bar" does get translated to "c:\foo\bar" by the current code, so it turns out the user doesn't have to use "/" delimitation after all. As for using a complete URI with scheme name, I see three problems. The deep problem is that users will expect us to support downloading tzfiles from arbitrary URIs of any scheme, which is not the plan. The trivial problem is that URI scheme name syntax makes URIs clash with some of the syntaxes we already support, so we'd need some other flag character in front of the URI. Finally, you're talking about inventing a completely new facility here, whereas the "/"-prefixed Unix filename is an existing widely-supported $TZ syntax. I'd like to know if there's any precedent for timezone setting by filename on Mac or Windows. >I'd love to hear from the original requestor, but I'd guess that they'd >prefer to use the correct modern rules, as opposed to a to-the-POSIX-spec >interpretation. The POSIX spec doesn't say what DST rules apply when they're not explicitly stated in the timezone string. Any rules at all are POSIX conformant. For this reason people should not be relying on any particular behaviour from such strings, and should be giving a full rule. The Alaskan user should be using "AKST9AKDT,M3.2.0,M11.1.0" if ey wants to go the SysV route. So I really don't care which behaviour we provide in the unspecified case. I readily defer to your judgement concerning grandfathering of these special cases. >Honestly, supporting these POSIX time zones seems of academic interest or >useful for emulating some old system's behavior, but if you're writing new >code, it doesn't seem like a good idea at all, My objective in this is merely to support all $TZ settings that the various libcs do. System V strings are an important subcase. -zefram
Re: API for multiple time scales
I wrote: >http://www.fysh.org/~zefram/time/time_scale_expt Version 0.001 is up. This release does Martian time, including the timezones used by the rover missions. (Martian rotation is much easier to model than Terran, because Mars has no large moon, tectonics, or oceans, all of which make the Earth's rotation rather variable.) I also implemented Eugene's idea of time scales modelling Unix time with the discontinuities at leap seconds. I already had an interface for linear counts of seconds, so this just slots in. I also implemented the leading proposed calendar for Mars in the module Date::Darian::Mars, which is on CPAN. That should plug right into the experimental code. (I haven't actually tried it.) So I've now got parallel sets of day counts for Terra and Mars. There are some people already tracking time on Titan (and there's a Darian calendar for it), so there might already be a day count system there. Obviously we're going to get such systems on many many planets and moons. On some moons we'll want to count rotations relative to the planet, as well as (or instead of) rotations relative to Sol. There's also sidereal days to consider, which we have a canonical count for on Earth (Earth Rotation Angle). We use the 24:60:60 clock for subdivisions of all of these types of day (at least so far), although we handle the integer parts in completely different ways. I think some factoring is in order. -zefram
Re: Help pulling dst change dates from DateTime::TimeZone
Anthony R. J. Ball wrote: > I want to be able to grab the actual DST change dates for a timezone >and year. Some of what I'm doing would benefit from this too. I suggest an addition to the DT::TZ API: =head2 $tz->boundary_for_datetime($dt, $which) Given a C object, this method returns another C object, in the UTC timezone, which identifies a boundary between observances in this timezone. Within a single observance, the offset, short name, DST flag, and any other such attributes, remain constant. C<$which> specifies which boundary is to be returned. If 0, the start of the current observance; if +1, the end of the current observance; if -1, the start of the observance before the current one. The "current observance" is the one that is in effect at the time identified by C<$dt>. If there is a boundary exactly at C<$dt>, then the current observance is the one starting at that instance. If an observance stretches infinitely far into the past or future, C is returned for any non-existent boundary. I'll do a patch to implement this if no one objects. -zefram
Re: ANNOUNCE: DateTime::TimeZone 0.62
Dave Rolsky wrote: >- This release is based on version 2007c of the Olson database. Where do we stand regarding my proposed changes? Are you waiting for anything from me? -zefram
Re: Help pulling dst change dates from DateTime::TimeZone
Anthony R. J. Ball wrote: > It sounds like a reasonable solution, as long as plugging >the current end boundary +1 gives you the next boundary, so >you can easily work your way forward. That's the concept. You'd use it like: $dt = starting_point(); while(defined $dt) { print $dt->iso8601, " ", $tz->offset_for_datetime($dt), "\n"; $dt = $tz->boundary_for_datetime($dt, +1); } which walks forward, or change "+1" to "-1" (and possibly add an initial step with $which==0) to walk backward. >maybe not to a lot of people, but the data is there, so >why not make it available. Quite. -zefram
Re: Help pulling dst change dates from DateTime::TimeZone
Dave Rolsky wrote: >I'd prefer multiple methods to a third parameter. Different names provides >clarity. Who would know what a number means without looking in the docs? It's not meant to be used without reading the doc at least once. Once read, of course, the $which values follow a logical plan and so are memorable. If you want three names, how about prev_observance_start_for_datetime this_observance_start_for_datetime next_observance_start_for_datetime -zefram
Re: Help pulling dst change dates from DateTime::TimeZone
Anthony R. J. Ball wrote: > Are three even necessary? Not absolutely, but with two when you want to find the start of the current observance you'd have to use both methods and a date equality comparison. It'd be a pain, lots of people wouldn't bother doing it properly and you'd get code that fails if given a date that is exactly a boundary. The three method way puts the effort where it belongs: in the library, where it's actually easier to implement than the two methods. -zefram
Re: Help pulling dst change dates from DateTime::TimeZone
Jim Bacon wrote: >next_dst and prev_dst based on the year value of the DT object and a >parameter specifying if what is wanted is the spring or fall date, or at >least specifying change to daylight time or standard time. Please no, not such a restrictive model. That'd be a nightmare. Timezone offset changes are a lot more complicated than just a twice-yearly alternation between two possibilities. There are years with more than two changes, and years with only one change or no change at all. With the generic arrangement, where you get the next/previous observance boundary working from an arbitrary DT, if you happen to know that your timezone fits the twice-yearly-change pattern, you can do next from the start of the year or previous from the end of the year to find the two boundaries. -zefram
Re: Help pulling dst change dates from DateTime::TimeZone
Eugene van der Pijll wrote: >"Datetime" just means one point in time; it is not something that is >observed. Yes. An offset (plus short name and DST flag) is observed. The "_for_datetime" bit indicates the argument format, just like "offset_for_datetime". >What do you think of: "next_offset_transition"? Or even >"next_transition", as it is always called on a timezone object, and it >should be clear in that context what it is a transition of. The latter is better, because it's not just the offset that transitions. In some cases there is a transition without the offset changing, as for example when the UK changed from British Summer Time to British Standard Time, when the is_dst flag was the only thing that changed. But with the "_transition" naming pattern there's a problem for the names of the other two methods. Logically the "prev_transition" could be the start of the current or previous observance. And "this_transition" is meaningless. If you want to drop the "_for_datetime" bit then just go to "{prev,this,next}_observance_start": it is the observance, not the transition, that is the referent of "this" and the others. -zefram
Re: Help pulling dst change dates from DateTime::TimeZone
Jim Bacon wrote: >Yes, provide methods for finding any type of transition besides DST, but I >think DST might be the most common and should therefore have as many >shortcuts as needed to simplify its use. I'm not convinced that finding the DST change dates in a given Gregorian calendar year is going to be a particularly common usage. It seems more likely that one would want to know the next observance (or offset) change from the present, whether that's due to conventional DST or for any other reason. Anyway, here are my thoughts on non-general-case methods: I don't want to have to reimplement them all in each independent timezone class. Let's implement them generically, in terms of the general-case methods. They don't, of course, strictly need to be methods; they can perfectly well be ordinary functions in an independent module. (So you can have a module that looks up DST changes in a given Chinese lunar year, for example.) Anything that's of sufficiently wide use to justify being a method can go into a base class that all timezone classes inherit. Since DT::TZ contains the machinery for the parsed-Olson classes, I think it should not itself be the mandatory base class; better to institute a DT::TZ::base. I'm principally interested in the general-case methods. I think we ought to establish the general-case inteface first, and do the syntactic sugar later. We have arbitrarily long to add more sugar methods to the base class, but the underlying general methods form a contract between independent bits of code, so other work depends on them. -zefram
Re: Help pulling dst change dates from DateTime::TimeZone
Eugene van der Pijll wrote: >So: perhaps it would be better to create a single method, returning a >DateTime::Span object? And then make iterating methods that accept these >spans: That's a reasonable interface, if one can take DT::Span as ubiquitous. It's certainly convenient if one really does want the interval rather than the boundary. Arguably also makes the method names more understandable when dealing with the boundaries ($tz->observance($dt)->end, for example). I suggest the method name "observance_span" instead of "observance", to distinguish it from a hypothetical method that would return a reification of the observance itself (as Dave mooted elsewhere on this thread). Could also append "_for_datetime" if we want to fit in with the existing so-named methods. >Only problem is that DT::TimeZone would have a dependency on DT::Span >now. There's a circularity there: DT::Span's CPAN distribution depends on DT, which depends on DT::TZ. DT::TZ doesn't currently depend on DT. DT::Span also looks quite heavyweight. Brings in DT::Set, Set::Infinite, and DT::Duration, even if one is only using it to wrap a pair of endpoints. Not sounding like such a good idea now. Maybe we need a DT::Span::Lite. Another possibility: as the span-based interface is conceptually handy, there's the option to have a lightweight DT-based interface in each DT::TZ class, and put the heavy span-based interface in a base class, wrapping the lightweight one. -zefram
Re: Help pulling dst change dates from DateTime::TimeZone
Dave Rolsky wrote: >However, something with some of the same info seems like a natural thing >to return from these methods. So we'd have a DT::TZ::Observance class, with methods ->offset, ->short_name, ->is_dst, ->start_datetime, ->end_datetime. $tz->observance_for_datetime($dt) would return one. Re DT::Span (see other subthread), could have a ->span method that loads DT::Span in all its glory and returns one. Last-minute loading would avoid bringing in so much mechanism when it's not being used. Would have a distribution-time circular dependency issue though. Would DT::TZ::Observance have methods ->next and ->prev? Would make walking the chain easy. Raises questions of implementation strategy. There's a general question of whether to cache the observance objects, guarantee that the same ones are returned repeatedly, and so on. If we're going to go the heavyweight route, this is the way to go. -zefram
Re: Help pulling dst change dates from DateTime::TimeZone
Eugene van der Pijll wrote: >Or: instead of making observance_for_datetime a method in the standard >TZ distribution, make a separate distribution, with class >DT::TZ::Observance (or maybe somewhere in DT::Util? DT::Ev?). Yes, that's probably better for the heavyweight approach. Still need a lightweight version to go in the timezone classes themselves. Presumably we'll go for the lightest form then, just dealing with the transition instants. >DT::TZ would than have to implement just a single method to get at the >raw data; for example DT::TZ->get_transition( $dt ), which returns the >first transition after $dt, or the first transition if no $dt is passed. I definitely want a backward iterator. ->prev in DT::TZ::O will require it, of course. This comes back to the interface issues already discussed for the boundary-based interface. -zefram
Re: Help pulling dst change dates from DateTime::TimeZone
Dave Rolsky wrote: >Constants and magic values suck, names rule, d00d ;) It's not a magic constant. It's the index of the target observance, relative to the current one. I considered allowing it to take arbitrary values (e.g., 3 to look three observances ahead), but people would misuse that and end up iterating in O(n^2). Hence a limited-range index. With three differently-named methods, they'll actually end up being implemented in terms of the single method anyway, it'll just be hidden. I wouldn't let such a consideration alone dictate the nature of the public API, of course. But if we go the route of a separate heavyweight mechanism, with a very lightweight mechanism in the classes themselves, then there may be an advantage in keeping the interface (and unavoidable implementation structure) as small as possible. -zefram
Re: gmt<->cst off by an hour
Matthew wrote: >$dt->set_time_zone("US/Central"); > >print "+9weeks CST: " . $dt->epoch . " - " . $dt->datetime . "\n"; This is wrong. "US/Central" doesn't refer to CST specifically. It refers to the US central timezone *including DST switches*. The date it's showing is in CDT, not CST. Try displaying $dt->time_zone_short_name as well, which will show what's going on. >Many of these events were created before the DST switch. How should I be >calculating these event dates so that 4PM 2 weeks ago still shows as 4PM >tomorrow? Do the ->add with the timezone already set. Thus: #!/usr/bin/perl use DateTime; my $dt = DateTime->from_epoch(epoch => 1168812000, time_zone => 'GMT'); print "Date in GMT: " . $dt->epoch . " - " . $dt->datetime . " " . $dt->time_zone_short_name . "\n"; $dt->set_time_zone("US/Central"); print "Date in cen: " . $dt->epoch . " - " . $dt->datetime . " " . $dt->time_zone_short_name . "\n"; $dt->add(weeks => 9); print "+9weeks cen: " . $dt->epoch . " - " . $dt->datetime . " " . $dt->time_zone_short_name . "\n"; $dt->set_time_zone("GMT"); print "+9weeks GMT: " . $dt->epoch . " - " . $dt->datetime . " " . $dt->time_zone_short_name . "\n"; yields: Date in GMT: 1168812000 - 2007-01-14T22:00:00 UTC Date in cen: 1168812000 - 2007-01-14T16:00:00 CST +9weeks cen: 1174251600 - 2007-03-18T16:00:00 CDT +9weeks GMT: 1174251600 - 2007-03-18T21:00:00 UTC -zefram
Re: gmt<->cst off by an hour
Matthew wrote: >Thanks Zefram. To combat this issue in the future, should we be storing >our customer's event information in our DB in GMT and doing all >calculations using GMT? or store in their local TZ and calculate with >local TZ? That depends on what you need to do with the data. If you want to do date arithmetic that is affected by the customer's timezone then you definitely need to store which timezone that is. For any event information where it is only the absolute time that matters, I recommend storing in GMT. Perform calculations in GMT or local time depending on what type of calculation you intend to perform. >Our servers are all GMT if that makes any difference. This is wise. -zefram
Re: gmt<->cst off by an hour
Matthew wrote: >if not, add 1 week to event start. loop until current time is less than >new event start and return new event start. If you're doing this in the local timezone, it is better to add N weeks to the original event time (and increment N) than to add 1 week onto the previous event time. This minimises funny behaviour around DST changes. >But when you throw in the adding of weeks to an original start date, >should the orig start date be in local TZ or GMT? The customer will most likely want events occurring at, say, 11:00 every Monday in their local timezone. For that you need to do the date arithmetic in the timezone; the gaps between events will occasionally be 167 or 169 hours instead of the regular 168. Some customers might want events at 168-hour intervals regardless of timezone; you could cater to that by giving them the option to specify an event in GMT instead of their actual timezone. You can handle both cases, therefore, with just the local timezone logic. -zefram
Re: DateTime and TimeZone question
crap wrote: >For the life of me I cannot figure this out. I am trying to look up the >timezone based off an hour offset. Is there a way to do this with >DateTime::TimeZone? If you want a timezone that is just a fixed hour offset, then just do $tz = DateTime::TimeZone->new->new(name => "-0400"); That's a timezone that's permanently four hours behind UT. But I suspect that what you actually want is to put in "-0400" and get back one of the civil timezones, with DST rules, that happens to be at UT-4h currently. There are several of these, such as America/New_York and America/Cuiaba, so at best you'd expect to get a list of matching timezones. The timezones aren't indexed in this way, so you'd have to iterate through the lot checking each. DateTime::TimeZone->all_names provides the list that you'll need to check through. -zefram
Re: Parsing LDAP Generalized Time with DateTime::Format::ISO8601
Ulrich Zehl wrote: >Since I don't have access to the ISO standard, I cannot verify that the >format as given in RFC 4517 is really standards compliant, It's conditionally compliant. The relevant paragraph of the standard reads: # NOTE By mutual agreement of the partners in information interchange, # the character [T] may be omitted in applications where there is no # risk of confusing a date and time of day representation with others # defined in this International Standard. So an ISO 8601 parser shouldn't accept it by default. Where context dictates that a date-time representation is expected, it is unambiguous and so parsing it this way is acceptable. -zefram
Re: Confused: adding/subtracting hour from timestamp
Bas Schulte wrote: >print STDERR "Converted time from $hours:$minutes with offset=$offset >to " . $normalizedTs->strftime("%H:%S:00") . "\n"; %S is seconds, not minutes. You might prefer to use the format "%T", which is equivalent to "%H:%M:%S". -zefram
Re: DateTime::Event again
Simon Wistow wrote: >I've started sketching out DateTime::Event - a module that would >represent a single, err, event. ... >The problem we have here is that for one off events start and end are >definite points in time. For recurring events this merely represents the >earliest and latest instances of this event (which may both be >infinite). A "recurring event" is not a single event. It is a structured group of events. You should have distinct classes for single event and recurrence. Most of the methods you list are applicable to one class or the other, not both. -zefram
Re: DateTime::Event again
Simon Wistow wrote: > In every calendaring system I've come across a >recurring event and a single event are represented as the same thing >only with different properties. Bad OO design is very common. Especially, I have found, where dates and times are concerned. >A recurring event is a single entity - Yes, sure it is. It's worthy of being represented by a specific type of object. It's just that that's not the same type as a single event. >it is one thing and should only be stored one time. I did not intend otherwise. It is certainly useful (and essential in infinite cases) to represent a recurrence just as a single object, not reifying each occasion. Reifying a particular instance (as an event object) should be done only when attention turns to the particular. When the particular *is* interesting, though, one certainly does want an object referring to that instance and not to all the other occasions of recurrence. That's what your "recurrences" method is about. >Using your description, a one-off event could be described as a >structured group containing only one event. You could certainly have such a trivial recurrence. It's about as useful as a one-element array. >A recurring event can and will have all the same characteristics of a >single event It does not have a specific start time, which is possibly the most fundamental aspect of a single event. Treatment of characteristics such as attendees, which you listed, depends on your model of recurrence, but you indicated a model in which a recurrence has just default values: quite different semantics from the definitive values of a single event. But most of your characteristics have only trivial semantics in the event object context anyway: bad things to base your class hierarchy design on. >It might be that a RecurrentEvent could be a subclass of SingleEvent. That would indicate that a recurrent event is a single event, which is not true. >vice versa, That's closer to the mark, treating single events as trivial recurrences. It's like treating a character as a string of length one. Perl does the latter, but in general I think it's a bad strategy. >or both are subclasses of a GenericEvent object, Tricky to say what a GenericEvent actually represents in that case. >more of an implementation detail rather than a conceptual detail. On the contrary, it is of the most profound conceptual importance. -zefram
Re: Possible Issue with DateTime->now()?
Veripex, Inc. wrote: >DateTime::now() does not appear to be accurate for me. I used to methods to >prove this. The first method is creating a DateTime object using information >provided by localtime(). The second is using the DateTime::now() method. The >localtime method provides what I expected, the DateTime::now() method has an >incorrect hour for me. A DateTime object doesn't just represent a date and time of day, it also has an attached timezone. With DateTime->new you're giving it a date and time in your local timezone and not specifying a timezone, so it only knows the local time and that's all it can show you. DateTime->now, on the other hand, picks up the correct absolute time, but because you didn't specify a timezone it doesn't know how you want it displayed. It defaults to using the UTC timezone, and the hour that it shows you is the current UTC hour. You can see these timezone settings in your dumps of the DateTime objects. Neither of these timezone settings is what you want. You most likely want to use your local timezone in both cases. Try adding the parameters "time_zone => 'local'" in both constructor calls. -zefram
Re: REQ: Additional 'truncate' option
Dave Rolsky wrote: > $dt->truncate( to => 'week' )->subtract( days => 1 ); That doesn't do what was requested: if you start with a Sunday then it moves a week back rather than just going to the beginning of the day. But this will work: $dt->add( days => 1 )->truncate( to => 'week' )->subtract( days => 1 ); -zefram
Re: Patch for DateTime::Format::W3CDTF to respekt second fragment part
Julian Haupt wrote: >+if ($date =~ s/\.(\d+)$// ) >+{ >+ my $fraction = $1; >+ $p{'nanosecond'} = (1 / $fraction) * 10**9; >+} That inversion can't be right. Surely you mathematically want $p{'nanosecond'} = "0.$fraction" * 10**9; but actually the nanoseconds member is supposed to be an integer, and it would be better to avoid floating-point arithmetic entirely: $fraction = substr($fraction, 0, 9); $fraction .= "0" x (9 - length($fraction); $p{'nanosecond'} = 0 + $fraction; -zefram
Re: Daylight-Saving Causes Twin Arrival Pickle
Rick Measham wrote: >http://www.wral.com/news/local/story/2011296/ When Parliament was debating the introduction of DST in the UK, as a wartime measure in 1916, Lord Balfour (a member of the House of Lords, the upper chamber of Parliament), with the usual aristocratic concern for matters of inheritance, noted precisely this problem with it: Supposing some unfortunate lady was confined with twins and one child was born 10 minutes before 1 o'clock. ... The elder child would be registered as being born at 12.50, but the younger child's birth, ten minutes later, would be registered at 12.00. ... the time of birth of the two children would be reversed. ... Such an alteration might conceivably affect the property and titles in that House. We can only hope that times of birth are annotated with the timezone abbreviation where such ambiguity occurs. I rather suspect that it's not standard practice, though. My understanding (from a British nurse) is that hospital clocks are not especially accurate, so that they can't be relied upon for minute-level accuracy anyway. The birth times of me and my three siblings (all single births) were all recorded as exact multiples of five minutes, so I presume there's some rounding going on there, but I'm at a loss to determine whether the rounding performed was down or to nearest. There's not much concern for precise timing in evidence. -zefram
Re: Patch for DateTime::Format::W3CDTF to respekt second fragment part
Jonathan Leffler wrote: >Or, what happens if there are 10 digits after the decimal point. That's what the substr() is for. >Yeah, mostly academic, except I'm working towards a time type (not for >Perl per se) that extends down to picoseconds (and up to 10^12 years, >too). At least 105 bits, then. TAI64 covers nearly 10^12 years, of course, and the extension TAI64NA goes down to attoseconds in a 128-bit format. What's the concept behind your type? Personally I like to use bignum rational arithmetic, for unlimited resolution. Performance is atrocious with the Perl bignum libraries, unfortunately. -zefram
Re: subtracting one date from another
jagdish eashwar wrote: >$dur = $date1->delta_days($date2); This is correct as far as it goes. >print $dur->days,"\n"; ># This gives me - "4" Here the duration is being expressed in weeks plus days, and you're only looking at the days portion. $dur->weeks returns 4; the duration is 4 weeks plus 4 days. To get the duration expressed purely in days, do $dur->in_units("days"). -zefram
Re: adding days to date
jagdish eashwar wrote: >I came across some unexpected behaviour in datetime. In the following >script, I first define $date1. Then I set $day1 = $date1. Then I add 2 days >to $day1. Why does $date1 also get incremented? Because a DateTime object doesn't represent a date-and-time per se; it implements a variable that is typed to hold a date and time. Walkthrough: >my $date1 = DateTime->new(year => 2007, > month => 12, > day => 23); You create a date/time variable, initialised as holding the date 2007-12-23. You set $date1 to be a reference to that variable. >my $day1 = $date1; You copy the reference to the date/time variable from $date1 to $day1. Both of these Perl variables now refer to the same date/time variable. >$day1->add(days => 2); You reference the date/time variable (via $day1), and tell it to modify the date value that it holds by advancing it by two days. The date/time variable now holds the date 2007-12-25. >print "day1 = ",$day1,"\n"; # gives me 2007-12-25 correctly. You reference the date/time variable (via $day1), and ask it to display the date that it holds (2007-12-25). >print "date1 = ",$date1,"\n"; # why does $date1 also change to 2007-12-25? You reference the date/time variable (via $date1), and ask it again to display the date that it holds (2007-12-25). The stage that should have rung alarm bells for you is $day1->add(days => 2); where you're doing date arithmetic calling a method on an object and *ignoring its return value*. This method operates by having a side effect on the object. If, instead, DateTime objects actually represented dates and times per se, then there wouldn't be any of these side effects, and this step in the program (combined with the previous step) would instead be something like my $day1 = $date1->plus(days => 2); As it is, you need to create a second date/time variable, initialised by copying the value from the first one. So instead of my $day1 = $date1; do my $day1 = $date1->clone; Then the ->add call will side-effect this second date/time variable, the one referenced by $day1, and leave the original date/time variable, the one referenced by $date1, alone. -zefram
Re: ANNOUNCE: DateTime::TimeZone 0.70
Dave Rolsky wrote: > is one major change in this release, for the new Venezuelan time > zone. What, again? I thought he'd've learned the first time. -zefram
Re: New Module - DateTime::NaturalLanguage
Ken Irving wrote: > convert seconds into a "readable" format 344 => 5m44s > >This sounds similar to your module, except for being compact vs verbose. I think Convert::Age doesn't qualify as processing natural language. Its encoded format is actually the ISO 8601 duration format, although C::A doesn't document that aspect and doesn't explain its interpretation of the variable-size units. Anyway, the ISO 8601 format, although derived from English abbreviations, is meant to be language-neutral. Luke's module is definitively about English text, which is quite a different job. -zefram
Re: DateTime->season?
David E. Wheeler wrote: >return $date lt '03-21' ? 'winter' > : $date lt '06-21' ? 'spring' Northern hemisphere chauvinism. Aside from the hemisphere issue, the code is also wrong for tropical latitudes, where the four-season system doesn't apply. If you're trying to answer a user's question of "what season is it?" then you need a lot more flexibility. Even within the four-season system, people draw the boundaries in different places. That's inevitable when trying to impose sharp distinctions on a system that actually has a fuzzy continuum. >Since seasons can sometimes change on the 22nd instead of the 21st, >this isn't quite right. Sounds like you're looking for the equinox and solstice dates. I don't see any CPAN module providing this, on search.cpan.org. I guess that makes it your job to write one. Ideally you'd want to work from Astronomical Algorithms <http://www.willbell.com/math/mc1.htm>. Google for "equinox calculation" to find several lower-precision algorithms in various programming languages. -zefram
Re: Proposed module for the DateTime namespace
Frazer Irving wrote: >Second, I am planning make this module a subclass of DateTime::Span. Are >there any problems with this approach I may be unaware of? This seems silly. Your comparison functions will be most useful if they can be applied to DateTime::Span objects. As far as I can see your subclass isn't changing any behaviour of DateTime::Span, but is merely a vehicle to provide access to your new functions that are a layer on top of the existing behaviour. The overall effect of such subclassing is to prevent access to the new stuff in situations where it's applicable. I suggest that your comparison predicates should be either standalone functions (for which the module name "DateTime::Span::Compare" is an excellent choice) or additional methods in the DateTime::Span class. I think the former is the most sensible interface. -zefram
Re: CET timezone
Ton Voon wrote: >timezones, but DateTime doesn't support the timezone CET. Is there a >reason for it? The lettered abbreviations for timezones are generally ambiguous. Most famously, there's an "EST" in both America and Australia. I don't think there's any "CET" other than Central European Time, though. Generally these abbreviations are deprecated. CET is almost certainly not what you want, though. CET is a fixed offset of UT+1h. The civil time in west-central continental Europe is UT+1h during the winter and UT+2h (Central European Summer Time, CEST) during the summer. I'm not aware of any short name for this CET/CEST combination. CET is year-round civil time only in certain equatorial countries, such as Angola. > Is it better to specify a timezone based on a location, >such as Europe/Paris? Yes. These unambiguously refer to the civil time in a particular location. -zefram
Re: CET timezone
Ton Voon wrote: >server's timezone to CET. Dodgy concept there. It really doesn't make sense for a server as a whole to have a default timezone other than UT. A timezone choice is a feature of certain types of application data, not a feature of where you run the application. >I can understand the arguments about EST, but if there's no ambiguity >about CET, We just found an ambiguity about CET: does it include the DST rules? Also, consider that your form of CET, with European-rules DST, is only defined for 1977 and later (when the EU DST rules are defined), so it falls apart if you need to process earlier times. For those applications you're forced to distinguish between Europe/Paris, Europe/Berlin, and the others. Not to mention that countries went onto CET-with-DST at different times. If you have some definite idea about what "CET" means in your application context, go ahead and implement it. That might be an alias to Europe/Berlin, or a fixed offset from UT, or a synthetic timezone (with its own tzfile) that doesn't match civil time anywhere. But be aware that it's not universally meaningful, and do it at the application level without gumming up the implementation for everyone else. > I note that EST, MST >and HST are supported timezones: Historical oddities. Not role models. -zefram
Re: DateTime and Test::MockTime
Mark Pitchless wrote: >For some reason using DateTime->now doesn't get effected by using the >Test::MockTime module to change the time. It does if you load Test::MockTime before you load DateTime. $ perl -MDateTime -MTest::MockTime=:all -lwe 'print time;print DateTime->now;set_relative_time(6000);print time;print DateTime->now' 1219919095 2008-08-28T10:24:55 1219925095 2008-08-28T10:24:55 $ perl -MTest::MockTime=:all -MDateTime -lwe 'print time;print DateTime->now;set_relative_time(6000);print time;print DateTime->now' 1219919098 2008-08-28T10:24:58 1219925098 2008-08-28T12:04:58 $ -zefram
Re: Can someone try this to make sure I'm not mental?
Kristian Flint wrote: >This outputs "31-12-2008", which is in my mind is wrong. This is about timezones. Look at other fields of the DateTime: $ perl -lwe 'use Date::Manip; use DateTime::Format::DateManip; $date=ParseDate("1st January 2009"); print $date; my $dt = DateTime::Format::DateManip->parse_datetime($date); print $dt->dmy; print $dt->hms; print $dt->time_zone_long_name' 2009010100:00:00 31-12-2008 23:00:00 Europe/London $ This is what happens if your $TZ (or system default timezone) is Europe/London. You can change it: $ TZ=UTC perl -lwe 'use Date::Manip; use DateTime::Format::DateManip; $date=ParseDate("1st January 2009"); print $date; my $dt = DateTime::Format::DateManip->parse_datetime($date); print $dt->dmy; print $dt->hms; print $dt->time_zone_long_name' 2009010100:00:00 01-01-2009 00:00:00 UTC $ But it's more complicated than it looks, and downright weird in some cases: $ TZ=America/New_York perl -lwe 'use Date::Manip; use DateTime::Format::DateManip; $date=ParseDate("1st January 2009"); print $date; my $dt = DateTime::Format::DateManip->parse_datetime($date); print $dt->dmy; print $dt->hms; print $dt->time_zone_long_name' 2009010100:00:00 31-12-2008 23:00:00 America/New_York $ TZ=Australia/Sydney perl -lwe 'use Date::Manip; use DateTime::Format::DateManip; $date=ParseDate("1st January 2009"); print $date; my $dt = DateTime::Format::DateManip->parse_datetime($date); print $dt->dmy; print $dt->hms; print $dt->time_zone_long_name' 2009010100:00:00 01-01-2009 00:00:00 America/New_York $ What's happening is complicated. DateTime::Format::DateManip->parse_datetime looks up the abbreviation that the environmental timezone has now. Ultimately it tags the generated DateTime object with a timezone that it works out (backwards) from this abbreviation, which is why Australia/Sydney, with abbreviation "EST", gets mapped to America/New_York. There's one bug. The DateTime isn't created with that timezone to start with, though. It's initially created with a fixed-offset timezone, for an offset worked out (again backwards) from the timezone abbreviation. This offset is what determines the interpretation of the (zoneless) calendar time that you input. The DateTime then gets switched to its final timezone, retaining the same absolute point in time. If the timezone has a different offset now from what the current abbreviation suggested, this causes a change in how the point in time is expressed. Second bug here. Part of this is actually the fault of Date::Manip, which DateTime::Format::DateManip calls out to. For example, this is utterly the wrong timezone: $ TZ=Australia/Sydney perl -MDate::Manip=UnixDate -lwe 'print UnixDate("2009010100:00:00", "%Y-%m-%d %T %z %Z")' 2009-01-01 00:00:00 -0500 EST $ And here the offset and abbreviation are for the current time, not the time being displayed: $ TZ=Europe/London perl -MDate::Manip=UnixDate -lwe 'print UnixDate("2009010100:00:00", "%Y-%m-%d %T %z %Z")' 2009-01-01 00:00:00 +0100 BST $ DateTime::Format::DateManip shares some of the blame, though, for going through such complicated gyrations with timezones. Using the two timezones and shifting between them is a definite bug. It looks like it would work correctly if it just told DateTime to use the local timezone and didn't ask Date::Manip about timezones at all. >I suppose I should go look at the internals and submit a patch? Go patch DT::F::DM, yes. Date::Manip seems to be beyond help. -zefram
Re: adding a time to a DT object
Perrin Harkins wrote: >I tried making a Strptime object with pattern '%I %p' but that seems >to just return undef when I try to parse these times. %I only does the hour. You'd need "%I:%M %p" to parse the string you gave. If the input is from a human, though, DT::F::Natural might be a better choice: you don't have to tell it what the format is. > It looks like >maybe I want a DateTime::Incomplete, You could use one to represent the time-of-day on its own, and that class then provides a method to merge it with the date to make a complete DateTime. You don't win much from this. I think it's only useful if the parts you're merging don't always have the same boundary. Say, if you sometimes want to include the day-of-month in your time-of-day string. > but it's not clear how to make >one from a string. Yes. DT::F::Strptime is logically an appropriate tool for this, but it doesn't actually provide output in DT::Incomplete form. Likewise DT::F::Natural. >And it also looks like maybe I want a >DateTime::Duration since I want to add it to my DT object, No. That would be appropriate if you were starting from a base time and adding on a duration (such as 10 hours and 30 minutes). That's not what you're doing. You're constructing the representation of a point in time by taking parts of that representation from different places. It's a piecewise construction, not an addition of complete entities. >I ended up parsing the string myself and calling set methods on the >DT, but that seems pretty lame with all of these classes available. It's not a bad way, especially if the string format is fixed. With DT::F::Strptime doing its bit, you still need to use the set methods to copy the time-of-day from one DT object to another (since DT::Incomplete isn't doing that for you). -zefram
Re: I'd tell you how long it'll take for my hair to fall out but I'm struggling with duration!
Kristian Flint wrote: >definitely a fixed number of seconds in a day Leap seconds. DateTime doesn't really do them correctly -- actually its time scale is a bit schizophrenic at the sub-second level -- but it does represent leap seconds that it knows about. So some days, about one in 500, have 86401 seconds. > (actually unless we're >talking about that tiny fraction that ends up counting towards a quarter >of a day per year?). No. That's a leap day occuring roughly every four years, which means that there isn't a fixed number of days per year. >This doesn't actually return what's stated above (#) but actually >returns >0 years, 41 months, 1 days, 00 hours, 375 minutes, 45 seconds Hmm, yes. DateTime::Duration is normalising to that form. DT::F::Duration is only showing what it gets from DT::Duration. Looks like DT::F::Duration is trying to normalise the other way, back to what you input, but that's going wrong somewhere. >And if I try and make the pattern => '%e' to just get the number of >days, this returns 0! Returns 1 for me. -zefram
leap seconds in DateTime
"floating" timezone. So, anyway, most users don't need precise leap second handling. Many, presumably, do need (approximate) calculations on times in the future and before 1972. It is sensible for them that vague-regular-UT is used in those eras. But they'd be better served by a *consistent* vague-regular-UT model. No one is well served by the mixed model: it's vague *ir*regular UT, not guaranteeing any of the useful things that its component models do. DateTime tries to be everything to everyone, and suffers from the resulting contradictions. (Yes, I'm a pedant.) -zefram
Re: leap seconds in DateTime
Monty, James T wrote: >Uh-oh, I don't get the same results with DateTime 0.4304 and ActivePerl >5.8.8 on Windows XP: In the changelog: |0.162003-08-06 | |[ IMPROVEMENTS ] | |- The XS code now implements leap second-related calculations. | However, this is only used on platforms where we can find a usable | finite() or isfinite() function/macro, so it isn't used on Win32. Looks like the XS picks up the leap second table from leaptab.txt, but the pure Perl needs to be edited manually and now isn't being tested by users who have XS functionality. -zefram
Re: America/Sao_Paolo timezone dying for 2008-10-19
Kevin M. Goess wrote: >perl -Ilib -MDateTime -MDateTime::TimeZone -e 'DateTime->new(time_zone >=> "America/Sao_Paulo", year => 2008, month => 10, day => 12)' >Invalid local time for date in time zone: America/Sao_Paulo Midnight on that date doesn't exist in that timezone, because that's when DST goes into effect and so the clocks jump ahead to 01:00. >Upgrading to the very latest version of DateTime::TimeZone (released >yesterday) shows that the 12th now works, but the library fails on 19th >of October: Politicians, eh. They keep changing DST rules at the last minute. >Suggested fixes or workarounds? Depends what you're doing with the DateTime. Maybe you'd be better off using the UTC timezone, where there are no DST switches to screw things up. Or possibly the floating timezone, if you can't actually do your calculation in UTC. If you really need Sao Paulo time, because either you need to convert between that and something else or you need to see the DST effects, construct the DateTime with hour=>12, because no one switches DST at noon. This problem, of course, is why *almost* no one switches DST exactly at midnight. -zefram
Re: How to Compute Hours In a Day?
[EMAIL PROTECTED] wrote: >How do I compute the number of hours in a day in a specific time zone? Try this: use DateTime; for(my $today = DateTime->new(year=>2007, time_zone=>$ARGV[0]); $today->year == 2007; ) { (my $tomorrow = $today->clone)->add(days=>1); print $today, " ", ($tomorrow->epoch - $today->epoch)/3600, "\n"; $today = $tomorrow; } It ought to be possible to do the interval calculation using DateTime::Duration instead of ->epoch, but the behaviour of DT::D is unreasonably confusing and I couldn't get it to work. (Strangely, I got a version that worked fine for America/New_York, where all the days are integer numbers of hours, but lost the fractional hour of 2007-12-09 in America/Caracas, which was 24.5 hours long.) Beware that the above code assumes that midnight exists every day. We recently had a thread <http://www.nntp.perl.org/group/perl.datetime/2008/10/msg7086.html> about midnight not existing in some timezones, specifically America/Sao_Paulo. -zefram
Re: How to Compute Hours In a Day?
[EMAIL PROTECTED] wrote: > C:\>perl oddhours.pl 2007 > 2007-12-09 24.5 America/Caracas > 2007-03-11 22 America/Indiana/Winamac > 2007-03-25 24.5 Australia/Lord_Howe > 2007-10-28 23.5 Australia/Lord_Howe Interesting, Australia/Lord_Howe does a half-hour DST shift every year. > 1961-01-01 23.74583 Africa/Dar_es_Salaam That's the switch from an unaligned +02:44:45 to the regular +03:00. Curiously, it went to +02:44:45 *from* +03:00 earlier, in 1948, and before that (until 1931) it had used +02:37:08. Strong odour of politics. > C:\>perl oddhours.pl 1967 > Invalid local time for date in time zone: Africa/Casablanca Wow, someone *does* switch at noon. Or did, once. A quick look at the tzdata files shows a handful of other noon switches, all one-offs. I think you're going to have to give up the idea of using a fixed local time each day as your reference point. You need a function that finds the earliest point that lies within a given calendar date in local time, which will usually (but not always) be labelled 00:00. It's probably safer to work in UTC and convert to local, rather than work with local time-of-day directly, to avoid trouble with ambiguous times of day (there might be two instances of local 00:00 in one day). This is still assuming that the extent of each local calendar day is contiguous. If the clocks go back an hour at 00:30 local time, it would break your model. The Alaskan zones stretch the model to the limit, having in 1867 a jump back by 24 hours at 24:00 local time, yielding a 48-hour day. (Subjectively it was treated as two consecutive Fridays, which would have had the same calendar date were it not for the simultaneous switch from the Julian calendar to the Gregorian calendar.) There are also some Pacific islands that have jumped across the IDL in the other direction, skipping a calendar date altogether. Anyway, have a go with this function: sub day_start() { my($zone, $y, $m, $d) = @_; my $p = DateTime->new(time_zone=>"UTC", year=>$y, month=>$m, day=>$d, hour=>12); (my $rd) = $p->utc_rd_values; while(do { (my $l = $p->clone)->set_time_zone($zone); [$l->local_rd_values]->[0] } >= $rd) { $p->subtract(hours=>1); } while(do { (my $l = $p->clone)->set_time_zone($zone); [$l->local_rd_values]->[0] } < $rd) { $p->add(hours=>1); } my $q; while(1) { ($q = $p->clone)->subtract(minutes=>1); last if do { (my $l = $q->clone)->set_time_zone($zone); [$l->local_rd_values]->[0] } < $rd; $p = $q; } while(1) { ($q = $p->clone)->subtract(seconds=>1); last if do { (my $l = $q->clone)->set_time_zone($zone); [$l->local_rd_values]->[0] } < $rd; $p = $q; } return $p; } -zefram
Re: Getting a named DateTime::TimeZone from an offset
Randy J. Ray wrote: >I get a the timezone as a DateTime::TimeZone::OffsetOnly object. But I'd really >like the "real" timezone, the one I can get a name or a short-name for. You can't. They're hopelessly ambiguous. -zefram
Re: DateTime performance
arie.ha...@gmail.com wrote: >Our project requres getting time-zone offset for the given time-zone >id at the current time. You can speed things up a bit by using the timezone modules in isolation. You can construct a fake DateTime class, which only provides the methods ->utc_rd_as_seconds and ->utc_year. Use that class to construct an object representing the current time. Then call ->offset_for_datetime on a timezone object, passing in your fake DateTime. -zefram
DT::Locale signature breakage
There is a bug in Module::Signature which is causing false signature verification failures for DateTime::Locale. The bug is that it attempts to canonicalise line endings of text files for checksumming, but it does so in a way that doesn't work on perl 5.6. The practical upshot is that if you have \r\n line endings then a signature generated with perl 5.8+ will fail to verify on perl 5.6. All the XML files in tools/t/test-data have \r\n line endings, and so suffer this problem. There's an easy workaround: don't use \r\n. If all the files are changed to use \n, like the rest of the distribution, then checksums will be computed consistently. Of course, the principle of signing something other than what's actually distributed is a stupid idea that opens up security holes. I have mentioned this to the M::S author, along with the inconsistent-canonicalisation bug. -zefram