14616d0f9Sopenharmony_ci#!/bin/bash 24616d0f9Sopenharmony_ci# Ask the user about the time zone, and output the resulting TZ value to stdout. 34616d0f9Sopenharmony_ci# Interact with the user via stderr and stdin. 44616d0f9Sopenharmony_ci 54616d0f9Sopenharmony_ciPKGVERSION='(tzcode) ' 64616d0f9Sopenharmony_ciTZVERSION=see_Makefile 74616d0f9Sopenharmony_ciREPORT_BUGS_TO=tz@iana.org 84616d0f9Sopenharmony_ci 94616d0f9Sopenharmony_ci# Contributed by Paul Eggert. This file is in the public domain. 104616d0f9Sopenharmony_ci 114616d0f9Sopenharmony_ci# Porting notes: 124616d0f9Sopenharmony_ci# 134616d0f9Sopenharmony_ci# This script requires a POSIX-like shell and prefers the extension of a 144616d0f9Sopenharmony_ci# 'select' statement. The 'select' statement was introduced in the 154616d0f9Sopenharmony_ci# Korn shell and is available in Bash and other shell implementations. 164616d0f9Sopenharmony_ci# If your host lacks both Bash and the Korn shell, you can get their 174616d0f9Sopenharmony_ci# source from one of these locations: 184616d0f9Sopenharmony_ci# 194616d0f9Sopenharmony_ci# Bash <https://www.gnu.org/software/bash/> 204616d0f9Sopenharmony_ci# Korn Shell <http://www.kornshell.com/> 214616d0f9Sopenharmony_ci# MirBSD Korn Shell <http://www.mirbsd.org/mksh.htm> 224616d0f9Sopenharmony_ci# 234616d0f9Sopenharmony_ci# For portability to Solaris 10 /bin/sh (supported by Oracle through 244616d0f9Sopenharmony_ci# January 2027) this script avoids some POSIX features and common 254616d0f9Sopenharmony_ci# extensions, such as $(...), $((...)), ! CMD, unquoted ^, ${#ID}, 264616d0f9Sopenharmony_ci# ${ID##PAT}, ${ID%%PAT}, and $10. Although some of these constructs 274616d0f9Sopenharmony_ci# work sometimes, it's simpler to avoid them entirely. 284616d0f9Sopenharmony_ci# 294616d0f9Sopenharmony_ci# This script also uses several features of POSIX awk. 304616d0f9Sopenharmony_ci# If your host lacks awk, or has an old awk that does not conform to POSIX, 314616d0f9Sopenharmony_ci# you can use any of the following free programs instead: 324616d0f9Sopenharmony_ci# 334616d0f9Sopenharmony_ci# Gawk (GNU awk) <https://www.gnu.org/software/gawk/> 344616d0f9Sopenharmony_ci# mawk <https://invisible-island.net/mawk/> 354616d0f9Sopenharmony_ci# nawk <https://github.com/onetrueawk/awk> 364616d0f9Sopenharmony_ci# 374616d0f9Sopenharmony_ci# Because 'awk "VAR=VALUE" ...' and 'awk -v "VAR=VALUE" ...' are not portable 384616d0f9Sopenharmony_ci# if VALUE contains \, ", or newline, awk scripts in this file use: 394616d0f9Sopenharmony_ci# awk 'BEGIN { VAR = substr(ARGV[1], 2); ARGV[1] = "" } ...' ="VALUE" 404616d0f9Sopenharmony_ci# The substr avoids problems when VALUE is of the form X=Y and would be 414616d0f9Sopenharmony_ci# misinterpreted as an assignment. 424616d0f9Sopenharmony_ci 434616d0f9Sopenharmony_ci# This script does not want path expansion. 444616d0f9Sopenharmony_ciset -f 454616d0f9Sopenharmony_ci 464616d0f9Sopenharmony_ci# Specify default values for environment variables if they are unset. 474616d0f9Sopenharmony_ci: ${AWK=awk} 484616d0f9Sopenharmony_ci: ${PWD=`pwd`} 494616d0f9Sopenharmony_ci: ${TZDIR=$PWD} 504616d0f9Sopenharmony_ci 514616d0f9Sopenharmony_ci# Output one argument as-is to standard output, with trailing newline. 524616d0f9Sopenharmony_ci# Safer than 'echo', which can mishandle '\' or leading '-'. 534616d0f9Sopenharmony_cisay() { 544616d0f9Sopenharmony_ci printf '%s\n' "$1" 554616d0f9Sopenharmony_ci} 564616d0f9Sopenharmony_ci 574616d0f9Sopenharmony_ci# Check for awk POSIX compliance. 584616d0f9Sopenharmony_ci($AWK -v x=y 'BEGIN { exit 123 }') <>/dev/null >&0 2>&0 594616d0f9Sopenharmony_ci[ $? = 123 ] || { 604616d0f9Sopenharmony_ci say >&2 "$0: Sorry, your '$AWK' program is not POSIX compatible." 614616d0f9Sopenharmony_ci exit 1 624616d0f9Sopenharmony_ci} 634616d0f9Sopenharmony_ci 644616d0f9Sopenharmony_cicoord= 654616d0f9Sopenharmony_cilocation_limit=10 664616d0f9Sopenharmony_cizonetabtype=zone1970 674616d0f9Sopenharmony_ci 684616d0f9Sopenharmony_ciusage="Usage: tzselect [--version] [--help] [-c COORD] [-n LIMIT] 694616d0f9Sopenharmony_ciSelect a timezone interactively. 704616d0f9Sopenharmony_ci 714616d0f9Sopenharmony_ciOptions: 724616d0f9Sopenharmony_ci 734616d0f9Sopenharmony_ci -c COORD 744616d0f9Sopenharmony_ci Instead of asking for continent and then country and then city, 754616d0f9Sopenharmony_ci ask for selection from time zones whose largest cities 764616d0f9Sopenharmony_ci are closest to the location with geographical coordinates COORD. 774616d0f9Sopenharmony_ci COORD should use ISO 6709 notation, for example, '-c +4852+00220' 784616d0f9Sopenharmony_ci for Paris (in degrees and minutes, North and East), or 794616d0f9Sopenharmony_ci '-c -35-058' for Buenos Aires (in degrees, South and West). 804616d0f9Sopenharmony_ci 814616d0f9Sopenharmony_ci -n LIMIT 824616d0f9Sopenharmony_ci Display at most LIMIT locations when -c is used (default $location_limit). 834616d0f9Sopenharmony_ci 844616d0f9Sopenharmony_ci --version 854616d0f9Sopenharmony_ci Output version information. 864616d0f9Sopenharmony_ci 874616d0f9Sopenharmony_ci --help 884616d0f9Sopenharmony_ci Output this help. 894616d0f9Sopenharmony_ci 904616d0f9Sopenharmony_ciReport bugs to $REPORT_BUGS_TO." 914616d0f9Sopenharmony_ci 924616d0f9Sopenharmony_ci# Ask the user to select from the function's arguments, 934616d0f9Sopenharmony_ci# and assign the selected argument to the variable 'select_result'. 944616d0f9Sopenharmony_ci# Exit on EOF or I/O error. Use the shell's nicer 'select' builtin if 954616d0f9Sopenharmony_ci# available, falling back on a portable substitute otherwise. 964616d0f9Sopenharmony_ciif 974616d0f9Sopenharmony_ci case $BASH_VERSION in 984616d0f9Sopenharmony_ci ?*) :;; 994616d0f9Sopenharmony_ci '') 1004616d0f9Sopenharmony_ci # '; exit' should be redundant, but Dash doesn't properly fail without it. 1014616d0f9Sopenharmony_ci (eval 'set --; select x; do break; done; exit') <>/dev/null 2>&0 1024616d0f9Sopenharmony_ci esac 1034616d0f9Sopenharmony_cithen 1044616d0f9Sopenharmony_ci # Do this inside 'eval', as otherwise the shell might exit when parsing it 1054616d0f9Sopenharmony_ci # even though it is never executed. 1064616d0f9Sopenharmony_ci eval ' 1074616d0f9Sopenharmony_ci doselect() { 1084616d0f9Sopenharmony_ci select select_result 1094616d0f9Sopenharmony_ci do 1104616d0f9Sopenharmony_ci case $select_result in 1114616d0f9Sopenharmony_ci "") echo >&2 "Please enter a number in range.";; 1124616d0f9Sopenharmony_ci ?*) break 1134616d0f9Sopenharmony_ci esac 1144616d0f9Sopenharmony_ci done || exit 1154616d0f9Sopenharmony_ci } 1164616d0f9Sopenharmony_ci ' 1174616d0f9Sopenharmony_cielse 1184616d0f9Sopenharmony_ci doselect() { 1194616d0f9Sopenharmony_ci # Field width of the prompt numbers. 1204616d0f9Sopenharmony_ci print_nargs_length="BEGIN {print length(\"$#\");}" 1214616d0f9Sopenharmony_ci select_width=`$AWK "$print_nargs_length"` 1224616d0f9Sopenharmony_ci 1234616d0f9Sopenharmony_ci select_i= 1244616d0f9Sopenharmony_ci 1254616d0f9Sopenharmony_ci while : 1264616d0f9Sopenharmony_ci do 1274616d0f9Sopenharmony_ci case $select_i in 1284616d0f9Sopenharmony_ci '') 1294616d0f9Sopenharmony_ci select_i=0 1304616d0f9Sopenharmony_ci for select_word 1314616d0f9Sopenharmony_ci do 1324616d0f9Sopenharmony_ci select_i=`$AWK "BEGIN { print $select_i + 1 }"` 1334616d0f9Sopenharmony_ci printf >&2 "%${select_width}d) %s\\n" $select_i "$select_word" 1344616d0f9Sopenharmony_ci done;; 1354616d0f9Sopenharmony_ci *[!0-9]*) 1364616d0f9Sopenharmony_ci echo >&2 'Please enter a number in range.';; 1374616d0f9Sopenharmony_ci *) 1384616d0f9Sopenharmony_ci if test 1 -le $select_i && test $select_i -le $#; then 1394616d0f9Sopenharmony_ci shift `$AWK "BEGIN { print $select_i - 1 }"` 1404616d0f9Sopenharmony_ci select_result=$1 1414616d0f9Sopenharmony_ci break 1424616d0f9Sopenharmony_ci fi 1434616d0f9Sopenharmony_ci echo >&2 'Please enter a number in range.' 1444616d0f9Sopenharmony_ci esac 1454616d0f9Sopenharmony_ci 1464616d0f9Sopenharmony_ci # Prompt and read input. 1474616d0f9Sopenharmony_ci printf >&2 %s "${PS3-#? }" 1484616d0f9Sopenharmony_ci read select_i || exit 1494616d0f9Sopenharmony_ci done 1504616d0f9Sopenharmony_ci } 1514616d0f9Sopenharmony_cifi 1524616d0f9Sopenharmony_ci 1534616d0f9Sopenharmony_ciwhile getopts c:n:t:-: opt 1544616d0f9Sopenharmony_cido 1554616d0f9Sopenharmony_ci case $opt$OPTARG in 1564616d0f9Sopenharmony_ci c*) 1574616d0f9Sopenharmony_ci coord=$OPTARG;; 1584616d0f9Sopenharmony_ci n*) 1594616d0f9Sopenharmony_ci location_limit=$OPTARG;; 1604616d0f9Sopenharmony_ci t*) # Undocumented option, used for developer testing. 1614616d0f9Sopenharmony_ci zonetabtype=$OPTARG;; 1624616d0f9Sopenharmony_ci -help) 1634616d0f9Sopenharmony_ci exec echo "$usage";; 1644616d0f9Sopenharmony_ci -version) 1654616d0f9Sopenharmony_ci exec echo "tzselect $PKGVERSION$TZVERSION";; 1664616d0f9Sopenharmony_ci -*) 1674616d0f9Sopenharmony_ci say >&2 "$0: -$opt$OPTARG: unknown option; try '$0 --help'"; exit 1;; 1684616d0f9Sopenharmony_ci *) 1694616d0f9Sopenharmony_ci say >&2 "$0: try '$0 --help'"; exit 1 1704616d0f9Sopenharmony_ci esac 1714616d0f9Sopenharmony_cidone 1724616d0f9Sopenharmony_ci 1734616d0f9Sopenharmony_cishift `$AWK "BEGIN { print $OPTIND - 1 }"` 1744616d0f9Sopenharmony_cicase $# in 1754616d0f9Sopenharmony_ci0) ;; 1764616d0f9Sopenharmony_ci*) say >&2 "$0: $1: unknown argument"; exit 1 1774616d0f9Sopenharmony_ciesac 1784616d0f9Sopenharmony_ci 1794616d0f9Sopenharmony_ci# translit=true to try transliteration. 1804616d0f9Sopenharmony_ci# This is false if U+12345 CUNEIFORM SIGN URU TIMES KI has length 1 1814616d0f9Sopenharmony_ci# which means awk (and presumably the shell) do not need transliteration. 1824616d0f9Sopenharmony_ciif $AWK 'BEGIN { u12345 = "\360\222\215\205"; exit length(u12345) == 1 }'; then 1834616d0f9Sopenharmony_ci translit=true 1844616d0f9Sopenharmony_cielse 1854616d0f9Sopenharmony_ci translit=false 1864616d0f9Sopenharmony_cifi 1874616d0f9Sopenharmony_ci 1884616d0f9Sopenharmony_ci# Read into shell variable $1 the contents of file $2. 1894616d0f9Sopenharmony_ci# Convert to the current locale's encoding if possible, 1904616d0f9Sopenharmony_ci# as the shell aligns columns better that way. 1914616d0f9Sopenharmony_ci# If GNU iconv's //TRANSLIT does not work, fall back on POSIXish iconv; 1924616d0f9Sopenharmony_ci# if that does not work, fall back on 'cat'. 1934616d0f9Sopenharmony_ciread_file() { 1944616d0f9Sopenharmony_ci { $translit && { 1954616d0f9Sopenharmony_ci eval "$1=\`(iconv -f UTF-8 -t //TRANSLIT) 2>/dev/null <\"\$2\"\`" || 1964616d0f9Sopenharmony_ci eval "$1=\`(iconv -f UTF-8) 2>/dev/null <\"\$2\"\`" 1974616d0f9Sopenharmony_ci }; } || 1984616d0f9Sopenharmony_ci eval "$1=\`cat <\"\$2\"\`" || { 1994616d0f9Sopenharmony_ci say >&2 "$0: time zone files are not set up correctly" 2004616d0f9Sopenharmony_ci exit 1 2014616d0f9Sopenharmony_ci } 2024616d0f9Sopenharmony_ci} 2034616d0f9Sopenharmony_ciread_file TZ_COUNTRY_TABLE "$TZDIR/iso3166.tab" 2044616d0f9Sopenharmony_ciread_file TZ_ZONETABTYPE_TABLE "$TZDIR/$zonetabtype.tab" 2054616d0f9Sopenharmony_ciTZ_ZONENOW_TABLE= 2064616d0f9Sopenharmony_ci 2074616d0f9Sopenharmony_cinewline=' 2084616d0f9Sopenharmony_ci' 2094616d0f9Sopenharmony_ciIFS=$newline 2104616d0f9Sopenharmony_ci 2114616d0f9Sopenharmony_ci# Awk script to output a country list. 2124616d0f9Sopenharmony_cioutput_country_list=' 2134616d0f9Sopenharmony_ci BEGIN { 2144616d0f9Sopenharmony_ci continent_re = substr(ARGV[1], 2) 2154616d0f9Sopenharmony_ci TZ_COUNTRY_TABLE = substr(ARGV[2], 2) 2164616d0f9Sopenharmony_ci TZ_ZONE_TABLE = substr(ARGV[3], 2) 2174616d0f9Sopenharmony_ci ARGV[1] = ARGV[2] = ARGV[3] = "" 2184616d0f9Sopenharmony_ci FS = "\t" 2194616d0f9Sopenharmony_ci nlines = split(TZ_ZONE_TABLE, line, /\n/) 2204616d0f9Sopenharmony_ci for (iline = 1; iline <= nlines; iline++) { 2214616d0f9Sopenharmony_ci $0 = line[iline] 2224616d0f9Sopenharmony_ci commentary = $0 ~ /^#@/ 2234616d0f9Sopenharmony_ci if (commentary) { 2244616d0f9Sopenharmony_ci if ($0 !~ /^#@/) 2254616d0f9Sopenharmony_ci continue 2264616d0f9Sopenharmony_ci col1ccs = substr($1, 3) 2274616d0f9Sopenharmony_ci conts = $2 2284616d0f9Sopenharmony_ci } else { 2294616d0f9Sopenharmony_ci col1ccs = $1 2304616d0f9Sopenharmony_ci conts = $3 2314616d0f9Sopenharmony_ci } 2324616d0f9Sopenharmony_ci ncc = split(col1ccs, cc, /,/) 2334616d0f9Sopenharmony_ci ncont = split(conts, cont, /,/) 2344616d0f9Sopenharmony_ci for (i = 1; i <= ncc; i++) { 2354616d0f9Sopenharmony_ci elsewhere = commentary 2364616d0f9Sopenharmony_ci for (ci = 1; ci <= ncont; ci++) { 2374616d0f9Sopenharmony_ci if (cont[ci] ~ continent_re) { 2384616d0f9Sopenharmony_ci if (!cc_seen[cc[i]]++) 2394616d0f9Sopenharmony_ci cc_list[++ccs] = cc[i] 2404616d0f9Sopenharmony_ci elsewhere = 0 2414616d0f9Sopenharmony_ci } 2424616d0f9Sopenharmony_ci } 2434616d0f9Sopenharmony_ci if (elsewhere) 2444616d0f9Sopenharmony_ci for (i = 1; i <= ncc; i++) 2454616d0f9Sopenharmony_ci cc_elsewhere[cc[i]] = 1 2464616d0f9Sopenharmony_ci } 2474616d0f9Sopenharmony_ci } 2484616d0f9Sopenharmony_ci nlines = split(TZ_COUNTRY_TABLE, line, /\n/) 2494616d0f9Sopenharmony_ci for (i = 1; i <= nlines; i++) { 2504616d0f9Sopenharmony_ci $0 = line[i] 2514616d0f9Sopenharmony_ci if ($0 !~ /^#/) 2524616d0f9Sopenharmony_ci cc_name[$1] = $2 2534616d0f9Sopenharmony_ci } 2544616d0f9Sopenharmony_ci for (i = 1; i <= ccs; i++) { 2554616d0f9Sopenharmony_ci country = cc_list[i] 2564616d0f9Sopenharmony_ci if (cc_elsewhere[country]) 2574616d0f9Sopenharmony_ci continue 2584616d0f9Sopenharmony_ci if (cc_name[country]) 2594616d0f9Sopenharmony_ci country = cc_name[country] 2604616d0f9Sopenharmony_ci print country 2614616d0f9Sopenharmony_ci } 2624616d0f9Sopenharmony_ci } 2634616d0f9Sopenharmony_ci' 2644616d0f9Sopenharmony_ci 2654616d0f9Sopenharmony_ci# Awk script to process a time zone table and output the same table, 2664616d0f9Sopenharmony_ci# with each row preceded by its distance from 'here'. 2674616d0f9Sopenharmony_ci# If output_times is set, each row is instead preceded by its local time 2684616d0f9Sopenharmony_ci# and any apostrophes are escaped for the shell. 2694616d0f9Sopenharmony_cioutput_distances_or_times=' 2704616d0f9Sopenharmony_ci BEGIN { 2714616d0f9Sopenharmony_ci coord = substr(ARGV[1], 2) 2724616d0f9Sopenharmony_ci TZ_COUNTRY_TABLE = substr(ARGV[2], 2) 2734616d0f9Sopenharmony_ci TZ_ZONE_TABLE = substr(ARGV[3], 2) 2744616d0f9Sopenharmony_ci ARGV[1] = ARGV[2] = ARGV[3] = "" 2754616d0f9Sopenharmony_ci FS = "\t" 2764616d0f9Sopenharmony_ci if (!output_times) { 2774616d0f9Sopenharmony_ci nlines = split(TZ_COUNTRY_TABLE, line, /\n/) 2784616d0f9Sopenharmony_ci for (i = 1; i <= nlines; i++) { 2794616d0f9Sopenharmony_ci $0 = line[i] 2804616d0f9Sopenharmony_ci if ($0 ~ /^#/) 2814616d0f9Sopenharmony_ci continue 2824616d0f9Sopenharmony_ci country[$1] = $2 2834616d0f9Sopenharmony_ci } 2844616d0f9Sopenharmony_ci country["US"] = "US" # Otherwise the strings get too long. 2854616d0f9Sopenharmony_ci } 2864616d0f9Sopenharmony_ci } 2874616d0f9Sopenharmony_ci function abs(x) { 2884616d0f9Sopenharmony_ci return x < 0 ? -x : x; 2894616d0f9Sopenharmony_ci } 2904616d0f9Sopenharmony_ci function min(x, y) { 2914616d0f9Sopenharmony_ci return x < y ? x : y; 2924616d0f9Sopenharmony_ci } 2934616d0f9Sopenharmony_ci function convert_coord(coord, deg, minute, ilen, sign, sec) { 2944616d0f9Sopenharmony_ci if (coord ~ /^[-+]?[0-9]?[0-9][0-9][0-9][0-9][0-9][0-9]([^0-9]|$)/) { 2954616d0f9Sopenharmony_ci degminsec = coord 2964616d0f9Sopenharmony_ci intdeg = degminsec < 0 ? -int(-degminsec / 10000) : int(degminsec / 10000) 2974616d0f9Sopenharmony_ci minsec = degminsec - intdeg * 10000 2984616d0f9Sopenharmony_ci intmin = minsec < 0 ? -int(-minsec / 100) : int(minsec / 100) 2994616d0f9Sopenharmony_ci sec = minsec - intmin * 100 3004616d0f9Sopenharmony_ci deg = (intdeg * 3600 + intmin * 60 + sec) / 3600 3014616d0f9Sopenharmony_ci } else if (coord ~ /^[-+]?[0-9]?[0-9][0-9][0-9][0-9]([^0-9]|$)/) { 3024616d0f9Sopenharmony_ci degmin = coord 3034616d0f9Sopenharmony_ci intdeg = degmin < 0 ? -int(-degmin / 100) : int(degmin / 100) 3044616d0f9Sopenharmony_ci minute = degmin - intdeg * 100 3054616d0f9Sopenharmony_ci deg = (intdeg * 60 + minute) / 60 3064616d0f9Sopenharmony_ci } else 3074616d0f9Sopenharmony_ci deg = coord 3084616d0f9Sopenharmony_ci return deg * 0.017453292519943296 3094616d0f9Sopenharmony_ci } 3104616d0f9Sopenharmony_ci function convert_latitude(coord) { 3114616d0f9Sopenharmony_ci match(coord, /..*[-+]/) 3124616d0f9Sopenharmony_ci return convert_coord(substr(coord, 1, RLENGTH - 1)) 3134616d0f9Sopenharmony_ci } 3144616d0f9Sopenharmony_ci function convert_longitude(coord) { 3154616d0f9Sopenharmony_ci match(coord, /..*[-+]/) 3164616d0f9Sopenharmony_ci return convert_coord(substr(coord, RLENGTH)) 3174616d0f9Sopenharmony_ci } 3184616d0f9Sopenharmony_ci # Great-circle distance between points with given latitude and longitude. 3194616d0f9Sopenharmony_ci # Inputs and output are in radians. This uses the great-circle special 3204616d0f9Sopenharmony_ci # case of the Vicenty formula for distances on ellipsoids. 3214616d0f9Sopenharmony_ci function gcdist(lat1, long1, lat2, long2, dlong, x, y, num, denom) { 3224616d0f9Sopenharmony_ci dlong = long2 - long1 3234616d0f9Sopenharmony_ci x = cos(lat2) * sin(dlong) 3244616d0f9Sopenharmony_ci y = cos(lat1) * sin(lat2) - sin(lat1) * cos(lat2) * cos(dlong) 3254616d0f9Sopenharmony_ci num = sqrt(x * x + y * y) 3264616d0f9Sopenharmony_ci denom = sin(lat1) * sin(lat2) + cos(lat1) * cos(lat2) * cos(dlong) 3274616d0f9Sopenharmony_ci return atan2(num, denom) 3284616d0f9Sopenharmony_ci } 3294616d0f9Sopenharmony_ci # Parallel distance between points with given latitude and longitude. 3304616d0f9Sopenharmony_ci # This is the product of the longitude difference and the cosine 3314616d0f9Sopenharmony_ci # of the latitude of the point that is further from the equator. 3324616d0f9Sopenharmony_ci # I.e., it considers longitudes to be further apart if they are 3334616d0f9Sopenharmony_ci # nearer the equator. 3344616d0f9Sopenharmony_ci function pardist(lat1, long1, lat2, long2) { 3354616d0f9Sopenharmony_ci return abs(long1 - long2) * min(cos(lat1), cos(lat2)) 3364616d0f9Sopenharmony_ci } 3374616d0f9Sopenharmony_ci # The distance function is the sum of the great-circle distance and 3384616d0f9Sopenharmony_ci # the parallel distance. It could be weighted. 3394616d0f9Sopenharmony_ci function dist(lat1, long1, lat2, long2) { 3404616d0f9Sopenharmony_ci return gcdist(lat1, long1, lat2, long2) + pardist(lat1, long1, lat2, long2) 3414616d0f9Sopenharmony_ci } 3424616d0f9Sopenharmony_ci BEGIN { 3434616d0f9Sopenharmony_ci coord_lat = convert_latitude(coord) 3444616d0f9Sopenharmony_ci coord_long = convert_longitude(coord) 3454616d0f9Sopenharmony_ci nlines = split(TZ_ZONE_TABLE, line, /\n/) 3464616d0f9Sopenharmony_ci for (h = 1; h <= nlines; h++) { 3474616d0f9Sopenharmony_ci $0 = line[h] 3484616d0f9Sopenharmony_ci if ($0 ~ /^#/) 3494616d0f9Sopenharmony_ci continue 3504616d0f9Sopenharmony_ci inline[inlines++] = $0 3514616d0f9Sopenharmony_ci ncc = split($1, cc, /,/) 3524616d0f9Sopenharmony_ci for (i = 1; i <= ncc; i++) 3534616d0f9Sopenharmony_ci cc_used[cc[i]]++ 3544616d0f9Sopenharmony_ci } 3554616d0f9Sopenharmony_ci for (h = 0; h < inlines; h++) { 3564616d0f9Sopenharmony_ci $0 = inline[h] 3574616d0f9Sopenharmony_ci outline = $1 "\t" $2 "\t" $3 3584616d0f9Sopenharmony_ci sep = "\t" 3594616d0f9Sopenharmony_ci ncc = split($1, cc, /,/) 3604616d0f9Sopenharmony_ci split("", item_seen) 3614616d0f9Sopenharmony_ci item_seen[""] = 1 3624616d0f9Sopenharmony_ci for (i = 1; i <= ncc; i++) { 3634616d0f9Sopenharmony_ci item = cc_used[cc[i]] <= 1 ? country[cc[i]] : $4 3644616d0f9Sopenharmony_ci if (item_seen[item]++) 3654616d0f9Sopenharmony_ci continue 3664616d0f9Sopenharmony_ci outline = outline sep item 3674616d0f9Sopenharmony_ci sep = "; " 3684616d0f9Sopenharmony_ci } 3694616d0f9Sopenharmony_ci if (output_times) { 3704616d0f9Sopenharmony_ci fmt = "TZ='\''%s'\'' date +'\''%d %%Y %%m %%d %%H:%%M %%a %%b\t%s'\''\n" 3714616d0f9Sopenharmony_ci gsub(/'\''/, "&\\\\&&", outline) 3724616d0f9Sopenharmony_ci printf fmt, $3, h, outline 3734616d0f9Sopenharmony_ci } else { 3744616d0f9Sopenharmony_ci here_lat = convert_latitude($2) 3754616d0f9Sopenharmony_ci here_long = convert_longitude($2) 3764616d0f9Sopenharmony_ci printf "%g\t%s\n", dist(coord_lat, coord_long, here_lat, here_long), \ 3774616d0f9Sopenharmony_ci outline 3784616d0f9Sopenharmony_ci } 3794616d0f9Sopenharmony_ci } 3804616d0f9Sopenharmony_ci } 3814616d0f9Sopenharmony_ci' 3824616d0f9Sopenharmony_ci 3834616d0f9Sopenharmony_ci# Begin the main loop. We come back here if the user wants to retry. 3844616d0f9Sopenharmony_ciwhile 3854616d0f9Sopenharmony_ci 3864616d0f9Sopenharmony_ci echo >&2 'Please identify a location' \ 3874616d0f9Sopenharmony_ci 'so that time zone rules can be set correctly.' 3884616d0f9Sopenharmony_ci 3894616d0f9Sopenharmony_ci continent= 3904616d0f9Sopenharmony_ci country= 3914616d0f9Sopenharmony_ci country_result= 3924616d0f9Sopenharmony_ci region= 3934616d0f9Sopenharmony_ci time= 3944616d0f9Sopenharmony_ci TZ_ZONE_TABLE=$TZ_ZONETABTYPE_TABLE 3954616d0f9Sopenharmony_ci 3964616d0f9Sopenharmony_ci case $coord in 3974616d0f9Sopenharmony_ci ?*) 3984616d0f9Sopenharmony_ci continent=coord;; 3994616d0f9Sopenharmony_ci '') 4004616d0f9Sopenharmony_ci 4014616d0f9Sopenharmony_ci # Ask the user for continent or ocean. 4024616d0f9Sopenharmony_ci 4034616d0f9Sopenharmony_ci echo >&2 \ 4044616d0f9Sopenharmony_ci 'Please select a continent, ocean, "coord", "TZ", "time", or "now".' 4054616d0f9Sopenharmony_ci 4064616d0f9Sopenharmony_ci quoted_continents=` 4074616d0f9Sopenharmony_ci $AWK ' 4084616d0f9Sopenharmony_ci function handle_entry(entry) { 4094616d0f9Sopenharmony_ci entry = substr(entry, 1, index(entry, "/") - 1) 4104616d0f9Sopenharmony_ci if (entry == "America") 4114616d0f9Sopenharmony_ci entry = entry "s" 4124616d0f9Sopenharmony_ci if (entry ~ /^(Arctic|Atlantic|Indian|Pacific)$/) 4134616d0f9Sopenharmony_ci entry = entry " Ocean" 4144616d0f9Sopenharmony_ci printf "'\''%s'\''\n", entry 4154616d0f9Sopenharmony_ci } 4164616d0f9Sopenharmony_ci BEGIN { 4174616d0f9Sopenharmony_ci TZ_ZONETABTYPE_TABLE = substr(ARGV[1], 2) 4184616d0f9Sopenharmony_ci ARGV[1] = "" 4194616d0f9Sopenharmony_ci FS = "\t" 4204616d0f9Sopenharmony_ci nlines = split(TZ_ZONETABTYPE_TABLE, line, /\n/) 4214616d0f9Sopenharmony_ci for (i = 1; i <= nlines; i++) { 4224616d0f9Sopenharmony_ci $0 = line[i] 4234616d0f9Sopenharmony_ci if ($0 ~ /^[^#]/) 4244616d0f9Sopenharmony_ci handle_entry($3) 4254616d0f9Sopenharmony_ci else if ($0 ~ /^#@/) { 4264616d0f9Sopenharmony_ci ncont = split($2, cont, /,/) 4274616d0f9Sopenharmony_ci for (ci = 1; ci <= ncont; ci++) 4284616d0f9Sopenharmony_ci handle_entry(cont[ci]) 4294616d0f9Sopenharmony_ci } 4304616d0f9Sopenharmony_ci } 4314616d0f9Sopenharmony_ci } 4324616d0f9Sopenharmony_ci ' ="$TZ_ZONETABTYPE_TABLE" | 4334616d0f9Sopenharmony_ci sort -u | 4344616d0f9Sopenharmony_ci tr '\n' ' ' 4354616d0f9Sopenharmony_ci echo '' 4364616d0f9Sopenharmony_ci ` 4374616d0f9Sopenharmony_ci 4384616d0f9Sopenharmony_ci eval ' 4394616d0f9Sopenharmony_ci doselect '"$quoted_continents"' \ 4404616d0f9Sopenharmony_ci "coord - I want to use geographical coordinates." \ 4414616d0f9Sopenharmony_ci "TZ - I want to specify the timezone using a POSIX.1-2017 TZ string." \ 4424616d0f9Sopenharmony_ci "time - I know local time already." \ 4434616d0f9Sopenharmony_ci "now - Like \"time\", but configure only for timestamps from now on." 4444616d0f9Sopenharmony_ci continent=$select_result 4454616d0f9Sopenharmony_ci case $continent in 4464616d0f9Sopenharmony_ci Americas) continent=America;; 4474616d0f9Sopenharmony_ci *) 4484616d0f9Sopenharmony_ci # Get the first word of $continent. Path expansion is disabled 4494616d0f9Sopenharmony_ci # so this works even with "*", which should not happen. 4504616d0f9Sopenharmony_ci IFS=" " 4514616d0f9Sopenharmony_ci for continent in $continent ""; do break; done 4524616d0f9Sopenharmony_ci IFS=$newline;; 4534616d0f9Sopenharmony_ci esac 4544616d0f9Sopenharmony_ci case $zonetabtype,$continent in 4554616d0f9Sopenharmony_ci zonenow,*) ;; 4564616d0f9Sopenharmony_ci *,now) 4574616d0f9Sopenharmony_ci ${TZ_ZONENOW_TABLE:+:} read_file TZ_ZONENOW_TABLE "$TZDIR/zonenow.tab" 4584616d0f9Sopenharmony_ci TZ_ZONE_TABLE=$TZ_ZONENOW_TABLE 4594616d0f9Sopenharmony_ci esac 4604616d0f9Sopenharmony_ci ' 4614616d0f9Sopenharmony_ci esac 4624616d0f9Sopenharmony_ci 4634616d0f9Sopenharmony_ci case $continent in 4644616d0f9Sopenharmony_ci TZ) 4654616d0f9Sopenharmony_ci # Ask the user for a POSIX.1-2017 TZ string. Check that it conforms. 4664616d0f9Sopenharmony_ci check_POSIX_TZ_string=' 4674616d0f9Sopenharmony_ci BEGIN { 4684616d0f9Sopenharmony_ci tz = substr(ARGV[1], 2) 4694616d0f9Sopenharmony_ci ARGV[1] = "" 4704616d0f9Sopenharmony_ci tzname = ("(<[[:alnum:]+-][[:alnum:]+-][[:alnum:]+-]+>" \ 4714616d0f9Sopenharmony_ci "|[[:alpha:]][[:alpha:]][[:alpha:]]+)") 4724616d0f9Sopenharmony_ci time = ("(2[0-4]|[0-1]?[0-9])" \ 4734616d0f9Sopenharmony_ci "(:[0-5][0-9](:[0-5][0-9])?)?") 4744616d0f9Sopenharmony_ci offset = "[-+]?" time 4754616d0f9Sopenharmony_ci mdate = "M([1-9]|1[0-2])\\.[1-5]\\.[0-6]" 4764616d0f9Sopenharmony_ci jdate = ("((J[1-9]|[0-9]|J?[1-9][0-9]" \ 4774616d0f9Sopenharmony_ci "|J?[1-2][0-9][0-9])|J?3[0-5][0-9]|J?36[0-5])") 4784616d0f9Sopenharmony_ci datetime = ",(" mdate "|" jdate ")(/" time ")?" 4794616d0f9Sopenharmony_ci tzpattern = ("^(:.*|" tzname offset "(" tzname \ 4804616d0f9Sopenharmony_ci "(" offset ")?(" datetime datetime ")?)?)$") 4814616d0f9Sopenharmony_ci exit tz ~ tzpattern 4824616d0f9Sopenharmony_ci } 4834616d0f9Sopenharmony_ci ' 4844616d0f9Sopenharmony_ci 4854616d0f9Sopenharmony_ci while 4864616d0f9Sopenharmony_ci echo >&2 'Please enter the desired value' \ 4874616d0f9Sopenharmony_ci 'of the TZ environment variable.' 4884616d0f9Sopenharmony_ci echo >&2 'For example, AEST-10 is abbreviated' \ 4894616d0f9Sopenharmony_ci 'AEST and is 10 hours' 4904616d0f9Sopenharmony_ci echo >&2 'ahead (east) of Greenwich,' \ 4914616d0f9Sopenharmony_ci 'with no daylight saving time.' 4924616d0f9Sopenharmony_ci read tz 4934616d0f9Sopenharmony_ci $AWK "$check_POSIX_TZ_string" ="$tz" 4944616d0f9Sopenharmony_ci do 4954616d0f9Sopenharmony_ci say >&2 "'$tz' is not a conforming POSIX.1-2017 timezone string." 4964616d0f9Sopenharmony_ci done 4974616d0f9Sopenharmony_ci TZ_for_date=$tz;; 4984616d0f9Sopenharmony_ci *) 4994616d0f9Sopenharmony_ci case $continent in 5004616d0f9Sopenharmony_ci coord) 5014616d0f9Sopenharmony_ci case $coord in 5024616d0f9Sopenharmony_ci '') 5034616d0f9Sopenharmony_ci echo >&2 'Please enter coordinates' \ 5044616d0f9Sopenharmony_ci 'in ISO 6709 notation.' 5054616d0f9Sopenharmony_ci echo >&2 'For example, +4042-07403 stands for' 5064616d0f9Sopenharmony_ci echo >&2 '40 degrees 42 minutes north,' \ 5074616d0f9Sopenharmony_ci '74 degrees 3 minutes west.' 5084616d0f9Sopenharmony_ci read coord 5094616d0f9Sopenharmony_ci esac 5104616d0f9Sopenharmony_ci distance_table=` 5114616d0f9Sopenharmony_ci $AWK \ 5124616d0f9Sopenharmony_ci "$output_distances_or_times" \ 5134616d0f9Sopenharmony_ci ="$coord" ="$TZ_COUNTRY_TABLE" ="$TZ_ZONE_TABLE" | 5144616d0f9Sopenharmony_ci sort -n | 5154616d0f9Sopenharmony_ci $AWK "{print} NR == $location_limit { exit }" 5164616d0f9Sopenharmony_ci ` 5174616d0f9Sopenharmony_ci regions=` 5184616d0f9Sopenharmony_ci $AWK ' 5194616d0f9Sopenharmony_ci BEGIN { 5204616d0f9Sopenharmony_ci distance_table = substr(ARGV[1], 2) 5214616d0f9Sopenharmony_ci ARGV[1] = "" 5224616d0f9Sopenharmony_ci nlines = split(distance_table, line, /\n/) 5234616d0f9Sopenharmony_ci for (nr = 1; nr <= nlines; nr++) { 5244616d0f9Sopenharmony_ci nf = split(line[nr], f, /\t/) 5254616d0f9Sopenharmony_ci print f[nf] 5264616d0f9Sopenharmony_ci } 5274616d0f9Sopenharmony_ci } 5284616d0f9Sopenharmony_ci ' ="$distance_table" 5294616d0f9Sopenharmony_ci ` 5304616d0f9Sopenharmony_ci echo >&2 'Please select one of the following timezones,' 5314616d0f9Sopenharmony_ci echo >&2 'listed roughly in increasing order' \ 5324616d0f9Sopenharmony_ci "of distance from $coord". 5334616d0f9Sopenharmony_ci doselect $regions 5344616d0f9Sopenharmony_ci region=$select_result 5354616d0f9Sopenharmony_ci tz=` 5364616d0f9Sopenharmony_ci $AWK ' 5374616d0f9Sopenharmony_ci BEGIN { 5384616d0f9Sopenharmony_ci distance_table = substr(ARGV[1], 2) 5394616d0f9Sopenharmony_ci region = substr(ARGV[2], 2) 5404616d0f9Sopenharmony_ci ARGV[1] = ARGV[2] = "" 5414616d0f9Sopenharmony_ci nlines = split(distance_table, line, /\n/) 5424616d0f9Sopenharmony_ci for (nr = 1; nr <= nlines; nr++) { 5434616d0f9Sopenharmony_ci nf = split(line[nr], f, /\t/) 5444616d0f9Sopenharmony_ci if (f[nf] == region) 5454616d0f9Sopenharmony_ci print f[4] 5464616d0f9Sopenharmony_ci } 5474616d0f9Sopenharmony_ci } 5484616d0f9Sopenharmony_ci ' ="$distance_table" ="$region" 5494616d0f9Sopenharmony_ci `;; 5504616d0f9Sopenharmony_ci *) 5514616d0f9Sopenharmony_ci case $continent in 5524616d0f9Sopenharmony_ci now|time) 5534616d0f9Sopenharmony_ci minute_format='%a %b %d %H:%M' 5544616d0f9Sopenharmony_ci old_minute=`TZ=UTC0 date +"$minute_format"` 5554616d0f9Sopenharmony_ci for i in 1 2 3 5564616d0f9Sopenharmony_ci do 5574616d0f9Sopenharmony_ci time_table_command=` 5584616d0f9Sopenharmony_ci $AWK \ 5594616d0f9Sopenharmony_ci -v output_times=1 \ 5604616d0f9Sopenharmony_ci "$output_distances_or_times" \ 5614616d0f9Sopenharmony_ci = = ="$TZ_ZONE_TABLE" 5624616d0f9Sopenharmony_ci ` 5634616d0f9Sopenharmony_ci time_table=`eval "$time_table_command"` 5644616d0f9Sopenharmony_ci new_minute=`TZ=UTC0 date +"$minute_format"` 5654616d0f9Sopenharmony_ci case $old_minute in 5664616d0f9Sopenharmony_ci "$new_minute") break 5674616d0f9Sopenharmony_ci esac 5684616d0f9Sopenharmony_ci old_minute=$new_minute 5694616d0f9Sopenharmony_ci done 5704616d0f9Sopenharmony_ci echo >&2 "The system says Universal Time is $new_minute." 5714616d0f9Sopenharmony_ci echo >&2 "Assuming that's correct, what is the local time?" 5724616d0f9Sopenharmony_ci sorted_table=`say "$time_table" | sort -k2n -k2,5 -k1n` || { 5734616d0f9Sopenharmony_ci say >&2 "$0: cannot sort time table" 5744616d0f9Sopenharmony_ci exit 1 5754616d0f9Sopenharmony_ci } 5764616d0f9Sopenharmony_ci eval doselect ` 5774616d0f9Sopenharmony_ci $AWK ' 5784616d0f9Sopenharmony_ci BEGIN { 5794616d0f9Sopenharmony_ci sorted_table = substr(ARGV[1], 2) 5804616d0f9Sopenharmony_ci ARGV[1] = "" 5814616d0f9Sopenharmony_ci nlines = split(sorted_table, line, /\n/) 5824616d0f9Sopenharmony_ci for (i = 1; i <= nlines; i++) { 5834616d0f9Sopenharmony_ci $0 = line[i] 5844616d0f9Sopenharmony_ci outline = $6 " " $7 " " $4 " " $5 5854616d0f9Sopenharmony_ci if (outline == oldline) 5864616d0f9Sopenharmony_ci continue 5874616d0f9Sopenharmony_ci oldline = outline 5884616d0f9Sopenharmony_ci gsub(/'\''/, "&\\\\&&", outline) 5894616d0f9Sopenharmony_ci printf "'\''%s'\''\n", outline 5904616d0f9Sopenharmony_ci } 5914616d0f9Sopenharmony_ci } 5924616d0f9Sopenharmony_ci ' ="$sorted_table" 5934616d0f9Sopenharmony_ci ` 5944616d0f9Sopenharmony_ci time=$select_result 5954616d0f9Sopenharmony_ci continent_re='^' 5964616d0f9Sopenharmony_ci zone_table=` 5974616d0f9Sopenharmony_ci $AWK ' 5984616d0f9Sopenharmony_ci BEGIN { 5994616d0f9Sopenharmony_ci time = substr(ARGV[1], 2) 6004616d0f9Sopenharmony_ci time_table = substr(ARGV[2], 2) 6014616d0f9Sopenharmony_ci ARGV[1] = ARGV[2] = "" 6024616d0f9Sopenharmony_ci nlines = split(time_table, line, /\n/) 6034616d0f9Sopenharmony_ci for (i = 1; i <= nlines; i++) { 6044616d0f9Sopenharmony_ci $0 = line[i] 6054616d0f9Sopenharmony_ci if ($6 " " $7 " " $4 " " $5 == time) { 6064616d0f9Sopenharmony_ci sub(/[^\t]*\t/, "") 6074616d0f9Sopenharmony_ci print 6084616d0f9Sopenharmony_ci } 6094616d0f9Sopenharmony_ci } 6104616d0f9Sopenharmony_ci } 6114616d0f9Sopenharmony_ci ' ="$time" ="$time_table" 6124616d0f9Sopenharmony_ci ` 6134616d0f9Sopenharmony_ci countries=` 6144616d0f9Sopenharmony_ci $AWK \ 6154616d0f9Sopenharmony_ci "$output_country_list" \ 6164616d0f9Sopenharmony_ci ="$continent_re" ="$TZ_COUNTRY_TABLE" ="$zone_table" | 6174616d0f9Sopenharmony_ci sort -f 6184616d0f9Sopenharmony_ci ` 6194616d0f9Sopenharmony_ci ;; 6204616d0f9Sopenharmony_ci *) 6214616d0f9Sopenharmony_ci continent_re="^$continent/" 6224616d0f9Sopenharmony_ci zone_table=$TZ_ZONE_TABLE 6234616d0f9Sopenharmony_ci esac 6244616d0f9Sopenharmony_ci 6254616d0f9Sopenharmony_ci # Get list of names of countries in the continent or ocean. 6264616d0f9Sopenharmony_ci countries=` 6274616d0f9Sopenharmony_ci $AWK \ 6284616d0f9Sopenharmony_ci "$output_country_list" \ 6294616d0f9Sopenharmony_ci ="$continent_re" ="$TZ_COUNTRY_TABLE" ="$zone_table" | 6304616d0f9Sopenharmony_ci sort -f 6314616d0f9Sopenharmony_ci ` 6324616d0f9Sopenharmony_ci # If all zone table entries have comments, and there are 6334616d0f9Sopenharmony_ci # at most 22 entries, asked based on those comments. 6344616d0f9Sopenharmony_ci # This fits the prompt onto old-fashioned 24-line screens. 6354616d0f9Sopenharmony_ci regions=` 6364616d0f9Sopenharmony_ci $AWK ' 6374616d0f9Sopenharmony_ci BEGIN { 6384616d0f9Sopenharmony_ci TZ_ZONE_TABLE = substr(ARGV[1], 2) 6394616d0f9Sopenharmony_ci ARGV[1] = "" 6404616d0f9Sopenharmony_ci FS = "\t" 6414616d0f9Sopenharmony_ci nlines = split(TZ_ZONE_TABLE, line, /\n/) 6424616d0f9Sopenharmony_ci for (i = 1; i <= nlines; i++) { 6434616d0f9Sopenharmony_ci $0 = line[i] 6444616d0f9Sopenharmony_ci if ($0 ~ /^[^#]/ && !missing_comment) { 6454616d0f9Sopenharmony_ci if ($4) 6464616d0f9Sopenharmony_ci comment[++inlines] = $4 6474616d0f9Sopenharmony_ci else 6484616d0f9Sopenharmony_ci missing_comment = 1 6494616d0f9Sopenharmony_ci } 6504616d0f9Sopenharmony_ci } 6514616d0f9Sopenharmony_ci if (!missing_comment && inlines <= 22) 6524616d0f9Sopenharmony_ci for (i = 1; i <= inlines; i++) 6534616d0f9Sopenharmony_ci print comment[i] 6544616d0f9Sopenharmony_ci } 6554616d0f9Sopenharmony_ci ' ="$zone_table" 6564616d0f9Sopenharmony_ci ` 6574616d0f9Sopenharmony_ci 6584616d0f9Sopenharmony_ci # If there's more than one country, ask the user which one. 6594616d0f9Sopenharmony_ci case $countries in 6604616d0f9Sopenharmony_ci *"$newline"*) 6614616d0f9Sopenharmony_ci echo >&2 'Please select a country' \ 6624616d0f9Sopenharmony_ci 'whose clocks agree with yours.' 6634616d0f9Sopenharmony_ci doselect $countries 6644616d0f9Sopenharmony_ci country_result=$select_result 6654616d0f9Sopenharmony_ci country=$select_result;; 6664616d0f9Sopenharmony_ci *) 6674616d0f9Sopenharmony_ci country=$countries 6684616d0f9Sopenharmony_ci esac 6694616d0f9Sopenharmony_ci 6704616d0f9Sopenharmony_ci 6714616d0f9Sopenharmony_ci # Get list of timezones in the country. 6724616d0f9Sopenharmony_ci regions=` 6734616d0f9Sopenharmony_ci $AWK ' 6744616d0f9Sopenharmony_ci BEGIN { 6754616d0f9Sopenharmony_ci country = substr(ARGV[1], 2) 6764616d0f9Sopenharmony_ci TZ_COUNTRY_TABLE = substr(ARGV[2], 2) 6774616d0f9Sopenharmony_ci TZ_ZONE_TABLE = substr(ARGV[3], 2) 6784616d0f9Sopenharmony_ci ARGV[1] = ARGV[2] = ARGV[3] = "" 6794616d0f9Sopenharmony_ci FS = "\t" 6804616d0f9Sopenharmony_ci cc = country 6814616d0f9Sopenharmony_ci nlines = split(TZ_COUNTRY_TABLE, line, /\n/) 6824616d0f9Sopenharmony_ci for (i = 1; i <= nlines; i++) { 6834616d0f9Sopenharmony_ci $0 = line[i] 6844616d0f9Sopenharmony_ci if ($0 !~ /^#/ && country == $2) { 6854616d0f9Sopenharmony_ci cc = $1 6864616d0f9Sopenharmony_ci break 6874616d0f9Sopenharmony_ci } 6884616d0f9Sopenharmony_ci } 6894616d0f9Sopenharmony_ci nlines = split(TZ_ZONE_TABLE, line, /\n/) 6904616d0f9Sopenharmony_ci for (i = 1; i <= nlines; i++) { 6914616d0f9Sopenharmony_ci $0 = line[i] 6924616d0f9Sopenharmony_ci if ($0 ~ /^#/) 6934616d0f9Sopenharmony_ci continue 6944616d0f9Sopenharmony_ci if ($1 ~ cc) 6954616d0f9Sopenharmony_ci print $4 6964616d0f9Sopenharmony_ci } 6974616d0f9Sopenharmony_ci } 6984616d0f9Sopenharmony_ci ' ="$country" ="$TZ_COUNTRY_TABLE" ="$zone_table" 6994616d0f9Sopenharmony_ci ` 7004616d0f9Sopenharmony_ci 7014616d0f9Sopenharmony_ci # If there's more than one region, ask the user which one. 7024616d0f9Sopenharmony_ci case $regions in 7034616d0f9Sopenharmony_ci *"$newline"*) 7044616d0f9Sopenharmony_ci echo >&2 'Please select one of the following timezones.' 7054616d0f9Sopenharmony_ci doselect $regions 7064616d0f9Sopenharmony_ci region=$select_result 7074616d0f9Sopenharmony_ci esac 7084616d0f9Sopenharmony_ci 7094616d0f9Sopenharmony_ci # Determine tz from country and region. 7104616d0f9Sopenharmony_ci tz=` 7114616d0f9Sopenharmony_ci $AWK ' 7124616d0f9Sopenharmony_ci BEGIN { 7134616d0f9Sopenharmony_ci country = substr(ARGV[1], 2) 7144616d0f9Sopenharmony_ci region = substr(ARGV[2], 2) 7154616d0f9Sopenharmony_ci TZ_COUNTRY_TABLE = substr(ARGV[3], 2) 7164616d0f9Sopenharmony_ci TZ_ZONE_TABLE = substr(ARGV[4], 2) 7174616d0f9Sopenharmony_ci ARGV[1] = ARGV[2] = ARGV[3] = ARGV[4] = "" 7184616d0f9Sopenharmony_ci FS = "\t" 7194616d0f9Sopenharmony_ci cc = country 7204616d0f9Sopenharmony_ci nlines = split(TZ_COUNTRY_TABLE, line, /\n/) 7214616d0f9Sopenharmony_ci for (i = 1; i <= nlines; i++) { 7224616d0f9Sopenharmony_ci $0 = line[i] 7234616d0f9Sopenharmony_ci if ($0 !~ /^#/ && country == $2) { 7244616d0f9Sopenharmony_ci cc = $1 7254616d0f9Sopenharmony_ci break 7264616d0f9Sopenharmony_ci } 7274616d0f9Sopenharmony_ci } 7284616d0f9Sopenharmony_ci nlines = split(TZ_ZONE_TABLE, line, /\n/) 7294616d0f9Sopenharmony_ci for (i = 1; i <= nlines; i++) { 7304616d0f9Sopenharmony_ci $0 = line[i] 7314616d0f9Sopenharmony_ci if ($0 ~ /^#/) 7324616d0f9Sopenharmony_ci continue 7334616d0f9Sopenharmony_ci if ($1 ~ cc && ($4 == region || !region)) 7344616d0f9Sopenharmony_ci print $3 7354616d0f9Sopenharmony_ci } 7364616d0f9Sopenharmony_ci } 7374616d0f9Sopenharmony_ci ' ="$country" ="$region" ="$TZ_COUNTRY_TABLE" ="$zone_table" 7384616d0f9Sopenharmony_ci ` 7394616d0f9Sopenharmony_ci esac 7404616d0f9Sopenharmony_ci 7414616d0f9Sopenharmony_ci # Make sure the corresponding zoneinfo file exists. 7424616d0f9Sopenharmony_ci TZ_for_date=$TZDIR/$tz 7434616d0f9Sopenharmony_ci <"$TZ_for_date" || { 7444616d0f9Sopenharmony_ci say >&2 "$0: time zone files are not set up correctly" 7454616d0f9Sopenharmony_ci exit 1 7464616d0f9Sopenharmony_ci } 7474616d0f9Sopenharmony_ci esac 7484616d0f9Sopenharmony_ci 7494616d0f9Sopenharmony_ci 7504616d0f9Sopenharmony_ci # Use the proposed TZ to output the current date relative to UTC. 7514616d0f9Sopenharmony_ci # Loop until they agree in seconds. 7524616d0f9Sopenharmony_ci # Give up after 8 unsuccessful tries. 7534616d0f9Sopenharmony_ci 7544616d0f9Sopenharmony_ci extra_info= 7554616d0f9Sopenharmony_ci for i in 1 2 3 4 5 6 7 8 7564616d0f9Sopenharmony_ci do 7574616d0f9Sopenharmony_ci TZdate=`LANG=C TZ="$TZ_for_date" date` 7584616d0f9Sopenharmony_ci UTdate=`LANG=C TZ=UTC0 date` 7594616d0f9Sopenharmony_ci if $AWK ' 7604616d0f9Sopenharmony_ci function getsecs(d) { 7614616d0f9Sopenharmony_ci return match(d, /.*:[0-5][0-9]/) ? substr(d, RLENGTH - 1, 2) : "" 7624616d0f9Sopenharmony_ci } 7634616d0f9Sopenharmony_ci BEGIN { exit getsecs(ARGV[1]) != getsecs(ARGV[2]) } 7644616d0f9Sopenharmony_ci ' ="$TZdate" ="$UTdate" 7654616d0f9Sopenharmony_ci then 7664616d0f9Sopenharmony_ci extra_info=" 7674616d0f9Sopenharmony_ciSelected time is now: $TZdate. 7684616d0f9Sopenharmony_ciUniversal Time is now: $UTdate." 7694616d0f9Sopenharmony_ci break 7704616d0f9Sopenharmony_ci fi 7714616d0f9Sopenharmony_ci done 7724616d0f9Sopenharmony_ci 7734616d0f9Sopenharmony_ci 7744616d0f9Sopenharmony_ci # Output TZ info and ask the user to confirm. 7754616d0f9Sopenharmony_ci 7764616d0f9Sopenharmony_ci echo >&2 "" 7774616d0f9Sopenharmony_ci echo >&2 "Based on the following information:" 7784616d0f9Sopenharmony_ci echo >&2 "" 7794616d0f9Sopenharmony_ci case $time%$country_result%$region%$coord in 7804616d0f9Sopenharmony_ci ?*%?*%?*%) 7814616d0f9Sopenharmony_ci say >&2 " $time$newline $country_result$newline $region";; 7824616d0f9Sopenharmony_ci ?*%?*%%|?*%%?*%) say >&2 " $time$newline $country_result$region";; 7834616d0f9Sopenharmony_ci ?*%%%) say >&2 " $time";; 7844616d0f9Sopenharmony_ci %?*%?*%) say >&2 " $country_result$newline $region";; 7854616d0f9Sopenharmony_ci %?*%%) say >&2 " $country_result";; 7864616d0f9Sopenharmony_ci %%?*%?*) say >&2 " coord $coord$newline $region";; 7874616d0f9Sopenharmony_ci %%%?*) say >&2 " coord $coord";; 7884616d0f9Sopenharmony_ci *) say >&2 " TZ='$tz'" 7894616d0f9Sopenharmony_ci esac 7904616d0f9Sopenharmony_ci say >&2 "" 7914616d0f9Sopenharmony_ci say >&2 "TZ='$tz' will be used.$extra_info" 7924616d0f9Sopenharmony_ci say >&2 "Is the above information OK?" 7934616d0f9Sopenharmony_ci 7944616d0f9Sopenharmony_ci doselect Yes No 7954616d0f9Sopenharmony_ci ok=$select_result 7964616d0f9Sopenharmony_ci case $ok in 7974616d0f9Sopenharmony_ci Yes) break 7984616d0f9Sopenharmony_ci esac 7994616d0f9Sopenharmony_cido coord= 8004616d0f9Sopenharmony_cidone 8014616d0f9Sopenharmony_ci 8024616d0f9Sopenharmony_cicase $SHELL in 8034616d0f9Sopenharmony_ci*csh) file=.login line="setenv TZ '$tz'";; 8044616d0f9Sopenharmony_ci*) file=.profile line="TZ='$tz'; export TZ" 8054616d0f9Sopenharmony_ciesac 8064616d0f9Sopenharmony_ci 8074616d0f9Sopenharmony_citest -t 1 && say >&2 " 8084616d0f9Sopenharmony_ciYou can make this change permanent for yourself by appending the line 8094616d0f9Sopenharmony_ci $line 8104616d0f9Sopenharmony_cito the file '$file' in your home directory; then log out and log in again. 8114616d0f9Sopenharmony_ci 8124616d0f9Sopenharmony_ciHere is that TZ value again, this time on standard output so that you 8134616d0f9Sopenharmony_cican use the $0 command in shell scripts:" 8144616d0f9Sopenharmony_ci 8154616d0f9Sopenharmony_cisay "$tz" 816