Re: Olson querying

2012-05-08 Thread Randal L. Schwartz
 Rick == Rick Measham r...@measham.id.au writes:

Rick $ olson time 13:48   # where is it currently 13:44?
Rick $ olson time 13:48 -Cau  # where in Australia is it currently 13:44

Does it offset by 4 minutes automatically?

:-)

-- 
Randal L. Schwartz - Stonehenge Consulting Services, Inc. - +1 503 777 0095
mer...@stonehenge.com URL:http://www.stonehenge.com/merlyn/
Smalltalk/Perl/Unix consulting, Technical writing, Comedy, etc. etc.
See http://methodsandmessages.posterous.com/ for Smalltalk discussion


Re: Olson querying

2012-05-08 Thread Rick Measham
Magic!

Cheers!
Rick Measham


On 09/05/2012, at 6:38, mer...@stonehenge.com (Randal L. Schwartz) wrote:

 Rick == Rick Measham r...@measham.id.au writes:
 
 Rick $ olson time 13:48   # where is it currently 13:44?
 Rick $ olson time 13:48 -Cau  # where in Australia is it currently 13:44
 
 Does it offset by 4 minutes automatically?
 
 :-)
 
 -- 
 Randal L. Schwartz - Stonehenge Consulting Services, Inc. - +1 503 777 0095
 mer...@stonehenge.com URL:http://www.stonehenge.com/merlyn/
 Smalltalk/Perl/Unix consulting, Technical writing, Comedy, etc. etc.
 See http://methodsandmessages.posterous.com/ for Smalltalk discussion
 -- 
 Message  protected for iSite by MailGuard: e-mail anti-virus, anti-spam and 
 content filtering.http://www.mailguard.com.au
 Click here to report this message as spam:
 https://login.mailguard.com.au/report/1EHdSoFRAS/5NsrA9R5r7L6i9em677WM1/0
 
-- 
Message  protected for iSite by MailGuard: e-mail anti-virus, anti-spam and 
content filtering.http://www.mailguard.com.au



Re: Olson querying

2012-03-06 Thread Zefram
Anthony Ball wrote:
a way to query when the DST changes happen.

That'll need additions to the API for the timezone objects.  I've got
some plans to do that, but it's a later stage.

-zefram


Re: Olson querying

2012-03-05 Thread Zefram
Dave Rolsky wrote:
The use of Date::ISO8601, Date::JD, and Time::Unix seems a bit odd.
Can't you use DateTime to do all this stuff and avoid the additional
prereqs?

Using DateTime would gain minimal convenience.  On the downside, it's a
heavy module load (both in memory and startup time) and a big dep tree.
It's nearly even a circular dep: it requires DT:TZ, so stuff under DT:TZ
had best not require DateTime.  The prospective App::olson isn't actually
a dep of (any version of) DT:TZ, but is closely allied with DT:TZ:Olson.

Date::ISO8601 and Date::JD are already used by DT:TZ:Tzfile and
DT:TZ:SystemV.  Date::ISO8601 is light, and certainly pulls its weight.
Date::JD is a bit heavy for what it achieves, due to eager generation
of hundreds of subs; it should probably be autoloading.  I wouldn't
mind replacing the minimal use of Date::JD in DT:TZ:{Tzfile,SystemV}
and App::olson with a literal constant.  Time::Unix is surprisingly large
for what it does, but still small overall, and unproblematic as a dep.

 We can safely assume that anyone installing
DateTime::TimeZone has DateTime, I think.

Has it available, sure, but better not to force its use, because of the
heaviness and (in many applications) abstraction inversion of doing so.
For what it's worth, I use DT:TZ in handful of places, but I usually
use it with cheap fake DateTime objects, as seen in the test suites for
DT:TZ:{Tzfile,SystemV}.  I've never needed DateTime's arithmetic or other
facilities; I only need a DateTime-alike as a container for RD values to
query timezone objects.  In fact, the one place where I do use DateTime
is only using it that way, predates me developing the cheaper substitute,
and will be switched when I get round to it.

So I'm inclined to keep DT:TZ and allied code free of any real dependency
on DateTime.

-zefram


Re: Olson querying

2012-03-05 Thread Zefram
New version of the query tool attached.  This one has a lot more options
for searching for zones.  It lets you ask questions like:

$ olson areas -Cru # where is Russia?
Asia
Europe

$ olson offsets -ICST # what does CST mean?
-06
-05
+08
+09:30
+10:30

$ olson zones -Cau -IEST # which zone might EST be in Australia?
Australia/Brisbane
Australia/Currie
Australia/Hobart
Australia/Lindeman
Australia/Melbourne
Australia/Sydney

I've got a todo list with a bunch more features that it ought to
support searching on, but I think I'm going to handle them by a radical
refactoring that yields more of a query language than this collection
of options.

-zefram
#!perl

{ use 5.006; }
use warnings;
use strict;

use Date::ISO8601 0.000 qw(present_ymd);
use DateTime::TimeZone::Olson ();
use DateTime::TimeZone::SystemV ();
use DateTime::TimeZone::Tzfile ();
use Getopt::Std qw(getopts);
use Params::Classify qw(is_string);
use Time::OlsonTZ::Data ();
use Time::Unix qw(time);

our $VERSION = 0.000;

my $rdn_epoch_cjdn = 1721425;

my %command;

$command{version} = sub () {
getopts(, {}) or die bad options\n;
die bad arguments\n if @ARGV;
print modules:\nApp::olson $VERSION\n;
foreach my $mod (qw(
DateTime::TimeZone::Olson
DateTime::TimeZone::SystemV
DateTime::TimeZone::Tzfile
Time::OlsonTZ::Data
)) {
no strict refs;
print $mod ${qq(${mod}::VERSION)}\n;
}
print Olson database: @{[DateTime::TimeZone::Olson::olson_version]}\n;
};

{
package FakeUtcDateTime;
sub new {
my($class, $rdns) = @_;
return bless({ rdn = $rdns-[0], sod = $rdns-[1] }, $class);
}
sub utc_rd_values { ($_[0]-{rdn}, $_[0]-{sod}, 0) }
}

{
package FakeLocalDateTime;
sub new {
my($class, $rdns) = @_;
return bless({ rdn = $rdns-[0], sod = $rdns-[1] }, $class);
}
sub local_rd_values { ($_[0]-{rdn}, $_[0]-{sod}, 0) }
}

sub handle_exception($$) {
my($val, $err) = @_;
if($err =~ /\A
time\ [-:TZ0-9]+\ is\ not\ represented\ in\ the\ [!-~]+
\ timezone\ due\ to\ (zone\ disuse|)\b
/x) {
return $1 eq zone disuse ? ! : ?;
} elsif($err ne ) {
return *;
} else {
return $val;
}
}

sub is_exception($) {
return is_string($_[0])  $_[0] =~ /\A[!?*]\z/;
}

sub rdns_offset($$) {
my($rdns, $offset) = @_;
return $rdns if is_exception($rdns);
return $offset if is_exception($offset);
my($rdn, $sod) = @$rdns;
$sod += $offset;
use integer;
my $doff = $sod  0 ? -((86399-$sod) / 86400) : $sod / 86400;
$rdn += $doff;
$sod -= 86400*$doff;
return [$rdn, $sod];
}

sub present_rdns($) {
my($rdns) = @_;
return $rdns x 19 if is_exception($rdns);
my($rdn, $sod) = @$rdns;
use integer;
return present_ymd($rdn + $rdn_epoch_cjdn).
T.sprintf(%02d:%02d:%02d, $sod/3600, $sod/60%60, $sod%60);
}

sub now_utc_dt() {
my $now_unixtime = time;
my $now_utc_rdn = 719163 + int($now_unixtime/86400);
my $now_utc_sod = $now_unixtime % 86400;
return FakeUtcDateTime-new([$now_utc_rdn, $now_utc_sod]);
}

my $current_utc_dt = now_utc_dt();

sub utc_to_local_dt($$) {
my($utcdt, $offset) = @_;
return $utcdt if is_exception($utcdt);
return $offset if is_exception($offset);
return FakeLocalDateTime-new(
rdns_offset([$utcdt-utc_rd_values], $offset));
}

sub local_to_utc_dt($$) {
my($lcldt, $offset) = @_;
return $lcldt if is_exception($lcldt);
return $offset if is_exception($offset);
return FakeUtcDateTime-new(
rdns_offset([$lcldt-utc_rd_values], -$offset));
}

sub present_utc_dt($) {
my($dt) = @_;
return present_rdns(is_exception($dt) ? $dt : [$dt-utc_rd_values]).Z;
}

sub present_local_dt($) {
my($dt) = @_;
return present_rdns(is_exception($dt) ? $dt : [$dt-local_rd_values]);
}

sub present_offset($) {
my($offset) = @_;
return $offset x 3 if is_exception($offset);
my $sign = $offset  0 ? - : +;
$offset = abs($offset);
use integer;
my $disp = sprintf(%s%02d:%02d:%02d, $sign, $offset/3600, 
$offset/60%60, $offset%60);
$disp =~ s/(?::00)+\z//;
return $disp;
}

sub present_initialism($) {
my($initialism) = @_;
return is_exception($initialism) ? $initialism x 3 : $initialism;
}

sub present_isdst($) {
my($isdst) = @_;
return is_exception($isdst) ? $isdst : $isdst ? + : -;
}

{ my $areas; sub areas() { $areas ||= do {
my %areas;
foreach my $country (
 

Re: Olson querying

2012-03-05 Thread Rick Measham

Nice utility.

I wouldn't mind something like this too:

$ olson time 13:48   # where is it currently 13:44?
$ olson time 13:48 -Cau  # where in Australia is it currently 13:44
Australia/Currie
Australia/Hobart
Australia/Lindeman
Australia/Melbourne
Australia/Sydney

Feels like a useful way to offer a limited number of zones to a customer 
when you know their localtime (eg. in a web interface)


Cheers!
Rick Measham


On 6/03/2012 9:21 AM, Zefram wrote:

New version of the query tool attached.  This one has a lot more options
for searching for zones.  It lets you ask questions like:

 $ olson areas -Cru # where is Russia?
 Asia
 Europe

 $ olson offsets -ICST # what does CST mean?
 -06
 -05
 +08
 +09:30
 +10:30

 $ olson zones -Cau -IEST # which zone might EST be in Australia?
 Australia/Brisbane
 Australia/Currie
 Australia/Hobart
 Australia/Lindeman
 Australia/Melbourne
 Australia/Sydney

I've got a todo list with a bunch more features that it ought to
support searching on, but I think I'm going to handle them by a radical
refactoring that yields more of a query language than this collection
of options.

-zefram




smime.p7s
Description: S/MIME Cryptographic Signature


Olson querying

2012-03-04 Thread Zefram
As part of the plan for replacing DT:TZ, we discussed the need for a way
to list the available timezones, to replace the static DT:TZ:Catalog
document.  Attached is a prototype of a command-line tool that could
take this role.  I'd appreciate comments about its current operation
and about what it ought to additionally support.

-zefram
#!perl

{ use 5.006; }
use warnings;
use strict;

use Date::ISO8601 0.000 qw(present_ymd);
use Date::JD 0.005 qw(rdn_to_cjdnn);
use DateTime::TimeZone::Olson ();
use Getopt::Std qw(getopts);
use Params::Classify qw(is_string);
use Time::OlsonTZ::Data ();
use Time::Unix qw(time);

our $VERSION = 0.000;

my %command;

$command{version} = sub () {
getopts(, {}) or die bad options\n;
die bad arguments\n if @ARGV;
print modules:\nApp::olson $VERSION\n;
foreach my $mod (qw(DateTime::TimeZone::Olson Time::OlsonTZ::Data)) {
no strict refs;
print $mod ${qq(${mod}::VERSION)}\n;
}
print Olson database: @{[DateTime::TimeZone::Olson::olson_version]}\n;
};

{
package FakeUtcDateTime;
sub new {
my($class, $rdns) = @_;
return bless({ rdn = $rdns-[0], sod = $rdns-[1] }, $class);
}
sub utc_rd_values { ($_[0]-{rdn}, $_[0]-{sod}, 0) }
}

{
package FakeLocalDateTime;
sub new {
my($class, $rdns) = @_;
return bless({ rdn = $rdns-[0], sod = $rdns-[1] }, $class);
}
sub local_rd_values { ($_[0]-{rdn}, $_[0]-{sod}, 0) }
}

sub handle_exception($$) {
my($val, $err) = @_;
if($err =~ /\A
time\ [-:TZ0-9]+\ is\ not\ represented\ in\ the\ [!-~]+
\ timezone\ due\ to\ (zone\ disuse|)\b
/x) {
return $1 eq zone disuse ? ! : ?;
} elsif($err ne ) {
return *;
} else {
return $val;
}
}

sub is_exception($) {
return is_string($_[0])  $_[0] =~ /\A[!?*]\z/;
}

sub rdns_offset($$) {
my($rdns, $offset) = @_;
return $rdns if is_exception($rdns);
return $offset if is_exception($offset);
my($rdn, $sod) = @$rdns;
$sod += $offset;
use integer;
my $doff = $sod  0 ? -((86399-$sod) / 86400) : $sod / 86400;
$rdn += $doff;
$sod -= 86400*$doff;
return [$rdn, $sod];
}

sub present_rdns($) {
my($rdns) = @_;
return $rdns x 19 if is_exception($rdns);
my($rdn, $sod) = @$rdns;
use integer;
return present_ymd(rdn_to_cjdnn($rdn)).
T.sprintf(%02d:%02d:%02d, $sod/3600, $sod/60%60, $sod%60);
}

sub now_utc_dt() {
my $now_unixtime = time;
my $now_utc_rdn = 719163 + int($now_unixtime/86400);
my $now_utc_sod = $now_unixtime % 86400;
return FakeUtcDateTime-new([$now_utc_rdn, $now_utc_sod]);
}

sub utc_to_local_dt($$) {
my($utcdt, $offset) = @_;
return $utcdt if is_exception($utcdt);
return $offset if is_exception($offset);
return FakeLocalDateTime-new(
rdns_offset([$utcdt-utc_rd_values], $offset));
}

sub local_to_utc_dt($$) {
my($lcldt, $offset) = @_;
return $lcldt if is_exception($lcldt);
return $offset if is_exception($offset);
return FakeUtcDateTime-new(
rdns_offset([$lcldt-utc_rd_values], -$offset));
}

sub present_utc_dt($) {
my($dt) = @_;
return present_rdns(is_exception($dt) ? $dt : [$dt-utc_rd_values]).Z;
}

sub present_local_dt($) {
my($dt) = @_;
return present_rdns(is_exception($dt) ? $dt : [$dt-local_rd_values]);
}

sub present_offset($) {
my($offset) = @_;
return sprintf(%-9s, $offset x 3) if is_exception($offset);
my $sign = $offset  0 ? - : +;
$offset = abs($offset);
use integer;
my $disp = sprintf(%s%02d:%02d:%02d, $sign, $offset/3600, 
$offset/60%60, $offset%60);
$disp =~ s/(?::00)+\z//;
return sprintf(%-9s, $disp);
}

sub present_abbreviation($) {
my($abbrev) = @_;
return sprintf(%-6s, is_exception($abbrev) ? $abbrev x 3 : $abbrev);
}

sub present_isdst($) {
my($isdst) = @_;
return is_exception($isdst) ? $isdst : $isdst ? + : -;
}

{ my $continents; sub continents() { $continents ||= do {
my %continents;
foreach my $country (
values %{DateTime::TimeZone::Olson::olson_country_selection()}
) {
foreach my $region (values %{$country-{regions}}) {
$continents{$1} = undef
if $region-{timezone_name} =~ m#\A([^/]+)/#;
}
}
\%continents;
} } }

$command{zones} = sub () {
my %opts;
getopts(C:N:tado, \%opts) or die bad options\n;
die bad arguments\n if @ARGV;
my @match;
if(exists $opts{C}) {
my %conts = map { 

Re: Olson querying

2012-03-04 Thread Dave Rolsky

On Sun, 4 Mar 2012, Zefram wrote:


As part of the plan for replacing DT:TZ, we discussed the need for a way
to list the available timezones, to replace the static DT:TZ:Catalog
document.  Attached is a prototype of a command-line tool that could
take this role.  I'd appreciate comments about its current operation
and about what it ought to additionally support.


The use of Date::ISO8601, Date::JD, and Time::Unix seems a bit odd. Can't 
you use DateTime to do all this stuff and avoid the additional prereqs? We 
can safely assume that anyone installing DateTime::TimeZone has DateTime, 
I think.



-dave

/*
http://VegGuide.org   http://blog.urth.org
Your guide to all that's veg  House Absolute(ly Pointless)
*/