Home | History | Annotate | Line # | Download | only in time
tzselect.ksh revision 1.10
      1   1.8  christos #! /bin/bash
      2   1.2     perry #
      3  1.10  christos #	$NetBSD: tzselect.ksh,v 1.10 2013/12/26 18:34:28 christos Exp $
      4   1.2     perry #
      5   1.8  christos PKGVERSION='(tzcode) '
      6   1.8  christos TZVERSION=see_Makefile
      7   1.8  christos REPORT_BUGS_TO=tz@iana.org
      8   1.5    kleink 
      9   1.1       jtc # Ask the user about the time zone, and output the resulting TZ value to stdout.
     10   1.1       jtc # Interact with the user via stderr and stdin.
     11   1.1       jtc 
     12   1.6   mlelstv # Contributed by Paul Eggert.
     13   1.1       jtc 
     14   1.1       jtc # Porting notes:
     15   1.1       jtc #
     16  1.10  christos # This script requires a Posix-like shell and prefers the extension of a
     17   1.8  christos # 'select' statement.  The 'select' statement was introduced in the
     18   1.8  christos # Korn shell and is available in Bash and other shell implementations.
     19   1.8  christos # If your host lacks both Bash and the Korn shell, you can get their
     20   1.8  christos # source from one of these locations:
     21   1.1       jtc #
     22   1.8  christos #	Bash <http://www.gnu.org/software/bash/bash.html>
     23   1.8  christos #	Korn Shell <http://www.kornshell.com/>
     24   1.8  christos #	Public Domain Korn Shell <http://www.cs.mun.ca/~michael/pdksh/>
     25   1.1       jtc #
     26  1.10  christos # For portability to Solaris 9 /bin/sh this script avoids some POSIX
     27  1.10  christos # features and common extensions, such as $(...) (which works sometimes
     28  1.10  christos # but not others), $((...)), and $10.
     29  1.10  christos #
     30   1.1       jtc # This script also uses several features of modern awk programs.
     31   1.8  christos # If your host lacks awk, or has an old awk that does not conform to Posix,
     32   1.1       jtc # you can use either of the following free programs instead:
     33   1.1       jtc #
     34   1.8  christos #	Gawk (GNU awk) <http://www.gnu.org/software/gawk/>
     35   1.8  christos #	mawk <http://invisible-island.net/mawk/>
     36   1.1       jtc 
     37   1.1       jtc 
     38   1.1       jtc # Specify default values for environment variables if they are unset.
     39   1.1       jtc : ${AWK=awk}
     40  1.10  christos : ${TZDIR=`pwd`}
     41   1.1       jtc 
     42   1.1       jtc # Check for awk Posix compliance.
     43   1.1       jtc ($AWK -v x=y 'BEGIN { exit 123 }') </dev/null >/dev/null 2>&1
     44   1.1       jtc [ $? = 123 ] || {
     45   1.1       jtc 	echo >&2 "$0: Sorry, your \`$AWK' program is not Posix compatible."
     46   1.1       jtc 	exit 1
     47   1.1       jtc }
     48   1.1       jtc 
     49   1.9  christos coord=
     50   1.9  christos location_limit=10
     51   1.9  christos 
     52   1.9  christos usage="Usage: tzselect [--version] [--help] [-c COORD] [-n LIMIT]
     53   1.6   mlelstv Select a time zone interactively.
     54   1.6   mlelstv 
     55   1.9  christos Options:
     56   1.9  christos 
     57   1.9  christos   -c COORD
     58   1.9  christos     Instead of asking for continent and then country and then city,
     59   1.9  christos     ask for selection from time zones whose largest cities
     60   1.9  christos     are closest to the location with geographical coordinates COORD.
     61   1.9  christos     COORD should use ISO 6709 notation, for example, '-c +4852+00220'
     62   1.9  christos     for Paris (in degrees and minutes, North and East), or
     63   1.9  christos     '-c -35-058' for Buenos Aires (in degrees, South and West).
     64   1.9  christos 
     65   1.9  christos   -n LIMIT
     66   1.9  christos     Display at most LIMIT locations when -c is used (default $location_limit).
     67   1.9  christos 
     68   1.9  christos   --version
     69   1.9  christos     Output version information.
     70   1.9  christos 
     71   1.9  christos   --help
     72   1.9  christos     Output this help.
     73   1.9  christos 
     74   1.9  christos Report bugs to $REPORT_BUGS_TO."
     75   1.9  christos 
     76  1.10  christos # Ask the user to select from the function's arguments,
     77  1.10  christos # and assign the selected argument to the variable 'select_result'.
     78  1.10  christos # Exit on EOF or I/O error.  Use the shell's 'select' builtin if available,
     79  1.10  christos # falling back on a less-nice but portable substitute otherwise.
     80  1.10  christos if
     81  1.10  christos   case $BASH_VERSION in
     82  1.10  christos   ?*) : ;;
     83  1.10  christos   '')
     84  1.10  christos     # '; exit' should be redundant, but Dash doesn't properly fail without it.
     85  1.10  christos     (eval 'set --; select x; do break; done; exit') 2>/dev/null
     86  1.10  christos   esac
     87  1.10  christos then
     88  1.10  christos   # Do this inside 'eval', as otherwise the shell might exit when parsing it
     89  1.10  christos   # even though it is never executed.
     90  1.10  christos   eval '
     91  1.10  christos     doselect() {
     92  1.10  christos       select select_result
     93  1.10  christos       do
     94  1.10  christos 	case $select_result in
     95  1.10  christos 	"") echo >&2 "Please enter a number in range." ;;
     96  1.10  christos 	?*) break
     97  1.10  christos 	esac
     98  1.10  christos       done || exit
     99  1.10  christos     }
    100  1.10  christos 
    101  1.10  christos     # Work around a bug in bash 1.14.7 and earlier, where $PS3 is sent to stdout.
    102  1.10  christos     case $BASH_VERSION in
    103  1.10  christos     [01].*)
    104  1.10  christos       case `echo 1 | (select x in x; do break; done) 2>/dev/null` in
    105  1.10  christos       ?*) PS3=
    106  1.10  christos       esac
    107  1.10  christos     esac
    108  1.10  christos   '
    109  1.10  christos else
    110  1.10  christos   doselect() {
    111  1.10  christos     # Field width of the prompt numbers.
    112  1.10  christos     select_width=`expr $# : '.*'`
    113  1.10  christos 
    114  1.10  christos     select_i=
    115  1.10  christos 
    116  1.10  christos     while :
    117  1.10  christos     do
    118  1.10  christos       case $select_i in
    119  1.10  christos       '')
    120  1.10  christos 	select_i=0
    121  1.10  christos 	for select_word
    122  1.10  christos 	do
    123  1.10  christos 	  select_i=`expr $select_i + 1`
    124  1.10  christos 	  printf >&2 "%${select_width}d) %s\\n" $select_i "$select_word"
    125  1.10  christos 	done ;;
    126  1.10  christos       *[!0-9]*)
    127  1.10  christos 	echo >&2 'Please enter a number in range.' ;;
    128  1.10  christos       *)
    129  1.10  christos 	if test 1 -le $select_i && test $select_i -le $#; then
    130  1.10  christos 	  shift `expr $select_i - 1`
    131  1.10  christos 	  select_result=$1
    132  1.10  christos 	  break
    133  1.10  christos 	fi
    134  1.10  christos 	echo >&2 'Please enter a number in range.'
    135  1.10  christos       esac
    136  1.10  christos 
    137  1.10  christos       # Prompt and read input.
    138  1.10  christos       printf >&2 %s "${PS3-#? }"
    139  1.10  christos       read select_i || exit
    140  1.10  christos     done
    141  1.10  christos   }
    142  1.10  christos fi
    143  1.10  christos 
    144   1.9  christos while getopts c:n:-: opt
    145   1.9  christos do
    146   1.9  christos     case $opt$OPTARG in
    147   1.9  christos     c*)
    148   1.9  christos 	coord=$OPTARG ;;
    149   1.9  christos     n*)
    150   1.9  christos 	location_limit=$OPTARG ;;
    151   1.9  christos     -help)
    152   1.9  christos 	exec echo "$usage" ;;
    153   1.9  christos     -version)
    154   1.9  christos 	exec echo "tzselect $PKGVERSION$TZVERSION" ;;
    155   1.9  christos     -*)
    156   1.9  christos 	echo >&2 "$0: -$opt$OPTARG: unknown option; try '$0 --help'"; exit 1 ;;
    157   1.9  christos     *)
    158   1.9  christos 	echo >&2 "$0: try '$0 --help'"; exit 1 ;;
    159   1.9  christos     esac
    160   1.9  christos done
    161   1.9  christos 
    162  1.10  christos shift `expr $OPTIND - 1`
    163   1.9  christos case $# in
    164   1.9  christos 0) ;;
    165   1.9  christos *) echo >&2 "$0: $1: unknown argument"; exit 1 ;;
    166   1.9  christos esac
    167   1.6   mlelstv 
    168   1.1       jtc # Make sure the tables are readable.
    169   1.1       jtc TZ_COUNTRY_TABLE=$TZDIR/iso3166.tab
    170   1.1       jtc TZ_ZONE_TABLE=$TZDIR/zone.tab
    171   1.1       jtc for f in $TZ_COUNTRY_TABLE $TZ_ZONE_TABLE
    172   1.1       jtc do
    173   1.1       jtc 	<$f || {
    174   1.1       jtc 		echo >&2 "$0: time zone files are not set up correctly"
    175   1.1       jtc 		exit 1
    176   1.1       jtc 	}
    177   1.1       jtc done
    178   1.1       jtc 
    179   1.1       jtc newline='
    180   1.1       jtc '
    181   1.1       jtc IFS=$newline
    182   1.1       jtc 
    183   1.1       jtc 
    184   1.9  christos # Awk script to read a time zone table and output the same table,
    185   1.9  christos # with each column preceded by its distance from 'here'.
    186   1.9  christos output_distances='
    187   1.9  christos   BEGIN {
    188   1.9  christos     FS = "\t"
    189   1.9  christos     while (getline <TZ_COUNTRY_TABLE)
    190   1.9  christos       if ($0 ~ /^[^#]/)
    191   1.9  christos         country[$1] = $2
    192   1.9  christos     country["US"] = "US" # Otherwise the strings get too long.
    193   1.9  christos   }
    194   1.9  christos   function convert_coord(coord, deg, min, ilen, sign, sec) {
    195   1.9  christos     if (coord ~ /^[-+]?[0-9]?[0-9][0-9][0-9][0-9][0-9][0-9]([^0-9]|$)/) {
    196   1.9  christos       degminsec = coord
    197   1.9  christos       intdeg = degminsec < 0 ? -int(-degminsec / 10000) : int(degminsec / 10000)
    198   1.9  christos       minsec = degminsec - intdeg * 10000
    199   1.9  christos       intmin = minsec < 0 ? -int(-minsec / 100) : int(minsec / 100)
    200   1.9  christos       sec = minsec - intmin * 100
    201   1.9  christos       deg = (intdeg * 3600 + intmin * 60 + sec) / 3600
    202   1.9  christos     } else if (coord ~ /^[-+]?[0-9]?[0-9][0-9][0-9][0-9]([^0-9]|$)/) {
    203   1.9  christos       degmin = coord
    204   1.9  christos       intdeg = degmin < 0 ? -int(-degmin / 100) : int(degmin / 100)
    205   1.9  christos       min = degmin - intdeg * 100
    206   1.9  christos       deg = (intdeg * 60 + min) / 60
    207   1.9  christos     } else
    208   1.9  christos       deg = coord
    209   1.9  christos     return deg * 0.017453292519943296
    210   1.9  christos   }
    211   1.9  christos   function convert_latitude(coord) {
    212   1.9  christos     match(coord, /..*[-+]/)
    213   1.9  christos     return convert_coord(substr(coord, 1, RLENGTH - 1))
    214   1.9  christos   }
    215   1.9  christos   function convert_longitude(coord) {
    216   1.9  christos     match(coord, /..*[-+]/)
    217   1.9  christos     return convert_coord(substr(coord, RLENGTH))
    218   1.9  christos   }
    219   1.9  christos   # Great-circle distance between points with given latitude and longitude.
    220   1.9  christos   # Inputs and output are in radians.  This uses the great-circle special
    221   1.9  christos   # case of the Vicenty formula for distances on ellipsoids.
    222   1.9  christos   function dist(lat1, long1, lat2, long2, dlong, x, y, num, denom) {
    223   1.9  christos     dlong = long2 - long1
    224   1.9  christos     x = cos (lat2) * sin (dlong)
    225   1.9  christos     y = cos (lat1) * sin (lat2) - sin (lat1) * cos (lat2) * cos (dlong)
    226   1.9  christos     num = sqrt (x * x + y * y)
    227   1.9  christos     denom = sin (lat1) * sin (lat2) + cos (lat1) * cos (lat2) * cos (dlong)
    228   1.9  christos     return atan2(num, denom)
    229   1.9  christos   }
    230   1.9  christos   BEGIN {
    231   1.9  christos     coord_lat = convert_latitude(coord)
    232   1.9  christos     coord_long = convert_longitude(coord)
    233   1.9  christos   }
    234   1.9  christos   /^[^#]/ {
    235   1.9  christos     here_lat = convert_latitude($2)
    236   1.9  christos     here_long = convert_longitude($2)
    237   1.9  christos     line = $1 "\t" $2 "\t" $3 "\t" country[$1]
    238   1.9  christos     if (NF == 4)
    239   1.9  christos       line = line " - " $4
    240   1.9  christos     printf "%g\t%s\n", dist(coord_lat, coord_long, here_lat, here_long), line
    241   1.9  christos   }
    242   1.9  christos '
    243   1.1       jtc 
    244   1.1       jtc # Begin the main loop.  We come back here if the user wants to retry.
    245   1.1       jtc while
    246   1.1       jtc 
    247   1.1       jtc 	echo >&2 'Please identify a location' \
    248   1.1       jtc 		'so that time zone rules can be set correctly.'
    249   1.1       jtc 
    250   1.1       jtc 	continent=
    251   1.1       jtc 	country=
    252   1.1       jtc 	region=
    253   1.1       jtc 
    254   1.9  christos 	case $coord in
    255   1.9  christos 	?*)
    256   1.9  christos 		continent=coord;;
    257   1.9  christos 	'')
    258   1.1       jtc 
    259   1.1       jtc 	# Ask the user for continent or ocean.
    260   1.1       jtc 
    261   1.9  christos 	echo >&2 'Please select a continent, ocean, "coord", or "TZ".'
    262   1.1       jtc 
    263  1.10  christos         quoted_continents=`
    264  1.10  christos 	  $AWK '
    265  1.10  christos 	    BEGIN { FS = "\t" }
    266   1.9  christos 	    /^[^#]/ {
    267   1.9  christos               entry = substr($3, 1, index($3, "/") - 1)
    268   1.9  christos               if (entry == "America")
    269   1.9  christos 		entry = entry "s"
    270   1.9  christos               if (entry ~ /^(Arctic|Atlantic|Indian|Pacific)$/)
    271   1.9  christos 		entry = entry " Ocean"
    272   1.9  christos               printf "'\''%s'\''\n", entry
    273   1.9  christos             }
    274   1.9  christos           ' $TZ_ZONE_TABLE |
    275   1.9  christos 	  sort -u |
    276   1.9  christos 	  tr '\n' ' '
    277   1.9  christos 	  echo ''
    278  1.10  christos 	`
    279   1.9  christos 
    280   1.9  christos 	eval '
    281  1.10  christos 	    doselect '"$quoted_continents"' \
    282   1.9  christos 		"coord - I want to use geographical coordinates." \
    283   1.9  christos 		"TZ - I want to specify the time zone using the Posix TZ format."
    284  1.10  christos 	    continent=$select_result
    285  1.10  christos 	    case $continent in
    286  1.10  christos 	    Americas) continent=America;;
    287  1.10  christos 	    *" "*) continent=`expr "$continent" : '\''\([^ ]*\)'\''`
    288  1.10  christos 	    esac
    289   1.9  christos 	'
    290   1.9  christos 	esac
    291   1.9  christos 
    292   1.1       jtc 	case $continent in
    293   1.9  christos 	TZ)
    294   1.1       jtc 		# Ask the user for a Posix TZ string.  Check that it conforms.
    295   1.1       jtc 		while
    296   1.1       jtc 			echo >&2 'Please enter the desired value' \
    297   1.1       jtc 				'of the TZ environment variable.'
    298   1.1       jtc 			echo >&2 'For example, GST-10 is a zone named GST' \
    299   1.1       jtc 				'that is 10 hours ahead (east) of UTC.'
    300   1.1       jtc 			read TZ
    301   1.1       jtc 			$AWK -v TZ="$TZ" 'BEGIN {
    302   1.1       jtc 				tzname = "[^-+,0-9][^-+,0-9][^-+,0-9]+"
    303   1.1       jtc 				time = "[0-2]?[0-9](:[0-5][0-9](:[0-5][0-9])?)?"
    304   1.1       jtc 				offset = "[-+]?" time
    305   1.1       jtc 				date = "(J?[0-9]+|M[0-9]+\.[0-9]+\.[0-9]+)"
    306   1.1       jtc 				datetime = "," date "(/" time ")?"
    307   1.1       jtc 				tzpattern = "^(:.*|" tzname offset "(" tzname \
    308   1.1       jtc 				  "(" offset ")?(" datetime datetime ")?)?)$"
    309   1.1       jtc 				if (TZ ~ tzpattern) exit 1
    310   1.1       jtc 				exit 0
    311   1.1       jtc 			}'
    312   1.1       jtc 		do
    313   1.1       jtc 			echo >&2 "\`$TZ' is not a conforming" \
    314   1.1       jtc 				'Posix time zone string.'
    315   1.1       jtc 		done
    316   1.1       jtc 		TZ_for_date=$TZ;;
    317   1.1       jtc 	*)
    318   1.9  christos 		case $continent in
    319   1.9  christos 		coord)
    320   1.9  christos 		    case $coord in
    321   1.9  christos 		    '')
    322   1.9  christos 			echo >&2 'Please enter coordinates' \
    323   1.9  christos 				'in ISO 6709 notation.'
    324   1.9  christos 			echo >&2 'For example, +4042-07403 stands for'
    325   1.9  christos 			echo >&2 '40 degrees 42 minutes north,' \
    326   1.9  christos 				'74 degrees 3 minutes west.'
    327   1.9  christos 			read coord;;
    328   1.9  christos 		    esac
    329  1.10  christos 		    distance_table=`$AWK \
    330   1.9  christos 			    -v coord="$coord" \
    331   1.9  christos 			    -v TZ_COUNTRY_TABLE="$TZ_COUNTRY_TABLE" \
    332   1.9  christos 			    "$output_distances" <$TZ_ZONE_TABLE |
    333   1.9  christos 		      sort -n |
    334   1.9  christos 		      sed "${location_limit}q"
    335  1.10  christos 		    `
    336  1.10  christos 		    regions=`echo "$distance_table" | $AWK '
    337   1.9  christos 		      BEGIN { FS = "\t" }
    338   1.9  christos 		      { print $NF }
    339  1.10  christos 		    '`
    340   1.9  christos 		    echo >&2 'Please select one of the following' \
    341   1.9  christos 			    'time zone regions,'
    342   1.9  christos 		    echo >&2 'listed roughly in increasing order' \
    343   1.9  christos 			    "of distance from $coord".
    344  1.10  christos 		    doselect $regions
    345  1.10  christos 		    region=$select_result
    346  1.10  christos 		    TZ=`echo "$distance_table" | $AWK -v region="$region" '
    347   1.9  christos 		      BEGIN { FS="\t" }
    348   1.9  christos 		      $NF == region { print $4 }
    349  1.10  christos 		    '`
    350   1.9  christos 		    ;;
    351   1.9  christos 		*)
    352   1.1       jtc 		# Get list of names of countries in the continent or ocean.
    353  1.10  christos 		countries=`$AWK \
    354   1.1       jtc 			-v continent="$continent" \
    355   1.1       jtc 			-v TZ_COUNTRY_TABLE="$TZ_COUNTRY_TABLE" \
    356   1.1       jtc 		'
    357  1.10  christos 			BEGIN { FS = "\t" }
    358   1.1       jtc 			/^#/ { next }
    359   1.1       jtc 			$3 ~ ("^" continent "/") {
    360   1.1       jtc 				if (!cc_seen[$1]++) cc_list[++ccs] = $1
    361   1.1       jtc 			}
    362   1.1       jtc 			END {
    363   1.1       jtc 				while (getline <TZ_COUNTRY_TABLE) {
    364   1.1       jtc 					if ($0 !~ /^#/) cc_name[$1] = $2
    365   1.1       jtc 				}
    366   1.1       jtc 				for (i = 1; i <= ccs; i++) {
    367   1.1       jtc 					country = cc_list[i]
    368   1.1       jtc 					if (cc_name[country]) {
    369   1.1       jtc 					  country = cc_name[country]
    370   1.1       jtc 					}
    371   1.1       jtc 					print country
    372   1.1       jtc 				}
    373   1.1       jtc 			}
    374  1.10  christos 		' <$TZ_ZONE_TABLE | sort -f`
    375   1.1       jtc 
    376   1.1       jtc 
    377   1.1       jtc 		# If there's more than one country, ask the user which one.
    378   1.1       jtc 		case $countries in
    379   1.1       jtc 		*"$newline"*)
    380   1.9  christos 			echo >&2 'Please select a country' \
    381   1.9  christos 				'whose clocks agree with yours.'
    382  1.10  christos 			doselect $countries
    383  1.10  christos 			country=$select_result;;
    384   1.1       jtc 		*)
    385   1.1       jtc 			country=$countries
    386   1.1       jtc 		esac
    387   1.1       jtc 
    388   1.1       jtc 
    389   1.1       jtc 		# Get list of names of time zone rule regions in the country.
    390  1.10  christos 		regions=`$AWK \
    391   1.1       jtc 			-v country="$country" \
    392   1.1       jtc 			-v TZ_COUNTRY_TABLE="$TZ_COUNTRY_TABLE" \
    393   1.1       jtc 		'
    394   1.1       jtc 			BEGIN {
    395  1.10  christos 				FS = "\t"
    396   1.1       jtc 				cc = country
    397   1.1       jtc 				while (getline <TZ_COUNTRY_TABLE) {
    398   1.1       jtc 					if ($0 !~ /^#/  &&  country == $2) {
    399   1.1       jtc 						cc = $1
    400   1.1       jtc 						break
    401   1.1       jtc 					}
    402   1.1       jtc 				}
    403   1.1       jtc 			}
    404   1.1       jtc 			$1 == cc { print $4 }
    405  1.10  christos 		' <$TZ_ZONE_TABLE`
    406   1.1       jtc 
    407   1.1       jtc 
    408   1.1       jtc 		# If there's more than one region, ask the user which one.
    409   1.1       jtc 		case $regions in
    410   1.1       jtc 		*"$newline"*)
    411   1.1       jtc 			echo >&2 'Please select one of the following' \
    412   1.1       jtc 				'time zone regions.'
    413  1.10  christos 			doselect $regions
    414  1.10  christos 			region=$select_result;;
    415   1.1       jtc 		*)
    416   1.1       jtc 			region=$regions
    417   1.1       jtc 		esac
    418   1.1       jtc 
    419   1.1       jtc 		# Determine TZ from country and region.
    420  1.10  christos 		TZ=`$AWK \
    421   1.1       jtc 			-v country="$country" \
    422   1.1       jtc 			-v region="$region" \
    423   1.1       jtc 			-v TZ_COUNTRY_TABLE="$TZ_COUNTRY_TABLE" \
    424   1.1       jtc 		'
    425   1.1       jtc 			BEGIN {
    426  1.10  christos 				FS = "\t"
    427   1.1       jtc 				cc = country
    428   1.1       jtc 				while (getline <TZ_COUNTRY_TABLE) {
    429   1.1       jtc 					if ($0 !~ /^#/  &&  country == $2) {
    430   1.1       jtc 						cc = $1
    431   1.1       jtc 						break
    432   1.1       jtc 					}
    433   1.1       jtc 				}
    434   1.1       jtc 			}
    435   1.1       jtc 			$1 == cc && $4 == region { print $3 }
    436  1.10  christos 		' <$TZ_ZONE_TABLE`
    437   1.9  christos 		esac
    438   1.1       jtc 
    439   1.1       jtc 		# Make sure the corresponding zoneinfo file exists.
    440   1.1       jtc 		TZ_for_date=$TZDIR/$TZ
    441   1.1       jtc 		<$TZ_for_date || {
    442   1.1       jtc 			echo >&2 "$0: time zone files are not set up correctly"
    443   1.1       jtc 			exit 1
    444   1.1       jtc 		}
    445   1.1       jtc 	esac
    446   1.1       jtc 
    447   1.1       jtc 
    448   1.1       jtc 	# Use the proposed TZ to output the current date relative to UTC.
    449   1.1       jtc 	# Loop until they agree in seconds.
    450   1.1       jtc 	# Give up after 8 unsuccessful tries.
    451   1.1       jtc 
    452   1.1       jtc 	extra_info=
    453   1.1       jtc 	for i in 1 2 3 4 5 6 7 8
    454   1.1       jtc 	do
    455  1.10  christos 		TZdate=`LANG=C TZ="$TZ_for_date" date`
    456  1.10  christos 		UTdate=`LANG=C TZ=UTC0 date`
    457  1.10  christos 		TZsec=`expr "$TZdate" : '.*:\([0-5][0-9]\)'`
    458  1.10  christos 		UTsec=`expr "$UTdate" : '.*:\([0-5][0-9]\)'`
    459   1.1       jtc 		case $TZsec in
    460   1.1       jtc 		$UTsec)
    461   1.1       jtc 			extra_info="
    462   1.1       jtc Local time is now:	$TZdate.
    463   1.1       jtc Universal Time is now:	$UTdate."
    464   1.1       jtc 			break
    465   1.1       jtc 		esac
    466   1.1       jtc 	done
    467   1.1       jtc 
    468   1.1       jtc 
    469   1.1       jtc 	# Output TZ info and ask the user to confirm.
    470   1.1       jtc 
    471   1.1       jtc 	echo >&2 ""
    472   1.1       jtc 	echo >&2 "The following information has been given:"
    473   1.1       jtc 	echo >&2 ""
    474   1.9  christos 	case $country%$region%$coord in
    475   1.9  christos 	?*%?*%)	echo >&2 "	$country$newline	$region";;
    476   1.9  christos 	?*%%)	echo >&2 "	$country";;
    477   1.9  christos 	%?*%?*) echo >&2 "	coord $coord$newline	$region";;
    478   1.9  christos 	%%?*)	echo >&2 "	coord $coord";;
    479   1.1       jtc 	+)	echo >&2 "	TZ='$TZ'"
    480   1.1       jtc 	esac
    481   1.1       jtc 	echo >&2 ""
    482   1.1       jtc 	echo >&2 "Therefore TZ='$TZ' will be used.$extra_info"
    483   1.1       jtc 	echo >&2 "Is the above information OK?"
    484   1.1       jtc 
    485  1.10  christos 	doselect Yes No
    486  1.10  christos 	ok=$select_result
    487   1.1       jtc 	case $ok in
    488   1.1       jtc 	Yes) break
    489   1.1       jtc 	esac
    490   1.9  christos do coord=
    491   1.1       jtc done
    492   1.1       jtc 
    493   1.5    kleink case $SHELL in
    494   1.5    kleink *csh) file=.login line="setenv TZ '$TZ'";;
    495   1.5    kleink *) file=.profile line="TZ='$TZ'; export TZ"
    496   1.5    kleink esac
    497   1.5    kleink 
    498   1.5    kleink echo >&2 "
    499   1.5    kleink You can make this change permanent for yourself by appending the line
    500   1.5    kleink 	$line
    501   1.5    kleink to the file '$file' in your home directory; then log out and log in again.
    502   1.5    kleink 
    503   1.5    kleink Here is that TZ value again, this time on standard output so that you
    504   1.5    kleink can use the $0 command in shell scripts:"
    505   1.5    kleink 
    506   1.1       jtc echo "$TZ"
    507