[tz] [PATCH 2/2] tzselect: -c COORD now supports more ISO 6709 forms

Paul Eggert eggert at cs.ucla.edu
Wed Aug 21 03:28:12 UTC 2013


* tzselect.ksh (LC_ALL): Don't set this, so that the user can
use the locale's decimal point in coordinates.
(convert_coord): Rename from cvt1.  All callers changed.
Support more ISO 6709 forms.
* tzselect.8: Document -c better, including the new forms.
---
 tzselect.8   | 43 +++++++++++++++++++++++++++++++++++--------
 tzselect.ksh | 39 ++++++++++++++++++---------------------
 2 files changed, 53 insertions(+), 29 deletions(-)

diff --git a/tzselect.8 b/tzselect.8
index 884af36..39436ae 100644
--- a/tzselect.8
+++ b/tzselect.8
@@ -31,14 +31,41 @@ All interaction with the user is done via standard input and standard error.
 Instead of asking for continent and then country and then city,
 ask for selection from time zones whose largest cities
 are closest to the location with geographical coordinates
-.IR coord .
+.I coord.
 Use ISO 6709 notation for
-.IR coord ,
-for example,
-.B "\-c\ \+42.391415\-071.570419"
-for 42.391415\(de\|N, 71.570419\(de\|W, and
-.B "\-c\ +404226\-0740319"
-for 48\(de\|42\(fm\|26\(sd\|N, 74\(de\|3\(fm\|19\(sd\|W.
+.I coord,
+that is, a latitude immediately followed by a longitude.  The latitude
+and longitude should be signed integers followed by an optional
+decimal point and fraction: positive numbers represent north and east,
+negative south and west.  Latitudes with two and longitudes with three
+integer digits are treated as degrees; latitudes with four or six and
+longitudes with five or seven integer digits are treated as
+.I "DDMM, DDDMM, DDMMSS,"
+or
+.I DDDMMSS
+representing
+.I DD
+or
+.I DDD
+degrees,
+.I MM
+minutes,
+and zero or
+.I SS
+seconds, with any trailing fractions represent fractional minutes or
+(if
+.I SS
+is present) seconds.  The decimal point is that of the current locale.
+For example, in the (default) C locale,
+.B "\-c\ +40.689\-074.045"
+specifies 40.689\(de\|N, 74.045\(de\|W,
+.B "\-c\ +4041.4\-07402.7"
+specifies 40\(de\|41.4\(fm\|N, 74\(de\|2.7\(fm\|W, and
+.B "\-c\ +404121\-0740240"
+specifies 40\(de\|41\(fm\|21\(sd\|N, 74\(de\|2\(fm\|40\(sd\|W.
+If
+.I coord
+is not one of the documented forms, the resulting behavior is unspecified.
 .TP
 .BI "\-n " limit
 When
@@ -49,7 +76,7 @@ locations (default 10).
 .TP
 .BI "\-t " zonetabtype
 Make selections from the time zone table of type
-.IR zonetabtype .
+.I zonetabtype.
 Possible
 .I zonetabtype
 values include:
diff --git a/tzselect.ksh b/tzselect.ksh
index b8f2bc6..798c704 100644
--- a/tzselect.ksh
+++ b/tzselect.ksh
@@ -1,7 +1,5 @@
 #!/bin/bash
 
-export LC_ALL=C
-
 PKGVERSION='(tzcode) '
 TZVERSION=see_Makefile
 REPORT_BUGS_TO=tz at iana.org
@@ -130,31 +128,30 @@ output_distances='
         country[$1] = $2
     country["US"] = "US" # Otherwise the strings get too long.
   }
-  function cvt1(coord, deg, min, ilen, sign, sec) {
-    ilen = length(coord)
-    sign = substr(coord, 1, 1)
-    if (coord ~ /\./) {
-      deg = coord + 0
-    } else {
-      if (ilen <= 6) {
-	 sec = 0
-      } else {
-	 sec = sign substr(coord, ilen - 1)
-	 ilen -= 2
-      }
-      min = sign substr(coord, ilen - 1, 2)
-      deg = substr(coord, 1, ilen - 2)
-      deg = (deg * 3600.0 + min * 60.0 + sec) / 3600.0
-    }
-    return deg * 0.017453292519943295
+  function convert_coord(coord, deg, min, ilen, sign, sec) {
+    if (coord ~ /^[-+]?[0-9]?[0-9][0-9][0-9][0-9][0-9][0-9]([^0-9]|$)/) {
+      degminsec = coord
+      intdeg = degminsec < 0 ? -int(-degminsec / 10000) : int(degminsec / 10000)
+      minsec = degminsec - intdeg * 10000
+      intmin = minsec < 0 ? -int(-minsec / 100) : int(minsec / 100)
+      sec = minsec - intmin * 100
+      deg = (intdeg * 3600 + intmin * 60 + sec) / 3600
+    } else if (coord ~ /^[-+]?[0-9]?[0-9][0-9][0-9][0-9]([^0-9]|$)/) {
+      degmin = coord
+      intdeg = degmin < 0 ? -int(-degmin / 100) : int(degmin / 100)
+      min = degmin - intdeg * 100
+      deg = (intdeg * 60 + min) / 60
+    } else
+      deg = coord
+    return deg * 0.017453292519943296
   }
   function convert_latitude(coord) {
     match(coord, /..*[-+]/)
-    return cvt1(substr(coord, 1, RLENGTH - 1))
+    return convert_coord(substr(coord, 1, RLENGTH - 1))
   }
   function convert_longitude(coord) {
     match(coord, /..*[-+]/)
-    return cvt1(substr(coord, RLENGTH))
+    return convert_coord(substr(coord, RLENGTH))
   }
   # Great-circle distance between points with given latitude and longitude.
   # Inputs and output are in radians.  This uses the great-circle special
-- 
1.8.1.2




More information about the tz mailing list