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; |
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}' |