Looking for World Time Application


Forum: Apps
Topic: Looking for World Time Application
started by: Juanito

Posted by Juanito on Sep. 23 2007,11:40
I'm looking for an application that displays the time in several locations - preferably analogue clocks that show the time in London, New York, Toyko, etc - that I can make into a mydsl extension.

So far, I've come across gworldtime but that requires gtk+2.0.

Does anybody know of a suitable application that uses gtk+1.2 or other base dsl libs? Could torsmo be used for this purpose?

Posted by mikshaw on Sep. 23 2007,13:04
It could be made very easily with murgaLua.
I just woke up, so I'm in no condition to do it or show how to do it at the moment, but it probably shouldn't take more than a few minutes to put something like that together.

Of course it would depend on whether or not you want it to actively retreive the time from a server (probably need additional software?), or just set an offset for each clock using your system time.

Posted by Juanito on Sep. 23 2007,13:53
It'd take me more than a few minutes to put something together :)

There's already a timeserver script in dsl (somewhere), but in my case an offset from the local time would probably be best as my time zone (GMT+4) is not in the dsl subset of time zones.

Posted by WDef on Sep. 23 2007,14:44
More perl practice.  You could call something like this and display its output in torsmo:

Code Sample
#!/usr/bin/perl

# Useage : citytime.pl somecity

use strict;
use warnings;

my $URL = "http://www.timeanddate.com/worldclock/";

#================================

my $city = shift;
my $download = "/tmp/times.html";

if (!$city) {die "No city specified"};

print "Downloading time from $URL\n"; # legal

system("wget -O $download $URL &>/dev/null");

open(CONT, $download) or die("Could not open $download");

while (<CONT>){
if (/$city.+?(\d{1,2}\:\d+\d+ (AM|PM))/i) { print "$city $1\n"};
}


NB: there is a notice in the TimeAndDate html source saying that programs that download content "transparent to the user" are forbidden.  Hence the output informing of the download in the above.

But if there's any call for it, this could be adapted to pull time off some other page not having restrictions.

EDIT: added argument check.

Posted by Juanito on Sep. 23 2007,15:04
Code Sample
$ /opt/citytime.pl tokyo
Downloading time from http://www.timeanddate.com/worldclock/
tokyo 12:30 AM


Impressive - and to have it in 24:00 format?

Posted by WDef on Sep. 23 2007,15:29
Some more perl could convert to 24 hr format (might try it), but it might be lazier to  call the system's date command from within perl to convert times.

There's  zdump, if you know the desired timezone, eg EST:

Code Sample
$ zdump EST


but this seems to be giving wrong answers on dsl.   Locale issues?

Posted by WDef on Sep. 23 2007,16:11
With 24-hr output and taking multiple city arguments:

EDIT: added  -f option to access extended listing of city times, useage -h

EDIT2&3:  now outputs 5-char time in justified columns for tidy display.  Set width with option -w

EDIT4:  Web source is www.whatisthetime.com.  -f switch has no effect for this.

Code Sample
#!/usr/bin/perl

# Use -h for useage
# 24-hour, multi arg version
# -f option for long city listing
# -w option to set output width

use strict;
use warnings;
use Getopt::Std;

my $defaultwidth = 14; # default output width in chars, overidden by -w switch

#========================================

sub twelveto24{
# adapted from http://keithdevens.com/weblog/archive/2006/Feb/02/12-to-24
   my ($hr, $per) = @_;
   return '00' if($hr == 12 and $per eq 'AM');
   return $hr+12 if($hr != 12 and $per eq 'PM');
   if (length($hr) eq 1){ $hr = '0' . $hr };
   return $hr;
}

#=========================================

my ($city, $URL, $displaywidth);
our ($opt_f, $opt_h, $opt_w);
my $download = "/tmp/citytimes.$$.html";


# Parse  cli switches
getopts('fhw:');

if ($opt_h) { die "Useage: $0 [-f|-h] [-w WIDTH ] somecity1 somecity2 somecity3 ..\n" };
if (!$ARGV[0]) {die "No city specified"};
if ($opt_w){
if ($opt_w !~ /\d+/ ) { die "Invalid argument to -w option"
} else { $displaywidth = $opt_w }
} else { $displaywidth = $defaultwidth }

#~ if ($opt_f) { $URL = "http://www.timeanddate.com/worldclock/full.html"
#~ } else { $URL = "http://www.timeanddate.com/worldclock/" }

if ($opt_f) { $URL = "http://www.whattimeisit.com/cgitime.exe?Mode=FullList"
} else { $URL = "http://www.whattimeisit.com/cgitime.exe?Mode=FullList" }

# print "timeanddate.com:\n"; # legal
print "www.whattimeisit.com:\n";

system("wget -O $download $URL &>/dev/null");

open(CONT, $download) or die "Could not open $download";

while (<CONT>){
foreach $city(@ARGV) {
if ($city !~ /\w+/) { die "City '$city' not alphanumeric" }
if (/$city.+?(\d{1,2})\:(\d+\d+) ((AM|PM))/i) {
my ($hr, $min, $ampm) = ( $1, $2, $3);
my $newhr = twelveto24($hr, $ampm);
my $newtime = $newhr . ":" . $min;
my $F = 'A' . $displaywidth;
print pack("$F A5", $city, $newtime), "\n";
}
}
}

unlink $download;

Posted by mikshaw on Sep. 23 2007,16:30
Wow. I'm glad you did that, because I already spent much more than a few minutes on it before remembering things like DST...which would mean much more work than I even want to consider bothering with =o)
Posted by Juanito on Sep. 23 2007,17:36
Code Sample
$ /opt/citytime.pl tokyo paris houston
Downloading time from http://www.timeanddate.com/worldclock/
tokyo 2:33
paris 19:33
houston 12:33

Now I'm well impressed - let's see if I can get this into torsmo

Posted by Juanito on Sep. 24 2007,11:07
So, I added this to the end of .torsmorc:
Code Sample
${color red}$hr
${color grey}Tokyo: $color ${execi 180 ~/.citytime.pl Tokyo}

But, since it starts off with:
Quote
Tokyo: Getting time from < http://www.timeanddate.com/worldclock >

The torsmo display gets v-e-r-y w-i-d-e...

I guess for this to progress, I'd need a site that didn't require the url to be stated.

Posted by mikshaw on Sep. 24 2007,14:01
I assume you would be allowed to format the outpoot slightly if it's causing display troubles. The timeanddate people would have to be mightily spitely to have a problem with that. Try just inserting a newline:
Code Sample
print "Getting time from\n $URL\n"; # legal

The information remains unchanged, but your display is not messed up.

Posted by WDef on Sep. 24 2007,14:04
Juanito: Did you notice I've added a width control switch to citytime.pl with some other stuff?

Eg set 20 chars output width before 5-char time is displayed (so total width is 25 chars):

Code Sample
citytime.pl -w 20 Tokyo London


Also, the data is now justified uniformly. You have Tokyo printed out twice; I'm doing (eg):

Code Sample
${color red}$hr
${color grey}$color${execi 180 ~/.citytime.pl 'San Francisco' Sydney Tokyo}


Mikshaw:  I've shortened the message to the minimum:

Quote
timeanddate.com:


Quote
a site that didn't require the url to be stated.


Another source might be nice - some of these have additional info eg weather.

I'm only guessing it is necessary to flag the source to the user. It is not clear to me and I'm not a lawyer.  There's no EULA on the web site that I can find, and I am wondering if they could enforce rights over "the time", public domain data if ever there was any.  Their notice is not in plain view - it is buried in the html source. And just how do they prevent people from accessing the web page data using whatever technology they feel like?  Tell them it's "forbidden?"

Posted by Juanito on Sep. 24 2007,15:19
One way around it could be to comment out the url in citytime.pl and use something like this in torsmorc:
Code Sample
${color red}$hr
${color grey}Time by www.timeanddate.com
${color grey}$color${execi 180 ~/.citytime.pl Singapore}
${color grey}$color${execi 180 ~/.citytime.pl Paris}
${color grey}$color${execi 180 ~/.citytime.pl London}
${color grey}$color${execi 180 ~/.citytime.pl Seattle}

On a minor level, aesthetically it might be better to put the time first (with a leading zero if required) or align the time output, but that's just splitting hairs.

Posted by WDef on Sep. 24 2007,15:35
You need to try the 'latest version' - I updated it already to add leading zeroes and to justify columns, and to check args and options.

For me, torsmo is looking very good without multiple calls to citytime.pl  (means multiple downloads).  No need to comment out the (shortened) message.

Also, have changed the source to < www.whatisthetime.com > , which does not seem to have evil notices anywhere that I can find, in case anyone is worried.  The same regex worked on their list.

Feedback about new server speed of download etc?

Posted by Juanito on Sep. 24 2007,17:15
Quote
You need to try the 'latest version'

- We must have been typing the last posts at the same time. This seems to do the trick now:
Code Sample
${color red}$hr
${color grey}$color${execi 180 ~/.citytime.pl Singapore Paris London 'San Francisco'}

About the only thing I notice (and it was the same for both url's) is that torsmo is very slow to start now and blinks occasionally (but I did see something about double-buffering somewhere).

Thanks - learnt something more there, now I'm going to try at adding some cpu info, etc to the display.

Posted by WDef on Sep. 24 2007,18:26
Actually it's been handy for me as I find the city/time display quite useful, so thanks Juanito for the impetus.

My torsmo was taking a second or two to start anyway, maybe coz I have acpi temp etc displayed.

May try to expand what it can pull in at the same time by using a different site containing more info  - maybe display city temperature?  Wonder if that would be interesting.  Might make torsmo display 5 chars wider if on the same line as time.

Posted by mikshaw on Sep. 24 2007,20:33
After waking up it occured to me that you cannot be forced to display credits on your own machine. I can maybe understand requiring it in distributed applications that use your service, but if that application is open the end users can modify it themselves to remove that credit.

After the information arrives at its intended destination the service provider has no say in how that info is used. After all the info itself is not property.

Posted by WDef on Sep. 24 2007,21:28
Makes sense. I think timeanddate.com's notice (doesn't actually say anything as speciific as they 'must be acknowledged') would be a lot less feeble, and more visible, if they thought they had a chance of enforcing it.   I don't mind acknowledging a free source - that is what they should specifically ask for.  

torsmo starts slowly for me with or without this perl code.

Does torsmo just start slower when you load it with *any* script? And this double buffering thing ..?

Thinking about ways to speed up citytimes.pl eg

1. Don't download every single call.  Instead, store the times and increment from the system clock, do correction from the web  every hour or so.     Needs to get seconds as well to do this.

2. Don't download a full page every time.  Instead, parse the page on the fly while it downloads, stop downloading as soon as required info is received.

3. Make web page grepping more efficient (not much benefit).

Posted by Juanito on Sep. 25 2007,03:36
Quote
1. Don't download every single call.  Instead, store the times and increment from the system clock, do correction from the web  every hour or so.     Needs to get seconds as well to do this.

- For me this would be the way to go, with the added bonus that your machine's time zone does not need to be set correctly (I cannot set mine in dsl).

I left citytime/torsmo running over night and this morning there was just the url and no times displayed - I suppose the net connection dropped out at some point and stopped things working. If you go with the web correction method then I guess it could be programmed to do nothing if it cannot connect.

Posted by WDef on Sep. 25 2007,12:36
I'll give this is go in the next few days.

The time display vanished for me also when left running overnight.

Posted by WDef on Oct. 01 2007,20:40
Here's a better rendition, makes config file ~/.citytimerc, updates betweeen downloads using the system clock, etc

Width is now the total width.

Code Sample
#!/usr/bin/perl

# citytime - outputs times in multiple cities
# by wdef

# - downloads times from web at preset interval
# - caches and updates times using system clock between downloads

my $version = 0.3;

# Use -h for useage
# 24-hour, multi arg version
# -f option for long city listing
# -w option to set output width

# Note that die messages won't show in torsmo.

use strict;
use warnings;
use Getopt::Std;



#===================================// SUBS //=========================================

my ($download_interval, $defaultwidth, $download, $timecache, $timestamp, $city, $citytimerc, $timeurl1, $timeurl2, $URL, $displaywidth, %cachedtimes, $storedcity,  $storedtime, $storedmins);
our ($opt_f, $opt_h, $opt_w, $opt_v);


sub make_config_file {

my $conf;

$conf = <<HERE_TARGET

# Citytime will use these settings

# Download time from these URLs:
\$timeurl1 = "http://www.whattimeisit.com/cgitime.exe?Mode=FullList";

# -f option will enable:
# \$timeurl2 = someotherURL

# Minutes between downloads:
\$download_interval = 15;

# Default total output width in chars, overidden by -w switch
\$defaultwidth = 20;

# Cache file name & location
\$timecache = "/tmp/citytime.timecache";

# Time stamp file name & location
\$timestamp = "/tmp/citytime.timestamp";

# Downloaded time temp file name & location
\$download = "/tmp/citytime.html";

HERE_TARGET
;

open (CONFIG, "> $citytimerc");
print CONFIG "$conf";

}


sub add_leading_zero{
my $n = shift;
if (length($n) eq 1){ $n = '0' . $n }
return $n
}


sub twelveto24{
# adapted from http://keithdevens.com/weblog/archive/2006/Feb/02/12-to-24
   my ($hr, $per) = @_;
   return '00' if($hr == 12 and $per eq 'AM');
   return $hr+12 if($hr != 12 and $per eq 'PM');
   $hr = add_leading_zero($hr);
   return $hr;
}

sub check_cityargs{
# Check if city args have changed since the last call
my $arg;
open(CACHE, "<$timecache") or return 0;
foreach $arg(@ARGV) {
if ($arg !~ /\w+/) { die "City '$city' not alphanumeric" }
if (<CACHE> !~ /$arg/i){ return 0 }
}
# Check if DST status has changed
my @timecmps = localtime;
my $dst = $timecmps[8];
if (<CACHE> !~  /$dst/){ return 0 };
return 1;
}


sub maketimestamp {
open(TIMESTAMP, ">$timestamp") or die "Could not open $timestamp";
my $epochsec = time;
print TIMESTAMP $epochsec, "\n";
}

sub readcache {
open(CACHE, "<$timecache") or return 0;
my $diff = shift;
while (<CACHE>){
chomp;
$storedcity = "";
$storedmins = "";
# to handle spaces in city names.
if (/^(.+)\s(\d+)$/) {
$storedcity = $1; $storedmins  = $2
} else { last }

my $updated_citysecs = $storedmins * 60 + $diff;
my @parts = gmtime($updated_citysecs);
my $minutes = add_leading_zero($parts[1]);
my $hours = add_leading_zero($parts[2]);
my $updatedtime = $hours . ':' . $minutes;

my $F = 'A' . $displaywidth;
print pack("$F A5", $storedcity, $updatedtime), "\n";
}
return 1;
}

sub record_daylight_saving{
# Write local DST status to cache
# Probably only useful in EU for looking at other EU timezones
my @timecomps = localtime;
print CACHE $timecomps[8];
}


sub check_online {
open (NET, "ifconfig -a |");
while (<NET>){
if (/.+inet addr:(\d+\.\d+\.\d+\.\d+).+/){
if ( $1 ne "127.0.0.1" ) { return 1 }
}
}
return 0;
}

sub getfreshtime {
unless (check_online) { print "> No network <\n"; return 0 }
if ( -e $timecache ) { unlink $timecache } # start clean just in case
open(CACHE, ">$timecache") or die "Could not open $timecache";
system("wget -O $download $URL &>/dev/null");
open(CONT, $download) or return 0;
while (<CONT>){
foreach $city(@ARGV) {
if (/$city.+?(\d{1,2})\:(\d+\d+) ((AM|PM))/i) {
my ($hr, $min, $ampm) = ( $1, $2, $3);
my $newhr = twelveto24($hr, $ampm);
my $newtime = $newhr . ":" . $min;
my $totalmins = $newhr * 60 + $min;
maketimestamp;
print CACHE $city, " ", $totalmins, "\n";
my $F = 'A' . $displaywidth;
print pack("$F A5", $city, $newtime), "\n";
}
}
}
unlink $download;
record_daylight_saving;
return 1;
}

sub time_elapsed {
if (!open(TIMESTAMP, "<$timestamp") ){
if (getfreshtime) { exit(0)
} else { die "No webtime\n" }
}
my $timestamped_time = <TIMESTAMP>;
chomp $timestamped_time;
my $epochsec = time;
my $timediff = $epochsec - $timestamped_time;
return $timediff;
}


# ============================//SETTINGS//=====================================

$citytimerc = ${ENV}{'HOME'} . '/' . '.citytimerc';

if (! -r "$citytimerc") { make_config_file() }

# Use config file
eval `cat $citytimerc`;

# Parse  cli switches
getopts('fhvw:');

if ($opt_h) { die "Usage: $0 [-fhvw WIDTH ] somecity1 somecity2 somecity3 ..\n" };
if ($opt_v) { die "$version\n" };
if (!$ARGV[0]) {die "No city specified"};
if ($opt_w){
if ($opt_w !~ /\d+/ ) { die "Invalid argument to -w option"
} else { $displaywidth = $opt_w - 5 }
} else { $displaywidth = $defaultwidth - 5 }

if ($opt_f) { $URL = "$timeurl2"
} else { $URL = "$timeurl1" }


#==========================//MAIN//=============================================

print "www.whatisthetime.com:\n"; # acknowledge source

# if the timestamp can't be read then download, cache and display fresh time and exit.

my $difference = time_elapsed;

sub get_time {
getfreshtime || readcache($difference) || die "No time!\n";
}

# If argument cities have been added or the timecache  can't be read
# or if DST status locally has changed
# then download, cache and display fresh time and exit.

if (!check_cityargs) { get_time; exit(0) };


my $threshold = $download_interval * 60;  # threshold in seconds

# If the download interval has been exceeded, then download, cache and display fresh time and exit.
# Otherwise read the timecache and update to current time by adding on secs since the timestamp.

if ($difference >= $threshold ) { get_time; exit(0)
} elsif (!readcache($difference)) { getfreshtime || die "No webtime\n" }

# If network goes down when citytime needs to get fresh time, then >no network< will be displayed.

# If network goes down and interval is not up and cached stuff is ok, and cityfime refreshes from
# the web for another reason (eg changed args), then <no network< will be displayed AND display
# times will be updated using the system clock.


unlink $download;


Posted by Juanito on Oct. 04 2007,14:50
Looks good so far.

I changed the .torsmorc line to read "execi 60" so that the times read the same as the system clock. Torsmo takes 100s to appear on my (slow) machine versus almost immediately without the .citytime call - it was probably as slow with the previous incarnations of .citytime.

Posted by WDef on Oct. 04 2007,15:20
It has to download the times page the first time it is run after bootup, that's going to slow things down.  I start my network connection after starting the desktop, so don't notice this.  Is this what the holdup is?

If you quit X and restart, it won't download again until the $download_interval period is up or something's happened to the cache or temp files etc. (Doing this on my 1.87Ghz machine, torsmo starts after about 3 sec, and I'm running several other scripts, hacks etc as well from it).

So that'll tell us if it's the download or something else holding up torsmo for you.

The torsmo config file does say that running external stuff from torsmo in this way consumes a lot of resources.

How's the blinking?  For me it's much improved, and seems to be coming from the other extra stuff I'm having torsmo do anyway.

I also use execi 60 - makes sense to refresh the minutes display every minute.

Posted by Juanito on Oct. 04 2007,15:32
If I exit and then (re)startx, the torsmo display takes about 20s to appear and the world time digital clocks about 20s after that - this is on a 267MHz Pentium II...

I would say the blinking is about the same with/without .citytime

Posted by WDef on Oct. 04 2007,16:25
I could add an option to disable arg and local dst status checking, that would make no difference on my 1.87Ghz machine but might on yours.  If you say the previous citytime was just as slow, this isn't the problem anyway.

It seems to be taking a long time just to parse the cache file and update the times display on your machine, which is almost instantaneous on my machine.

If I knew more perl, I could probably make it run much faster.  It's not helped by calling system progs like wget as child processes -  a workaround because dsl lacks the standard LWN::Simple module (contains perl's 'get').

A lua version probably would go faster, but might still need to drop to perl/sed/awk in order to extract the times from the html.

In case anyone wants to write a version in another language, perl can be called from the shell to extract a time from the downloaded html file thusly:

Code Sample

export city=Boston
cat Zones.html | perl -ne 'my $city=${ENV}{city}; if (/$city.+?(\d{1,2})\:(\d+\d+) ((AM|PM))/i) {print $city, " ", $1,":",$2}'


But it could be that running external interpreters from torsmo like this is just not so wonderful in any case on low spec machines.

Posted by Juanito on Oct. 04 2007,17:01
Don't get me wrong, I'm not complaining - I restart this machine once/twice a month :)
Posted by WDef on Oct. 04 2007,17:07
There's nothing like reliability!

Actually I've taken to choking my CPU down to 800Mhz anyway, so the laptop runs much cooler. Has no effect on citytime.  So if you ever "upgrade" to a PIII+, you can expect much quicker torsmo stuff.

Posted by Juanito on Oct. 05 2007,05:35
...left it going all night, every so often the torsmo display disappears for 10-15s and then comes back - this doesn't seem to match the frequency at which .citytime checks the web time though...
Posted by WDef on Oct. 05 2007,23:19
If you're calling a number of different things from torsmo - here I'm guessing - but perhaps this occurs when a number of torsmo-initiated events occur at the same time.

Perhaps try breaking the intervals between the different calls so these are not in lock step eg every 90 sec for one external event  and every 60 sec for another so they can't coincide.

And/or try disabling these and adding them back in one at a time until the behavior manifests?

Posted by Juanito on Oct. 06 2007,03:59
The only other external call being made is .torsmo_ip - I'll offset the "execi 180" to something else as you suggest. The blanking also might be related to the cpu %load - I'll have a look at this.
Posted by WDef on Oct. 10 2007,15:08
I've been rewriting this in C.  Preliminary tests running it from torsmo are very smooth, no blinking at all, even downloading every call (no caching yet).   It forks a child and downloads the time in that, so it might be possible to make it so that citytime just carries on reading from cached times while a sluggish download is in progress, thus removing any additional interruption to the display caused by a download.   I also tried doing this in perl, but forking in perl by itself slowed things down.

Still more work to do, but an interesting little project.

Powered by Ikonboard 3.1.2a
Ikonboard © 2001 Jarvis Entertainment Group, Inc.