WDef
Group: Members
Posts: 798
Joined: Sep. 2005 |
|
Posted: 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;
|
|