Local time - UTC offset and daylight saving correction
authorColin Clark <colin.clark@cclark.uk>
Wed, 25 Apr 2018 10:46:38 +0000 (11:46 +0100)
committerColin Clark <colin.clark@cclark.uk>
Wed, 25 Apr 2018 10:46:38 +0000 (11:46 +0100)
Use GPS lat/long to provide local time corrected for UTC offset and DST
correction.

The corrected time is available in formatted.localtime
The selected timezone is available in formatted.timezone

33 files changed:
ZoneDetect.md [new file with mode: 0644]
configure.in
doc/docbook/GuideReference.xml
doc/docbook/GuideReferenceFileDates.xml [new file with mode: 0644]
doc/docbook/GuideReferenceTags.xml
doc/docbook/GuideReferenceUTC.xml [new file with mode: 0644]
doc/docbook/GuideSidebarsInfo.xml
plugins/Makefile.am
plugins/ZoneDetect/Makefile.am [new file with mode: 0644]
plugins/ZoneDetect/timezone21.bin [new file with mode: 0644]
src/Makefile.am
src/bar.c
src/exif-common.c
src/main.h
src/preferences.c
src/zonedetect.c [new file with mode: 0644]
src/zonedetect.h [new file with mode: 0644]
web/help/GuideIndex.html
web/help/GuideReference.html
web/help/GuideReferenceCommandLine.html
web/help/GuideReferenceConfig.html
web/help/GuideReferenceDecodeLatLong.html
web/help/GuideReferenceKeyboardShortcuts.html
web/help/GuideReferenceLIRC.html
web/help/GuideReferenceLua.html
web/help/GuideReferenceMetadata.html
web/help/GuideReferencePixbufLoaders.html
web/help/GuideReferenceStandards.html
web/help/GuideReferenceSupportedFormats.html
web/help/GuideReferenceThumbnails.html
web/help/GuideReferenceUTC.html [new file with mode: 0644]
web/help/GuideReferenceXmpExif.html
web/help/GuideSidebarsInfo.html

diff --git a/ZoneDetect.md b/ZoneDetect.md
new file mode 100644 (file)
index 0000000..9b1ecc3
--- /dev/null
@@ -0,0 +1,10 @@
+The detection of timezone is performed by
+ [ZoneDetect](https://github.com/BertoldVdb/ZoneDetect)
+ timezone16.bin has a longitude resolution of 0.0055 degrees (~0.5km).  
+ timezone21.bin has a longitude resolution of 0.00017 degrees (~20m).
+ The safe zone result indicates how close you are to the nearest border (flat earth model using lat and lon as x and y), so you can know when to do a new lookup. If you don't need it you can ignore it, in this case you can pass a NULL parameter to save the (very small) calculation effort.
+ Note that the [underlying database](https://github.com/evansiroky/timezone-boundary-builder) will change from time-to-time.
index c89ca35..102fbcd 100644 (file)
@@ -590,6 +590,7 @@ AC_CONFIG_FILES([
     plugins/ufraw/Makefile
     plugins/import/Makefile
     plugins/geocode-parameters/Makefile
+    plugins/ZoneDetect/Makefile
     geeqie.spec
 ])
 
index 51aa16d..9b45b3a 100644 (file)
@@ -11,6 +11,7 @@
   <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="GuideReferenceTags.xml" />\r
   <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="GuideReferenceSupportedFormats.xml" />\r
   <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="GuideReferencePixbufLoaders.xml" />\r
+  <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="GuideReferenceUTC.xml" />\r
   <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="GuideReferenceDecodeLatLong.xml" />\r
   <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="GuideReferenceStandards.xml" />\r
   <para />\r
diff --git a/doc/docbook/GuideReferenceFileDates.xml b/doc/docbook/GuideReferenceFileDates.xml
new file mode 100644 (file)
index 0000000..5373c25
--- /dev/null
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>\r
+<section id="GuideReferenceFileDates">\r
+  <title>File date types</title>\r
+  <para>Geeqie understands 4 types of file dates:</para>\r
+  <itemizedlist spacing="compact">\r
+    <listitem>\r
+      <para>Standard date (mtime) - The date the file contents were last modified, or when the file was created if since unchanged.</para>\r
+    </listitem>\r
+    <listitem>\r
+      <para>Status changed (ctime) - The date the file status was last changed. This includes change of owner, change of read/write permission and change of contents.</para>\r
+    </listitem>\r
+    <listitem>\r
+      <para>Exif date original (Exif.Photo.DateTimeOriginal) -  For images from a digital camera, this is the time the photo was taken.</para>\r
+    </listitem>\r
+    <listitem>\r
+      <para>Exif date digitized (Exif.Photo.DateTimeDigitized) -  For scanned images, this the time the scan was made. For images from a digital camera, it may be identical to the above date.</para>\r
+    </listitem>\r
+  </itemizedlist>\r
+</section>\r
index c2b0167..42929b8 100644 (file)
               <para>Latitude, Longitude</para>\r
             </entry>\r
           </row>\r
+          <row>\r
+            <entry>\r
+              <para>formatted.localtime</para>\r
+            </entry>\r
+            <entry>\r
+              <para>\r
+                Exif.GPSInfo.GPSLatitude\r
+                <para />\r
+                Exif.GPSInfo.GPSLatitudeRef\r
+                <para />\r
+                Exif.GPSInfo.GPSLongitude\r
+                <para />\r
+                Exif.GPSInfo.GPSLongitudeRef\r
+                <para />\r
+                Exif.GPSInfo.GPSDateStamp\r
+                <para />\r
+                Exif.GPSInfo.GPSTimeStamp\r
+              </para>\r
+            </entry>\r
+            <entry>\r
+              <para>\r
+                Local time corrected for UTC offset, DST correction\r
+                <footnote id='ref1'>\r
+                  <para>\r
+                    Refer to\r
+                    <link linkend="GuideReferenceUTC">UTC and DST</link>\r
+                    section.\r
+                  </para>\r
+                </footnote>\r
+              </para>\r
+            </entry>\r
+          </row>\r
+          <row>\r
+            <entry>\r
+              <para>formatted.timezone</para>\r
+            </entry>\r
+            <entry>\r
+              <para>\r
+                Exif.GPSInfo.GPSLatitude\r
+                <para />\r
+                Exif.GPSInfo.GPSLatitudeRef\r
+                <para />\r
+                Exif.GPSInfo.GPSLongitude\r
+                <para />\r
+                Exif.GPSInfo.GPSLongitudeRef\r
+              </para>\r
+            </entry>\r
+            <entry>\r
+              <para>\r
+                Timezone indicated by lat/long\r
+                <footnote id='ref1'>\r
+                  <para>\r
+                    Refer to\r
+                    <link linkend="GuideReferenceUTC">UTC and DST</link>\r
+                    section.\r
+                  </para>\r
+                </footnote>\r
+              </para>\r
+            </entry>\r
+          </row>\r
         </tbody>\r
       </tgroup>\r
     </table>\r
               <para>GPS altitiude</para>\r
             </entry>\r
           </row>\r
+          <row>\r
+            <entry>\r
+              <para>formatted.timezone</para>\r
+            </entry>\r
+            <entry>\r
+              <para>Time zone</para>\r
+            </entry>\r
+          </row>\r
           <row>\r
             <entry>\r
               <para>Xmp.photoshop.Country</para>\r
               <para>Date</para>\r
             </entry>\r
           </row>\r
+          <row>\r
+            <entry>\r
+              <para>formatted.localtime</para>\r
+            </entry>\r
+            <entry>\r
+              <para>Local time</para>\r
+            </entry>\r
+          </row>\r
           <row>\r
             <entry>\r
               <para>formatted.ShutterSpeed</para>\r
diff --git a/doc/docbook/GuideReferenceUTC.xml b/doc/docbook/GuideReferenceUTC.xml
new file mode 100644 (file)
index 0000000..ceb3863
--- /dev/null
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>\r
+<section id="GuideReferenceUTC">\r
+  <title id="titleGuideReferenceUTC">UTC and Daylight Saving Time (DST)</title>\r
+  <para>Geeqie can display the local time at which a photo was taken, adjusted for UTC offset and Daylight Saving Time.</para>\r
+  <para>\r
+    If the image exif data contains the required parameters (see\r
+    <link linkend="GuideReferenceXmpExif">Pre-formatted tags</link>\r
+    ), Geeqie will use the latitude and longitude to determine which timezone the image was taken in.\r
+    <para />\r
+    The UTC offset and Daylight Saving Time Correction for that timezone, combined with the GPS UTC value, will then be used to compute the correct local time.\r
+    <para />\r
+    This value may be displayed in either the Info Sidebar or Overlay Screen Display by using the parameter\r
+    <code>formatted.localtime</code>\r
+  </para>\r
+  <para>\r
+    The timezone for the image may also be displayed by using the parameter\r
+    <code>formatted.timezone</code>\r
+    .\r
+  </para>\r
+</section>\r
index 0853b98..3313415 100644 (file)
             <entry>formatted.GPSPosition</entry>\r
             <entry>Latitude, Longitude</entry>\r
           </row>\r
+          <row>\r
+            <entry>formatted.localtime</entry>\r
+            <entry>\r
+              Local time corrected for UTC offset, DST correction\r
+              <footnote id='ref1'>\r
+                <para>\r
+                  Refer to\r
+                  <link linkend="GuideReferenceUTC">UTC and DST</link>\r
+                  section.\r
+                </para>\r
+              </footnote>\r
+            </entry>\r
+          </row>\r
+          <row>\r
+            <entry>formatted.timezone</entry>\r
+            <entry>\r
+              Timezone indicated by GPS lat/long values\r
+              <footnote id='ref1'>\r
+                <para>\r
+                  Refer to\r
+                  <link linkend="GuideReferenceUTC">UTC and DST</link>\r
+                  section.\r
+                </para>\r
+              </footnote>\r
+            </entry>\r
+          </row>\r
           <row>\r
             <entry>file.size</entry>\r
             <entry>file size in bytes</entry>\r
index 9d1aaca..4b57bd0 100644 (file)
@@ -1,6 +1,6 @@
 #FIXME enable or disable individual plugins from configure
 
-SUBDIRS = rotate symlink ufraw import geocode-parameters
+SUBDIRS = rotate symlink ufraw import geocode-parameters ZoneDetect
 qq_desktoptemplatedir = $(appdir)
 qq_desktoptemplate_DATA = template.desktop
 
diff --git a/plugins/ZoneDetect/Makefile.am b/plugins/ZoneDetect/Makefile.am
new file mode 100644 (file)
index 0000000..adead9a
--- /dev/null
@@ -0,0 +1 @@
+dist_gq_bin_SCRIPTS = timezone21.bin
diff --git a/plugins/ZoneDetect/timezone21.bin b/plugins/ZoneDetect/timezone21.bin
new file mode 100644 (file)
index 0000000..02b6645
Binary files /dev/null and b/plugins/ZoneDetect/timezone21.bin differ
index 82478de..6ea6ff3 100644 (file)
@@ -264,7 +264,9 @@ geeqie_SOURCES = \
        window.c        \
        window.h        \
        lua.c           \
-       glua.h
+       glua.h          \
+       zonedetect.c    \
+       zonedetect.h
 
 geeqie_LDADD = $(GTK_LIBS) $(GLIB_LIBS) $(INTLLIBS) $(JPEG_LIBS) $(TIFF_LIBS) $(LCMS_LIBS) $(EXIV2_LIBS) $(LIBCHAMPLAIN_LIBS) $(LIBCHAMPLAIN_GTK_LIBS) $(LUA_LIBS) $(CLUTTER_LIBS) $(CLUTTER_GTK_LIBS) $(FFMPEGTHUMBNAILER_LIBS)
 
index 0eb8fdf..8f8673c 100644 (file)
--- a/src/bar.c
+++ b/src/bar.c
@@ -99,6 +99,7 @@ static const gchar default_config_exif[] =
 "            <pane_exif id = 'exif' expanded = 'true' >"
 "                <entry key = 'formatted.Camera' if_set = 'true' editable = 'false' />"
 "                <entry key = 'formatted.DateTime' if_set = 'true' editable = 'false' />"
+"                <entry key = 'formatted.localtime' if_set = 'true' editable = 'false' />"
 "                <entry key = 'formatted.ShutterSpeed' if_set = 'true' editable = 'false' />"
 "                <entry key = 'formatted.Aperture' if_set = 'true' editable = 'false' />"
 "                <entry key = 'formatted.ExposureBias' if_set = 'true' editable = 'false' />"
@@ -138,6 +139,7 @@ static const gchar default_config_location[] =
 "            <pane_exif id = 'location' expanded = 'true' >"
 "                <entry key = 'formatted.GPSPosition' if_set = 'true' editable = 'false' />"
 "                <entry key = 'formatted.GPSAltitude' if_set = 'true' editable = 'false' />"
+"                <entry key = 'formatted.timezone' if_set = 'true' editable = 'false' />"
 "                <entry key = 'Xmp.photoshop.Country' if_set = 'false' editable = 'true' />"
 "                <entry key = 'Xmp.iptc.CountryCode' if_set = 'false' editable = 'true' />"
 "                <entry key = 'Xmp.photoshop.State' if_set = 'false' editable = 'true' />"
index 2af25a5..67caac3 100644 (file)
@@ -56,6 +56,7 @@
 #include "ui_fileops.h"
 #include "cache.h"
 #include "jpeg_parser.h"
+#include "zonedetect.h"
 
 
 static gdouble exif_rational_to_double(ExifRational *r, gint sign)
@@ -607,6 +608,247 @@ static gchar *exif_build_formatted_GPSAltitude(ExifData *exif)
        return g_strdup_printf("%0.f m %s", alt, (ref==0)?_("Above Sea Level"):_("Below Sea Level"));
 }
 
+/**
+ * @brief Extracts timezone from a ZoneDetect search structure
+ * @param results ZoneDetect search structure
+ * @returns Timezone in the form "Europe/London"
+ * 
+ * Refer to https://github.com/BertoldVdb/ZoneDetect
+ * for structure details
+ */
+static gchar *zd_tz(ZoneDetectResult* results)
+{
+       gchar *timezone = NULL;
+       gchar *timezone_pre = NULL;
+       gchar *timezone_id = NULL;
+       unsigned int index = 0;
+
+    if (!results)
+               {
+               return NULL;
+               }
+
+       while(results[index].lookupResult != ZD_LOOKUP_END)
+               {
+               if(results[index].data)
+                       {
+                       for(unsigned int i=0; i<results[index].numFields; i++)
+                               {
+                               if (g_strstr_len(results[index].fieldNames[i], -1, "TimezoneIdPrefix"))
+                                       {
+                                       timezone_pre = g_strdup(results[index].data[i]);
+                                       }
+                               if (g_strstr_len(results[index].fieldNames[i], -1, "TimezoneId"))
+                                       {
+                                       timezone_id = g_strdup(results[index].data[i]);
+                                       }
+                               }
+                       }
+               index++;
+               }
+
+       timezone = g_strconcat(timezone_pre, timezone_id, NULL);
+       g_free(timezone_pre);
+       g_free(timezone_id);
+       return timezone;
+}
+
+/**
+ * @brief Creates local time from GPS lat/long
+ * @param exif 
+ * @returns Localised time and date
+ * 
+ * GPS lat/long is translated to timezone using ZoneDetect.
+ * GPS UTC is converted to Unix time stamp (seconds since 1970).
+ * The TZ environment variable is set to the relevant timezone
+ * and the Unix timestamp converted to local time using locale.
+ * If the conversion fails, unformatted UTC is returned.
+ */
+static gchar *exif_build_formatted_localtime(ExifData *exif)
+{
+       gfloat latitude;
+       gfloat longitude;
+       gchar *text_latitude;
+       gchar *text_longitude;
+       gchar *text_latitude_ref;
+       gchar *text_longitude_ref;
+       gchar *text_date;
+       gchar *text_time;
+       gchar *text_date_time = NULL;
+       gchar buf[128];
+       gchar *tmp;
+       gint buflen;
+       GError *error = NULL;
+       gchar *lat_deg;
+       gchar *lat_min;
+       gchar *lon_deg;
+       gchar *lon_min;
+       gchar *time_zone;
+       gchar *time_zone_org;
+       struct tm *tm_local;
+       struct tm tm_utc;
+       time_t stamp;
+       gchar *zd_path;
+       gchar *zone_selected;
+       ZoneDetect *cd;
+       ZoneDetectResult *results;
+
+       text_latitude = exif_get_data_as_text(exif, "Exif.GPSInfo.GPSLatitude");
+       text_longitude = exif_get_data_as_text(exif, "Exif.GPSInfo.GPSLongitude");
+       text_latitude_ref = exif_get_data_as_text(exif, "Exif.GPSInfo.GPSLatitudeRef");
+       text_longitude_ref = exif_get_data_as_text(exif, "Exif.GPSInfo.GPSLongitudeRef");
+       text_date = exif_get_data_as_text(exif, "Exif.GPSInfo.GPSDateStamp");
+       text_time = exif_get_data_as_text(exif, "Exif.GPSInfo.GPSTimeStamp");
+
+       if (text_latitude && text_longitude && text_latitude_ref &&
+                                               text_longitude_ref && text_date && text_time)
+               {
+               text_date_time = g_strconcat(text_date, ":", text_time, NULL);
+
+               lat_deg = strtok(text_latitude, "deg'");
+               lat_min = strtok(NULL, "deg'");
+               latitude = atof(lat_deg) + atof(lat_min) / 60;
+               if (!g_strcmp0(text_latitude_ref, "South"))
+                       {
+                       latitude = -latitude;
+                       }
+               lon_deg = strtok(text_longitude, "deg'");
+               lon_min = strtok(NULL, "deg'");
+               longitude = atof(lon_deg) + atof(lon_min) / 60;
+               if (!g_strcmp0(text_longitude_ref, "West"))
+                       {
+                       longitude = -longitude;
+                       }
+
+               zd_path = g_build_filename(GQ_BIN_DIR, TIMEZONE_DATABASE, NULL);
+               cd = ZDOpenDatabase(zd_path);
+               if (cd)
+                       {
+                       results = ZDLookup(cd, latitude, longitude, NULL);
+                       zone_selected = zd_tz(results);
+                       time_zone = g_strconcat("TZ=", zone_selected, NULL);
+                       time_zone_org = g_strconcat("TZ=", getenv("TZ"), NULL);
+                       putenv("TZ=UTC");
+                       g_free(zone_selected);
+
+                       memset(&tm_utc, 0, sizeof(tm_utc));
+                       if (text_date_time && strptime(text_date_time, "%Y:%m:%d:%H:%M:%S", &tm_utc))
+                               {
+                               stamp = mktime(&tm_utc);        // Convert the struct to a Unix timestamp
+                               putenv(time_zone);      // Switch to destination time zone
+
+                               tm_local = localtime(&stamp);
+
+                               /* Convert to localtime using locale */
+                               buflen = strftime(buf, sizeof(buf), "%x %X", tm_local);
+                               if (buflen > 0)
+                                       {
+                                       tmp = g_locale_to_utf8(buf, buflen, NULL, NULL, &error);
+                                       if (error)
+                                               {
+                                               log_printf("Error converting locale strftime to UTF-8: %s\n", error->message);
+                                               g_error_free(error);
+                                               }
+                                       else
+                                               {
+                                               g_free(text_date_time);
+                                               text_date_time = g_strdup(tmp);
+                                               }
+                                       }
+                                       g_free(tmp);
+                               }
+                       putenv(time_zone_org);
+
+                       g_free(time_zone);
+                       g_free(time_zone_org);
+                       }
+               else
+                       {
+                       log_printf("Error: Init of timezone database %s failed\n", zd_path);
+                       }
+               ZDCloseDatabase(cd);
+               g_free(zd_path);
+               }
+
+       g_free(text_latitude);
+       g_free(text_longitude);
+       g_free(text_latitude_ref);
+       g_free(text_longitude_ref);
+       g_free(text_date);
+       g_free(text_time);
+
+       return text_date_time;
+}
+
+/**
+ * @brief Gets timezone from GPS lat/long
+ * @param exif 
+ * @returns Timezone string in the form "Europe/London"
+ * 
+ * 
+ */
+static gchar *exif_build_formatted_timezone(ExifData *exif)
+{
+       gfloat latitude;
+       gfloat longitude;
+       gchar *text_latitude;
+       gchar *text_longitude;
+       gchar *text_latitude_ref;
+       gchar *text_longitude_ref;
+       gchar *lat_deg;
+       gchar *lat_min;
+       gchar *lon_deg;
+       gchar *lon_min;
+       gchar *time_zone = NULL;
+       gchar *zd_path;
+       ZoneDetect *cd;
+       ZoneDetectResult *results;
+
+       text_latitude = exif_get_data_as_text(exif, "Exif.GPSInfo.GPSLatitude");
+       text_longitude = exif_get_data_as_text(exif, "Exif.GPSInfo.GPSLongitude");
+       text_latitude_ref = exif_get_data_as_text(exif, "Exif.GPSInfo.GPSLatitudeRef");
+       text_longitude_ref = exif_get_data_as_text(exif, "Exif.GPSInfo.GPSLongitudeRef");
+
+       if (text_latitude && text_longitude && text_latitude_ref &&
+                                               text_longitude_ref)
+               {
+               lat_deg = strtok(text_latitude, "deg'");
+               lat_min = strtok(NULL, "deg'");
+               latitude = atof(lat_deg) + atof(lat_min) / 60;
+               if (g_strcmp0(text_latitude_ref, "South") == 0)
+                       {
+                       latitude = -latitude;
+                       }
+               lon_deg = strtok(text_longitude, "deg'");
+               lon_min = strtok(NULL, "deg'");
+               longitude = atof(lon_deg) + atof(lon_min) / 60;
+               if (g_strcmp0(text_longitude_ref, "West") == 0)
+                       {
+                       longitude = -longitude;
+                       }
+               zd_path = g_build_filename(GQ_BIN_DIR, TIMEZONE_DATABASE, NULL);
+               cd = ZDOpenDatabase(zd_path);
+               if (cd)
+                       {
+                       results = ZDLookup(cd, latitude, longitude, NULL);
+                       time_zone = zd_tz(results);
+                       ZDFreeResults(results);
+                       }
+               else
+                       {
+                       log_printf("Error: Init of timezone database %s failed\n", zd_path);
+                       }
+               ZDCloseDatabase(cd);
+               g_free(zd_path);
+               }
+
+       g_free(text_latitude);
+       g_free(text_longitude);
+       g_free(text_latitude_ref);
+       g_free(text_longitude_ref);
+
+       return time_zone;
+}
 
 /* List of custom formatted pseudo-exif tags */
 #define EXIF_FORMATTED_TAG(name, label) { EXIF_FORMATTED()#name, label, exif_build_formatted##_##name }
@@ -627,6 +869,8 @@ ExifFormattedText ExifFormattedList[] = {
        EXIF_FORMATTED_TAG(ColorProfile,        N_("Color profile")),
        EXIF_FORMATTED_TAG(GPSPosition,         N_("GPS position")),
        EXIF_FORMATTED_TAG(GPSAltitude,         N_("GPS altitude")),
+       EXIF_FORMATTED_TAG(localtime,           N_("Local time")),
+       EXIF_FORMATTED_TAG(timezone,            N_("Time zone")),
        {"file.size",                           N_("File size"),        NULL},
        {"file.date",                           N_("File date"),        NULL},
        {"file.mode",                           N_("File mode"),        NULL},
index 2465622..120f528 100644 (file)
 #include "options.h"
 
 #define DESKTOP_FILE_TEMPLATE GQ_APP_DIR "/template.desktop"
+
+#define TIMEZONE_DATABASE "timezone21.bin"
 /*
  *----------------------------------------------------------------------------
  * main.c
index 3df77c1..d242f0f 100644 (file)
@@ -46,6 +46,7 @@
 #include "ui_tabcomp.h"
 #include "ui_utildlg.h"
 #include "window.h"
+#include "zonedetect.h"
 
 #include <math.h>
 
@@ -2739,26 +2740,24 @@ void show_about_window(LayoutWindow *lw)
        gchar *comment;
        gint i_authors = 0;
        gchar *path;
+       GString *copyright;
+       gchar *zd_path;
+       ZoneDetect *cd;
        FILE *fp = NULL;
 #define LINE_LENGTH 1000
        gchar line[LINE_LENGTH];
 
-#if !GTK_CHECK_VERSION(3,0,0)
-       GString *copyright;
-
        copyright = g_string_new(NULL);
-       path = g_build_filename(GQ_HELPDIR, "COPYING", NULL);
-       fp = fopen(path, "r");
-       if (fp)
+       copyright = g_string_append(copyright, "This program comes with absolutely no warranty.\nGNU General Public License, version 2 or later.\nSee https://www.gnu.org/licenses/old-licenses/gpl-2.0.html\n\n");
+
+       zd_path = g_build_filename(GQ_BIN_DIR, TIMEZONE_DATABASE, NULL);
+       cd = ZDOpenDatabase(zd_path);
+       if (cd)
                {
-               while(fgets(line, LINE_LENGTH, fp))
-                       {
-                       copyright = g_string_append(copyright, line);
-                       }
-               fclose(fp);
+               copyright = g_string_append(copyright, ZDGetNotice(cd));
                }
-       g_free(path);
-#endif
+       ZDCloseDatabase(cd);
+       g_free(zd_path);
 
        authors[0] = NULL;
        path = g_build_filename(GQ_HELPDIR, "AUTHORS", NULL);
@@ -2794,16 +2793,12 @@ void show_about_window(LayoutWindow *lw)
                "comments", comment,
                "authors", authors,
                "translator-credits", _("translator-credits"),
-#if GTK_CHECK_VERSION(3,0,0)
-               "license-type", GTK_LICENSE_GPL_2_0,
-#else
-               "license",  copyright->str,
-#endif
+               "wrap-license", TRUE,
+               "license", copyright->str,
                NULL);
 
-#if !GTK_CHECK_VERSION(3,0,0)
        g_string_free(copyright, TRUE);
-#endif
+
        gint n = 0;
        while(n < i_authors)
                {
diff --git a/src/zonedetect.c b/src/zonedetect.c
new file mode 100644 (file)
index 0000000..74bb8f4
--- /dev/null
@@ -0,0 +1,597 @@
+/*
+ * Copyright (c) 2018, Bertold Van den Bergh (vandenbergh@bertold.org)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of the author nor the
+ *       names of its contributors may be used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR DISTRIBUTOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/mman.h>
+#include <stdlib.h>
+#include <string.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <math.h>
+
+#include "zonedetect.h"
+
+struct ZoneDetectOpaque {
+    int fd;
+    uint32_t length;
+    uint8_t* mapping;
+
+    uint8_t tableType;
+    uint8_t version;
+    uint8_t precision;
+    uint8_t numFields;
+
+    char* notice;
+    char** fieldNames;
+
+    uint32_t bboxOffset;
+    uint32_t metadataOffset;
+    uint32_t dataOffset;
+};
+
+static int32_t ZDFloatToFixedPoint(float input, float scale, unsigned int precision) {
+    float inputScaled = input / scale;
+    return inputScaled * (float)(1 << (precision-1));
+}
+
+static unsigned int ZDDecodeVariableLengthUnsigned(ZoneDetect* library, uint32_t* index, uint32_t* result) {
+    uint32_t value = 0;
+    unsigned int i=0, shift = 0;
+
+    if(*index >= library->length) {
+        return 0;
+    }
+
+    uint8_t* buffer = library->mapping + *index;
+    uint8_t* bufferEnd = library->mapping + library->length - 1;
+
+    while(1) {
+        value |= (buffer[i] & 0x7F) << shift;
+        shift += 7;
+
+        if(!(buffer[i] & 0x80)) {
+            break;
+        }
+
+        i++;
+        if(buffer + i > bufferEnd) {
+            return 0;
+        }
+    }
+
+    i++;
+    *result = value;
+    *index += i;
+    return i;
+}
+
+static unsigned int ZDDecodeVariableLengthSigned(ZoneDetect* library, uint32_t* index, int32_t* result) {
+    uint32_t value = 0;
+    unsigned int retVal = ZDDecodeVariableLengthUnsigned(library, index, &value);
+    *result = (value & 1)?-(value/2):(value/2);
+    return retVal;
+}
+
+static char* ZDParseString(ZoneDetect* library, uint32_t* index) {
+    uint32_t strLength;
+    if(!ZDDecodeVariableLengthUnsigned(library, index, &strLength)) {
+        return NULL;
+    }
+
+    uint32_t strOffset = *index;
+    unsigned int remoteStr = 0;
+    if(strLength >= 256) {
+        strOffset = library->metadataOffset + strLength - 256;
+        remoteStr = 1;
+
+        if(!ZDDecodeVariableLengthUnsigned(library, &strOffset, &strLength)) {
+            return NULL;
+        }
+
+        if(strLength > 256) {
+            return NULL;
+        }
+    }
+
+    char* str = malloc(strLength + 1);
+
+    if(str) {
+        unsigned int i;
+        for(i=0; i<strLength; i++) {
+            str[i] = library->mapping[strOffset+i] ^ 0x80;
+        }
+        str[strLength] = 0;
+    }
+
+    if(!remoteStr) {
+        *index += strLength;
+    }
+
+    return str;
+}
+
+static int ZDParseHeader(ZoneDetect* library) {
+    if(library->length < 7) {
+        return -1;
+    }
+
+    if(memcmp(library->mapping, "PLB", 3)) {
+        return -1;
+    }
+
+    library->tableType = library->mapping[3];
+    library->version   = library->mapping[4];
+    library->precision = library->mapping[5];
+    library->numFields = library->mapping[6];
+
+    if(library->version != 0) {
+        return -1;
+    }
+
+    uint32_t index = 7;
+
+    library->fieldNames = malloc(library->numFields * sizeof(char*));
+    unsigned int i;
+    for(i=0; i<library->numFields; i++) {
+        library->fieldNames[i] = ZDParseString(library, &index);
+    }
+
+    library->notice = ZDParseString(library, &index);
+    if(!library->notice) {
+        return -1;
+    }
+
+    uint32_t tmp;
+    /* Read section sizes */
+    /* By memset: library->bboxOffset = 0 */
+
+    if(!ZDDecodeVariableLengthUnsigned(library, &index, &tmp)) return -1;
+    library->metadataOffset = tmp + library->bboxOffset;
+
+    if(!ZDDecodeVariableLengthUnsigned(library, &index, &tmp))return -1;
+    library->dataOffset = tmp + library->metadataOffset;
+
+    if(!ZDDecodeVariableLengthUnsigned(library, &index, &tmp)) return -1;
+
+    /* Add header size to everything */
+    library->bboxOffset += index;
+    library->metadataOffset += index;
+    library->dataOffset += index;
+
+    /* Verify file length */
+    if(tmp + library->dataOffset != library->length) {
+        return -2;
+    }
+
+    return 0;
+}
+
+static int ZDPointInBox(int32_t xl, int32_t x, int32_t xr, int32_t yl, int32_t y, int32_t yr) {
+    if((xl <= x && x <= xr) || (xr <= x && x <= xl)) {
+        if((yl <= y && y <= yr) || (yr <= y && y <= yl)) {
+            return 1;
+        }
+    }
+
+    return 0;
+}
+
+static ZDLookupResult ZDPointInPolygon(ZoneDetect* library, uint32_t polygonIndex, int32_t latFixedPoint, int32_t lonFixedPoint, uint64_t* distanceSqrMin) {
+    uint32_t numVertices;
+    int32_t pointLat = 0, pointLon = 0, diffLat = 0, diffLon = 0, firstLat = 0, firstLon = 0, prevLat = 0, prevLon = 0;
+    lonFixedPoint -= 3;
+
+    /* Read number of vertices */
+    if(!ZDDecodeVariableLengthUnsigned(library, &polygonIndex, &numVertices)) return ZD_LOOKUP_PARSE_ERROR;
+    if(numVertices > 1000000) return ZD_LOOKUP_PARSE_ERROR;
+
+    int prevQuadrant = 0, winding = 0;
+
+    uint32_t i;
+    for(i=0; i<=numVertices; i++) {
+        if(i<numVertices) {
+            if(!ZDDecodeVariableLengthSigned(library, &polygonIndex, &diffLat)) return ZD_LOOKUP_PARSE_ERROR;
+            if(!ZDDecodeVariableLengthSigned(library, &polygonIndex, &diffLon)) return ZD_LOOKUP_PARSE_ERROR;
+            pointLat += diffLat;
+            pointLon += diffLon;
+            if(i==0) {
+                firstLat = pointLat;
+                firstLon = pointLon;
+            }
+        } else {
+            /* The polygons should be closed, but just in case */
+            pointLat = firstLat;
+            pointLon = firstLon;
+        }
+
+        /* Check if point is ON the border */
+        if(pointLat == latFixedPoint && pointLon == lonFixedPoint) {
+            if(distanceSqrMin) *distanceSqrMin=0;
+            return ZD_LOOKUP_ON_BORDER_VERTEX;
+        }
+
+        /* Find quadrant */
+        int quadrant;
+        if(pointLat>=latFixedPoint) {
+            if(pointLon>=lonFixedPoint) {
+                quadrant = 0;
+            } else {
+                quadrant = 1;
+            }
+        } else {
+            if(pointLon>=lonFixedPoint) {
+                quadrant = 3;
+            } else {
+                quadrant = 2;
+            }
+        }
+
+        if(i>0) {
+            int windingNeedCompare = 0, lineIsStraight = 0;
+            float a = 0, b = 0;
+
+            /* Calculate winding number */
+            if(quadrant == prevQuadrant) {
+                /* Do nothing */
+            } else if(quadrant == (prevQuadrant + 1) % 4) {
+                winding ++;
+            } else if((quadrant + 1) % 4 == prevQuadrant) {
+                winding --;
+            } else {
+                windingNeedCompare = 1;
+            }
+
+            /* Avoid horizontal and vertical lines */
+            if((pointLon == prevLon || pointLat == prevLat)) {
+                lineIsStraight = 1;
+            }
+
+            /* Calculate the parameters of y=ax+b if needed */
+            if(!lineIsStraight && (distanceSqrMin || windingNeedCompare)) {
+                a = ((float)pointLat - (float)prevLat)/((float)pointLon - prevLon);
+                b = (float)pointLat - a*(float)pointLon;
+            }
+
+            /* Jumped two quadrants. */
+            if(windingNeedCompare) {
+                if(lineIsStraight) {
+                    if(distanceSqrMin) *distanceSqrMin=0;
+                    return ZD_LOOKUP_ON_BORDER_SEGMENT;
+                }
+
+                /* Check if the target is on the border */
+                int32_t intersectLon = ((float)latFixedPoint - b)/a;
+                if(intersectLon == lonFixedPoint) {
+                    if(distanceSqrMin) *distanceSqrMin=0;
+                    return ZD_LOOKUP_ON_BORDER_SEGMENT;
+                }
+
+                /* Ok, it's not. In which direction did we go round the target? */
+                int sign = (intersectLon < lonFixedPoint)?2:-2;
+                if(quadrant == 2 || quadrant == 3) {
+                    winding += sign;
+                } else {
+                    winding -= sign;
+                }
+            }
+
+            /* Calculate closest point on line (if needed) */
+            if(distanceSqrMin) {
+                float closestLon, closestLat;
+                if(!lineIsStraight) {
+                    closestLon=((float)lonFixedPoint+a*(float)latFixedPoint-a*b)/(a*a+1);
+                    closestLat=(a*((float)lonFixedPoint+a*(float)latFixedPoint)+b)/(a*a+1);
+                } else {
+                    if(pointLon == prevLon) {
+                        closestLon=pointLon;
+                        closestLat=latFixedPoint;
+                    } else {
+                        closestLon=lonFixedPoint;
+                        closestLat=pointLat;
+                    }
+                }
+
+                int closestInBox = ZDPointInBox(pointLon, closestLon, prevLon, pointLat, closestLat, prevLat);
+
+                int64_t diffLat, diffLon;
+                if(closestInBox) {
+                    /* Calculate squared distance to segment. */
+                    diffLat = closestLat - latFixedPoint;
+                    diffLon = (closestLon - lonFixedPoint);
+                } else {
+                    /*
+                     * Calculate squared distance to vertices
+                     * It is enough to check the current point since the polygon is closed.
+                     */
+                    diffLat = pointLat - latFixedPoint;
+                    diffLon = (pointLon - lonFixedPoint);
+                }
+
+                /* Note: lon has half scale */
+                uint64_t distanceSqr = diffLat*diffLat + diffLon*diffLon*4;
+                if(distanceSqr < *distanceSqrMin) *distanceSqrMin = distanceSqr;
+            }
+        }
+
+        prevQuadrant = quadrant;
+        prevLat = pointLat;
+        prevLon = pointLon;
+    }
+
+    if(winding == -4) {
+        return ZD_LOOKUP_IN_ZONE;
+    } else if(winding == 4) {
+        return ZD_LOOKUP_IN_EXCLUDED_ZONE;
+    } else if(winding == 0) {
+        return ZD_LOOKUP_NOT_IN_ZONE;
+    }
+
+    /* Should not happen */
+    if(distanceSqrMin) *distanceSqrMin=0;
+    return ZD_LOOKUP_ON_BORDER_SEGMENT;
+}
+
+void ZDCloseDatabase(ZoneDetect* library) {
+    if(library) {
+        if(library->fieldNames) {
+            unsigned int i;
+            for(i=0; i<library->numFields; i++) {
+                if(library->fieldNames[i]) {
+                    free(library->fieldNames[i]);
+                }
+            }
+            free(library->fieldNames);
+        }
+        if(library->notice) {
+            free(library->notice);
+        }
+        if(library->mapping) {
+            munmap(library->mapping, library->length);
+        }
+        if(library->fd >= 0) {
+            close(library->fd);
+        }
+        free(library);
+    }
+}
+
+ZoneDetect* ZDOpenDatabase(const char* path) {
+    ZoneDetect* library = (ZoneDetect*)malloc(sizeof(*library));
+
+    if(library) {
+        memset(library, 0, sizeof(*library));
+
+        library->fd = open(path, O_RDONLY | O_CLOEXEC);
+        if(library->fd < 0) {
+            goto fail;
+        }
+
+        library->length = lseek(library->fd, 0, SEEK_END);
+        if(library->length <= 0) {
+            goto fail;
+        }
+        lseek(library->fd, 0, SEEK_SET);
+
+        library->mapping = mmap(NULL, library->length, PROT_READ, MAP_PRIVATE | MAP_FILE, library->fd, 0);
+        if(!library->mapping) {
+            goto fail;
+        }
+
+        /* Parse the header */
+        if(ZDParseHeader(library)) {
+            goto fail;
+        }
+    }
+
+    return library;
+
+fail:
+    ZDCloseDatabase(library);
+    return NULL;
+}
+
+ZoneDetectResult* ZDLookup(ZoneDetect* library, float lat, float lon, float* safezone) {
+    int32_t latFixedPoint = ZDFloatToFixedPoint(lat, 90, library->precision);
+    int32_t lonFixedPoint = ZDFloatToFixedPoint(lon, 180, library->precision);
+    unsigned int numResults = 0;
+    uint64_t distanceSqrMin=-1;
+
+    /* Iterate over all polygons */
+    uint32_t bboxIndex = library->bboxOffset;
+    int32_t metadataIndex = 0;
+    int32_t polygonIndex = 0;
+
+    ZoneDetectResult* results = malloc(sizeof(ZoneDetectResult));
+    if(!results) {
+        return NULL;
+    }
+
+    while(bboxIndex < library->metadataOffset) {
+        int32_t minLat, minLon, maxLat, maxLon, metadataIndexDelta;
+        uint32_t polygonIndexDelta;
+        if(!ZDDecodeVariableLengthSigned(library, &bboxIndex, &minLat)) break;
+        if(!ZDDecodeVariableLengthSigned(library, &bboxIndex, &minLon)) break;
+        if(!ZDDecodeVariableLengthSigned(library, &bboxIndex, &maxLat)) break;
+        if(!ZDDecodeVariableLengthSigned(library, &bboxIndex, &maxLon)) break;
+        if(!ZDDecodeVariableLengthSigned(library, &bboxIndex, &metadataIndexDelta)) break;
+        if(!ZDDecodeVariableLengthUnsigned(library, &bboxIndex, &polygonIndexDelta)) break;
+
+        metadataIndex+=metadataIndexDelta;
+        polygonIndex+=polygonIndexDelta;
+
+        if(latFixedPoint >= minLat) {
+            if(latFixedPoint <= maxLat &&
+                    lonFixedPoint >= minLon &&
+                    lonFixedPoint <= maxLon) {
+
+                /* Indices valid? */
+                if(library->metadataOffset + metadataIndex >= library->dataOffset) continue;
+                if(library->dataOffset + polygonIndex >= library->length) continue;
+
+                ZDLookupResult lookupResult = ZDPointInPolygon(library, library->dataOffset + polygonIndex, latFixedPoint, lonFixedPoint, (safezone)?&distanceSqrMin:NULL);
+                if(lookupResult == ZD_LOOKUP_PARSE_ERROR) {
+                    break;
+                } else if(lookupResult != ZD_LOOKUP_NOT_IN_ZONE) {
+                    ZoneDetectResult* newResults = realloc(results, sizeof(ZoneDetectResult) * (numResults+2));
+
+                    if(newResults) {
+                        results = newResults;
+                        results[numResults].metaId = metadataIndex;
+                        results[numResults].numFields = library->numFields;
+                        results[numResults].fieldNames = library->fieldNames;
+                        results[numResults].lookupResult = lookupResult;
+
+                        numResults++;
+                    } else {
+                        break;
+                    }
+                }
+            }
+        } else {
+            /* The data is sorted along minLat */
+            break;
+        }
+    }
+
+    /* Clean up results */
+    unsigned int i, j;
+    for(i=0; i<numResults; i++) {
+        int insideSum = 0;
+        ZDLookupResult overrideResult = ZD_LOOKUP_IGNORE;
+        for(j=i; j<numResults; j++) {
+            if(results[i].metaId == results[j].metaId) {
+                ZDLookupResult tmpResult = results[j].lookupResult;
+                results[j].lookupResult = ZD_LOOKUP_IGNORE;
+
+                /* This is the same result. Is it an exclusion zone? */
+                if(tmpResult == ZD_LOOKUP_IN_ZONE) {
+                    insideSum++;
+                } else if(tmpResult == ZD_LOOKUP_IN_EXCLUDED_ZONE) {
+                    insideSum--;
+                } else {
+                    /* If on the bodrder then the final result is on the border */
+                    overrideResult = tmpResult;
+                }
+
+            }
+        }
+
+        if(overrideResult != ZD_LOOKUP_IGNORE) {
+            results[i].lookupResult = overrideResult;
+        } else {
+            if(insideSum) {
+                results[i].lookupResult = ZD_LOOKUP_IN_ZONE;
+            }
+        }
+    }
+
+    /* Remove zones to ignore */
+    unsigned int newNumResults = 0;
+    for(i=0; i<numResults; i++) {
+        if(results[i].lookupResult != ZD_LOOKUP_IGNORE) {
+            results[newNumResults] = results[i];
+            newNumResults++;
+        }
+    }
+    numResults = newNumResults;
+
+    /* Lookup metadata */
+    for(i=0; i<numResults; i++) {
+        uint32_t tmpIndex = library->metadataOffset + results[i].metaId;
+        results[i].data = malloc(library->numFields * sizeof(char*));
+        if(results[i].data) {
+            for(j=0; j<library->numFields; j++) {
+                results[i].data[j] = ZDParseString(library, &tmpIndex);
+            }
+        }
+    }
+
+    /* Write end marker */
+    results[numResults].lookupResult = ZD_LOOKUP_END;
+    results[numResults].numFields = 0;
+    results[numResults].fieldNames = NULL;
+    results[numResults].data = NULL;
+
+    if(safezone) {
+        *safezone = sqrtf(distanceSqrMin) * 90 / (float)(1 << (library->precision-1));
+    }
+
+    return results;
+}
+
+void ZDFreeResults(ZoneDetectResult* results) {
+    unsigned int index = 0;
+
+    if(!results) {
+        return;
+    }
+
+    while(results[index].lookupResult != ZD_LOOKUP_END) {
+        if(results[index].data) {
+            unsigned int i;
+            for(i=0; i<results[index].numFields; i++) {
+                if(results[index].data[i]) {
+                    free(results[index].data[i]);
+                }
+            }
+            free(results[index].data);
+        }
+        index++;
+    }
+    free(results);
+}
+
+const char* ZDGetNotice(ZoneDetect* library) {
+    return library->notice;
+}
+
+uint8_t ZDGetTableType(ZoneDetect* library) {
+    return library->tableType;
+}
+
+const char* ZDLookupResultToString(ZDLookupResult result) {
+    switch(result) {
+    case ZD_LOOKUP_IGNORE:
+        return "Ignore";
+    case ZD_LOOKUP_END:
+        return "End";
+    case ZD_LOOKUP_PARSE_ERROR:
+        return "Parsing error";
+    case ZD_LOOKUP_NOT_IN_ZONE:
+        return "Not in zone";
+    case ZD_LOOKUP_IN_ZONE:
+        return "In zone";
+    case ZD_LOOKUP_IN_EXCLUDED_ZONE:
+        return "In excluded zone";
+    case ZD_LOOKUP_ON_BORDER_VERTEX:
+        return "Target point is border vertex";
+    case ZD_LOOKUP_ON_BORDER_SEGMENT:
+        return "Target point is on border";
+    }
+
+    return "Unknown";
+}
+
diff --git a/src/zonedetect.h b/src/zonedetect.h
new file mode 100644 (file)
index 0000000..4be5367
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2018, Bertold Van den Bergh (vandenbergh@bertold.org)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of the author nor the
+ *       names of its contributors may be used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR DISTRIBUTOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdint.h>
+
+#ifndef _ZONEDETECT_H_
+#define _ZONEDETECT_H_
+
+typedef enum {
+    ZD_LOOKUP_IGNORE = -3,
+    ZD_LOOKUP_END = -2,
+    ZD_LOOKUP_PARSE_ERROR = -1,
+    ZD_LOOKUP_NOT_IN_ZONE = 0,
+    ZD_LOOKUP_IN_ZONE = 1,
+    ZD_LOOKUP_IN_EXCLUDED_ZONE = 2,
+    ZD_LOOKUP_ON_BORDER_VERTEX = 3,
+    ZD_LOOKUP_ON_BORDER_SEGMENT = 4
+} ZDLookupResult;
+
+typedef struct {
+    ZDLookupResult lookupResult;
+
+    uint32_t metaId;
+    uint8_t numFields;
+    char** fieldNames;
+    char** data;
+} ZoneDetectResult;
+
+struct ZoneDetectOpaque;
+typedef struct ZoneDetectOpaque ZoneDetect;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+ZoneDetect* ZDOpenDatabase(const char* path);
+void        ZDCloseDatabase(ZoneDetect* library);
+
+ZoneDetectResult* ZDLookup(ZoneDetect* library, float lat, float lon, float* safezone);
+void              ZDFreeResults(ZoneDetectResult* results);
+
+const char* ZDGetNotice(ZoneDetect* library);
+uint8_t     ZDGetTableType(ZoneDetect* library);
+const char* ZDLookupResultToString(ZDLookupResult result);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
index 703f6c8..af022c8 100644 (file)
@@ -648,10 +648,13 @@ dd.answer div.label { float: left; }
 <span class="label">13.10. </span><a class="xref" href="GuideReferencePixbufLoaders.html" title="Additional pixbuf loaders">Additional pixbuf loaders</a>
 </li>
 <li>
-<span class="label">13.11. </span><a class="xref" href="GuideReferenceDecodeLatLong.html" title="Decoding Latitude and Longitude">Decoding Latitude and Longitude</a>
+<span class="label">13.11. </span><a class="xref" href="GuideReferenceUTC.html" title="UTC and Daylight Saving Time (DST)">UTC and Daylight Saving Time (DST)</a>
 </li>
 <li>
-<span class="label">13.12. </span><a class="xref" href="GuideReferenceStandards.html" title="Standards">Standards</a>
+<span class="label">13.12. </span><a class="xref" href="GuideReferenceDecodeLatLong.html" title="Decoding Latitude and Longitude">Decoding Latitude and Longitude</a>
+</li>
+<li>
+<span class="label">13.13. </span><a class="xref" href="GuideReferenceStandards.html" title="Standards">Standards</a>
 </li>
 </ul></div>
 </li>
index 8f00d85..a2537db 100644 (file)
@@ -440,6 +440,7 @@ dd.answer div.label { float: left; }
 <li><a class="xref" href="GuideReferenceXmpExif.html" title="XMP, Exif and IPTC">XMP, Exif and IPTC</a></li>
 <li><a class="xref" href="GuideReferenceSupportedFormats.html" title="Supported File Formats">Supported File Formats</a></li>
 <li><a class="xref" href="GuideReferencePixbufLoaders.html" title="Additional pixbuf loaders">Additional pixbuf loaders</a></li>
+<li><a class="xref" href="GuideReferenceUTC.html" title="UTC and Daylight Saving Time (DST)">UTC and Daylight Saving Time (DST)</a></li>
 <li><a class="xref" href="GuideReferenceDecodeLatLong.html" title="Decoding Latitude and Longitude">Decoding Latitude and Longitude</a></li>
 <li><a class="xref" href="GuideReferenceStandards.html" title="Standards">Standards</a></li>
 </ul></div>
@@ -487,10 +488,13 @@ dd.answer div.label { float: left; }
 <span class="label">13.10. </span><a class="xref" href="GuideReferencePixbufLoaders.html" title="Additional pixbuf loaders">Additional pixbuf loaders</a>
 </li>
 <li>
-<span class="label">13.11. </span><a class="xref" href="GuideReferenceDecodeLatLong.html" title="Decoding Latitude and Longitude">Decoding Latitude and Longitude</a>
+<span class="label">13.11. </span><a class="xref" href="GuideReferenceUTC.html" title="UTC and Daylight Saving Time (DST)">UTC and Daylight Saving Time (DST)</a>
 </li>
 <li>
-<span class="label">13.12. </span><a class="xref" href="GuideReferenceStandards.html" title="Standards">Standards</a>
+<span class="label">13.12. </span><a class="xref" href="GuideReferenceDecodeLatLong.html" title="Decoding Latitude and Longitude">Decoding Latitude and Longitude</a>
+</li>
+<li>
+<span class="label">13.13. </span><a class="xref" href="GuideReferenceStandards.html" title="Standards">Standards</a>
 </li>
 </ul></div>
 </div></div>
index 32a576c..c811ebe 100644 (file)
@@ -441,6 +441,7 @@ dd.answer div.label { float: left; }
 <li><a class="xref" href="GuideReferenceXmpExif.html" title="XMP, Exif and IPTC">XMP, Exif and IPTC</a></li>
 <li><a class="xref" href="GuideReferenceSupportedFormats.html" title="Supported File Formats">Supported File Formats</a></li>
 <li><a class="xref" href="GuideReferencePixbufLoaders.html" title="Additional pixbuf loaders">Additional pixbuf loaders</a></li>
+<li><a class="xref" href="GuideReferenceUTC.html" title="UTC and Daylight Saving Time (DST)">UTC and Daylight Saving Time (DST)</a></li>
 <li><a class="xref" href="GuideReferenceDecodeLatLong.html" title="Decoding Latitude and Longitude">Decoding Latitude and Longitude</a></li>
 <li><a class="xref" href="GuideReferenceStandards.html" title="Standards">Standards</a></li>
 </ul></div>
index 67f0f41..a4f3665 100644 (file)
@@ -441,6 +441,7 @@ dd.answer div.label { float: left; }
 <li><a class="xref" href="GuideReferenceXmpExif.html" title="XMP, Exif and IPTC">XMP, Exif and IPTC</a></li>
 <li><a class="xref" href="GuideReferenceSupportedFormats.html" title="Supported File Formats">Supported File Formats</a></li>
 <li><a class="xref" href="GuideReferencePixbufLoaders.html" title="Additional pixbuf loaders">Additional pixbuf loaders</a></li>
+<li><a class="xref" href="GuideReferenceUTC.html" title="UTC and Daylight Saving Time (DST)">UTC and Daylight Saving Time (DST)</a></li>
 <li><a class="xref" href="GuideReferenceDecodeLatLong.html" title="Decoding Latitude and Longitude">Decoding Latitude and Longitude</a></li>
 <li><a class="xref" href="GuideReferenceStandards.html" title="Standards">Standards</a></li>
 </ul></div>
index 695f079..4f6e13f 100644 (file)
@@ -3,7 +3,7 @@
 <head>
 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
 <title>Decoding Latitude and Longitude</title>
-<link rel="previous" href="GuideReferencePixbufLoaders.html" title="Additional pixbuf loaders">
+<link rel="previous" href="GuideReferenceUTC.html" title="UTC and Daylight Saving Time (DST)">
 <link rel="next" href="GuideReferenceStandards.html" title="Standards">
 <link rel="top" href="GuideIndex.html" title="The Geeqie User Manual">
 <style type="text/css">
@@ -410,7 +410,7 @@ dd.answer div.label { float: left; }
 </head>
 <body>
 <div class="navbar navbar-top"><table class="navbar"><tr>
-<td class="navbar-prev"><a class="navbar-prev" href="GuideReferencePixbufLoaders.html" title="Additional pixbuf loaders">Additional pixbuf loaders</a></td>
+<td class="navbar-prev"><a class="navbar-prev" href="GuideReferenceUTC.html" title="UTC and Daylight Saving Time (DST)">UTC and Daylight Saving Time (DST)</a></td>
 <td class="navbar-next"><a class="navbar-next" href="GuideReferenceStandards.html" title="Standards">Standards</a></td>
 </tr></table></div>
 <div class="sidebar"><div class="sidenav"><div class="autotoc"><ul>
@@ -441,6 +441,7 @@ dd.answer div.label { float: left; }
 <li><a class="xref" href="GuideReferenceXmpExif.html" title="XMP, Exif and IPTC">XMP, Exif and IPTC</a></li>
 <li><a class="xref" href="GuideReferenceSupportedFormats.html" title="Supported File Formats">Supported File Formats</a></li>
 <li><a class="xref" href="GuideReferencePixbufLoaders.html" title="Additional pixbuf loaders">Additional pixbuf loaders</a></li>
+<li><a class="xref" href="GuideReferenceUTC.html" title="UTC and Daylight Saving Time (DST)">UTC and Daylight Saving Time (DST)</a></li>
 <li>Decoding Latitude and Longitude</li>
 <li><a class="xref" href="GuideReferenceStandards.html" title="Standards">Standards</a></li>
 </ul></div>
@@ -481,7 +482,7 @@ dd.answer div.label { float: left; }
   </p>
 </div></div>
 <div class="navbar navbar-bottom"><table class="navbar"><tr>
-<td class="navbar-prev"><a class="navbar-prev" href="GuideReferencePixbufLoaders.html" title="Additional pixbuf loaders">Additional pixbuf loaders</a></td>
+<td class="navbar-prev"><a class="navbar-prev" href="GuideReferenceUTC.html" title="UTC and Daylight Saving Time (DST)">UTC and Daylight Saving Time (DST)</a></td>
 <td class="navbar-next"><a class="navbar-next" href="GuideReferenceStandards.html" title="Standards">Standards</a></td>
 </tr></table></div>
 </body>
index 33f45f3..4361dd9 100644 (file)
@@ -441,6 +441,7 @@ dd.answer div.label { float: left; }
 <li><a class="xref" href="GuideReferenceXmpExif.html" title="XMP, Exif and IPTC">XMP, Exif and IPTC</a></li>
 <li><a class="xref" href="GuideReferenceSupportedFormats.html" title="Supported File Formats">Supported File Formats</a></li>
 <li><a class="xref" href="GuideReferencePixbufLoaders.html" title="Additional pixbuf loaders">Additional pixbuf loaders</a></li>
+<li><a class="xref" href="GuideReferenceUTC.html" title="UTC and Daylight Saving Time (DST)">UTC and Daylight Saving Time (DST)</a></li>
 <li><a class="xref" href="GuideReferenceDecodeLatLong.html" title="Decoding Latitude and Longitude">Decoding Latitude and Longitude</a></li>
 <li><a class="xref" href="GuideReferenceStandards.html" title="Standards">Standards</a></li>
 </ul></div>
index ca27599..0f9267e 100644 (file)
@@ -441,6 +441,7 @@ dd.answer div.label { float: left; }
 <li><a class="xref" href="GuideReferenceXmpExif.html" title="XMP, Exif and IPTC">XMP, Exif and IPTC</a></li>
 <li><a class="xref" href="GuideReferenceSupportedFormats.html" title="Supported File Formats">Supported File Formats</a></li>
 <li><a class="xref" href="GuideReferencePixbufLoaders.html" title="Additional pixbuf loaders">Additional pixbuf loaders</a></li>
+<li><a class="xref" href="GuideReferenceUTC.html" title="UTC and Daylight Saving Time (DST)">UTC and Daylight Saving Time (DST)</a></li>
 <li><a class="xref" href="GuideReferenceDecodeLatLong.html" title="Decoding Latitude and Longitude">Decoding Latitude and Longitude</a></li>
 <li><a class="xref" href="GuideReferenceStandards.html" title="Standards">Standards</a></li>
 </ul></div>
index 76e0ce4..91d5d25 100644 (file)
@@ -441,6 +441,7 @@ dd.answer div.label { float: left; }
 <li><a class="xref" href="GuideReferenceXmpExif.html" title="XMP, Exif and IPTC">XMP, Exif and IPTC</a></li>
 <li><a class="xref" href="GuideReferenceSupportedFormats.html" title="Supported File Formats">Supported File Formats</a></li>
 <li><a class="xref" href="GuideReferencePixbufLoaders.html" title="Additional pixbuf loaders">Additional pixbuf loaders</a></li>
+<li><a class="xref" href="GuideReferenceUTC.html" title="UTC and Daylight Saving Time (DST)">UTC and Daylight Saving Time (DST)</a></li>
 <li><a class="xref" href="GuideReferenceDecodeLatLong.html" title="Decoding Latitude and Longitude">Decoding Latitude and Longitude</a></li>
 <li><a class="xref" href="GuideReferenceStandards.html" title="Standards">Standards</a></li>
 </ul></div>
index 39b0356..e1d01ba 100644 (file)
@@ -441,6 +441,7 @@ dd.answer div.label { float: left; }
 <li><a class="xref" href="GuideReferenceXmpExif.html" title="XMP, Exif and IPTC">XMP, Exif and IPTC</a></li>
 <li><a class="xref" href="GuideReferenceSupportedFormats.html" title="Supported File Formats">Supported File Formats</a></li>
 <li><a class="xref" href="GuideReferencePixbufLoaders.html" title="Additional pixbuf loaders">Additional pixbuf loaders</a></li>
+<li><a class="xref" href="GuideReferenceUTC.html" title="UTC and Daylight Saving Time (DST)">UTC and Daylight Saving Time (DST)</a></li>
 <li><a class="xref" href="GuideReferenceDecodeLatLong.html" title="Decoding Latitude and Longitude">Decoding Latitude and Longitude</a></li>
 <li><a class="xref" href="GuideReferenceStandards.html" title="Standards">Standards</a></li>
 </ul></div>
index f1c6fa1..eaf24b1 100644 (file)
@@ -4,7 +4,7 @@
 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
 <title>Additional pixbuf loaders</title>
 <link rel="previous" href="GuideReferenceSupportedFormats.html" title="Supported File Formats">
-<link rel="next" href="GuideReferenceDecodeLatLong.html" title="Decoding Latitude and Longitude">
+<link rel="next" href="GuideReferenceUTC.html" title="UTC and Daylight Saving Time (DST)">
 <link rel="top" href="GuideIndex.html" title="The Geeqie User Manual">
 <style type="text/css">
 
@@ -411,7 +411,7 @@ dd.answer div.label { float: left; }
 <body>
 <div class="navbar navbar-top"><table class="navbar"><tr>
 <td class="navbar-prev"><a class="navbar-prev" href="GuideReferenceSupportedFormats.html" title="Supported File Formats">Supported File Formats</a></td>
-<td class="navbar-next"><a class="navbar-next" href="GuideReferenceDecodeLatLong.html" title="Decoding Latitude and Longitude">Decoding Latitude and Longitude</a></td>
+<td class="navbar-next"><a class="navbar-next" href="GuideReferenceUTC.html" title="UTC and Daylight Saving Time (DST)">UTC and Daylight Saving Time (DST)</a></td>
 </tr></table></div>
 <div class="sidebar"><div class="sidenav"><div class="autotoc"><ul>
 <li><a href="GuideIndex-info.html" title="About This Document">About This Document</a></li>
@@ -441,6 +441,7 @@ dd.answer div.label { float: left; }
 <li><a class="xref" href="GuideReferenceXmpExif.html" title="XMP, Exif and IPTC">XMP, Exif and IPTC</a></li>
 <li><a class="xref" href="GuideReferenceSupportedFormats.html" title="Supported File Formats">Supported File Formats</a></li>
 <li>Additional pixbuf loaders</li>
+<li><a class="xref" href="GuideReferenceUTC.html" title="UTC and Daylight Saving Time (DST)">UTC and Daylight Saving Time (DST)</a></li>
 <li><a class="xref" href="GuideReferenceDecodeLatLong.html" title="Decoding Latitude and Longitude">Decoding Latitude and Longitude</a></li>
 <li><a class="xref" href="GuideReferenceStandards.html" title="Standards">Standards</a></li>
 </ul></div>
@@ -525,7 +526,7 @@ dd.answer div.label { float: left; }
 </div></div>
 <div class="navbar navbar-bottom"><table class="navbar"><tr>
 <td class="navbar-prev"><a class="navbar-prev" href="GuideReferenceSupportedFormats.html" title="Supported File Formats">Supported File Formats</a></td>
-<td class="navbar-next"><a class="navbar-next" href="GuideReferenceDecodeLatLong.html" title="Decoding Latitude and Longitude">Decoding Latitude and Longitude</a></td>
+<td class="navbar-next"><a class="navbar-next" href="GuideReferenceUTC.html" title="UTC and Daylight Saving Time (DST)">UTC and Daylight Saving Time (DST)</a></td>
 </tr></table></div>
 </body>
 </html>
index 432372f..0911b71 100644 (file)
@@ -441,6 +441,7 @@ dd.answer div.label { float: left; }
 <li><a class="xref" href="GuideReferenceXmpExif.html" title="XMP, Exif and IPTC">XMP, Exif and IPTC</a></li>
 <li><a class="xref" href="GuideReferenceSupportedFormats.html" title="Supported File Formats">Supported File Formats</a></li>
 <li><a class="xref" href="GuideReferencePixbufLoaders.html" title="Additional pixbuf loaders">Additional pixbuf loaders</a></li>
+<li><a class="xref" href="GuideReferenceUTC.html" title="UTC and Daylight Saving Time (DST)">UTC and Daylight Saving Time (DST)</a></li>
 <li><a class="xref" href="GuideReferenceDecodeLatLong.html" title="Decoding Latitude and Longitude">Decoding Latitude and Longitude</a></li>
 <li>Standards</li>
 </ul></div>
index 113e217..d4f8b83 100644 (file)
@@ -441,6 +441,7 @@ dd.answer div.label { float: left; }
 <li><a class="xref" href="GuideReferenceXmpExif.html" title="XMP, Exif and IPTC">XMP, Exif and IPTC</a></li>
 <li>Supported File Formats</li>
 <li><a class="xref" href="GuideReferencePixbufLoaders.html" title="Additional pixbuf loaders">Additional pixbuf loaders</a></li>
+<li><a class="xref" href="GuideReferenceUTC.html" title="UTC and Daylight Saving Time (DST)">UTC and Daylight Saving Time (DST)</a></li>
 <li><a class="xref" href="GuideReferenceDecodeLatLong.html" title="Decoding Latitude and Longitude">Decoding Latitude and Longitude</a></li>
 <li><a class="xref" href="GuideReferenceStandards.html" title="Standards">Standards</a></li>
 </ul></div>
index 505987e..31d6f0f 100644 (file)
@@ -441,6 +441,7 @@ dd.answer div.label { float: left; }
 <li><a class="xref" href="GuideReferenceXmpExif.html" title="XMP, Exif and IPTC">XMP, Exif and IPTC</a></li>
 <li><a class="xref" href="GuideReferenceSupportedFormats.html" title="Supported File Formats">Supported File Formats</a></li>
 <li><a class="xref" href="GuideReferencePixbufLoaders.html" title="Additional pixbuf loaders">Additional pixbuf loaders</a></li>
+<li><a class="xref" href="GuideReferenceUTC.html" title="UTC and Daylight Saving Time (DST)">UTC and Daylight Saving Time (DST)</a></li>
 <li><a class="xref" href="GuideReferenceDecodeLatLong.html" title="Decoding Latitude and Longitude">Decoding Latitude and Longitude</a></li>
 <li><a class="xref" href="GuideReferenceStandards.html" title="Standards">Standards</a></li>
 </ul></div>
diff --git a/web/help/GuideReferenceUTC.html b/web/help/GuideReferenceUTC.html
new file mode 100644 (file)
index 0000000..82c7dc0
--- /dev/null
@@ -0,0 +1,484 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>UTC and Daylight Saving Time (DST)</title>
+<link rel="previous" href="GuideReferencePixbufLoaders.html" title="Additional pixbuf loaders">
+<link rel="next" href="GuideReferenceDecodeLatLong.html" title="Decoding Latitude and Longitude">
+<link rel="top" href="GuideIndex.html" title="The Geeqie User Manual">
+<style type="text/css">
+
+html { height: 100%; }
+body {
+  margin: 0px; padding: 12px;
+  background-color: #f9f9f6;
+  min-height: 100%;
+  direction: ltr;
+}
+div, p, pre, blockquote { margin: 0; padding: 0; }
+p img { vertical-align: middle; }
+sub { font-size: 0.83em; }
+sub sub { font-size: 1em; }
+sup { font-size: 0.83em; }
+sup sup { font-size: 1em; }
+table { border-collapse: collapse; }
+table.table-pgwide { width: 100%; }
+td { vertical-align: top; }
+td { padding: 0.2em 0.83em 0.2em 0.83em; }
+th { padding: 0 0.83em 0 0.83em; }
+tr.tr-shade {
+  background-color: #f9f9f6;
+}
+td.td-colsep { border-right: solid 1px; }
+td.td-rowsep { border-bottom: solid 1px; }
+thead { border-top: solid 2px; border-bottom: solid 2px; }
+tfoot { border-top: solid 2px; border-bottom: solid 2px; }
+div.body {
+  padding: 1em;
+  max-width: 60em;
+  background-color: #ffffff;
+  border: solid 1px #e0e0df;
+}
+div.body-sidebar {
+  margin-right: 13em;
+}
+div.division div.division { margin-top: 1.72em; }
+div.division div.division div.division { margin-top: 1.44em; }
+div.header {
+  margin: 0;
+  color: #3f3f3f;
+  border-bottom: solid 1px #e0e0df;
+}
+h1, h2, h3, h4, h5, h6, h7 {
+  margin: 0; padding: 0;
+  color: #3f3f3f;
+}
+h1.title { font-size: 1.72em; }
+h2.title { font-size: 1.44em; }
+h3.title { font-size: 1.2em; }
+h4.title, h5.title, h6.title, h7.title { font-size: 1em; }
+.block { margin-top: 1em; }
+.block .block-first { margin-top: 0; }
+.block-indent {
+  margin-left left: 1.72em;
+  margin-: 1em;
+}
+.block-indent .block-indent { margin-left: 0em; margin-right: 0em; }
+td .block-indent  { margin-left: 0em; margin-right: 0em; }
+dd .block-indent  { margin-left: 0em; margin-right: 0em; }
+.block-verbatim { white-space: pre; }
+div.title {
+  margin-bottom: 0.2em;
+  font-weight: bold;
+  color: #3f3f3f;
+}
+div.title-formal { padding-left: 0.2em; padding-right: 0.2em; }
+div.title-formal .label { font-weight: normal; }
+a {
+  color: #1f609f;
+  text-decoration: none;
+}
+a:hover { text-decoration: underline; }
+a:visited { color: #9f1f6f; }
+ul, ol, dl { margin: 0; padding: 0; }
+li {
+  margin-top: 1em;
+  margin-left: 2.4em;
+  padding: 0;
+}
+li.li-first { margin-top: 0; }
+dt { margin: 1em 0 0 0; }
+dt.dt-first { margin: 0; }
+dd {
+  margin-left: 1.72em;
+  margin-top: 0.5em;
+}
+dl.dl-compact dt { margin-top: 0; }
+dl.dl-compact dd { margin-top: 0; margin-bottom: 0; }
+
+
+ul.linktrail {
+  display: block;
+  margin: 0.2em 0 0 0;
+  text-align: right;
+}
+li.linktrail { display: inline; margin: 0; padding: 0; }
+
+li.linktrail::before {
+  content: '  /  ';
+  color: #3f3f3f;
+}
+
+li.linktrail-first::before, li.linktrail-only::before { content: ''; }
+
+
+div.navbar {
+  padding: 0.5em 1em 0.5em 1em;
+  max-width: 60em;
+  background-color: #ffffff;
+  border: solid 1px #e0e0df;
+}
+div.navbar-top { margin-bottom: 1em; }
+div.navbar-bottom { margin-top: 1em; clear: both; }
+div.navbar img { border: 0; vertical-align: -0.4em; }
+table.navbar { width: 100%; margin: 0; border: none; }
+table.navbar td { padding: 0; border: none; }
+td.navbar-next {
+  text-align: right;
+}
+a.navbar-prev::before {
+  
+  content: '◀  ';
+  color: #3f3f3f;
+}
+a.navbar-next::after {
+  
+  content: '  ▶';
+  color: #3f3f3f;
+}
+
+
+div.sidebar {
+  float: right;
+  padding: 0; margin: 0; width: 12em;
+}
+div.sidenav {
+  padding: 0.5em 1em 0 1em;
+  background-color: #ffffff;
+  border: solid 1px #e0e0df;
+}
+div.sidenav div.autotoc {
+  background-color: #ffffff;
+  border: none; padding: 0; margin: 0;
+}
+div.sidenav div.autotoc div.autotoc { margin-top: 0.5em; }
+div.sidenav div.autotoc li { margin-bottom: 0.5em; }
+div.sidenav div.autotoc div.autotoc div.autotoc {
+  margin-left: 1em;
+  margin-top: 0;
+}
+div.sidenav div.autotoc div.autotoc div.autotoc li { margin-bottom: 0; }
+
+
+div.autotoc {
+  
+  display: table;
+  margin-top: 1em;
+  margin-left: 1.72em;
+  padding: 0.5em 1em 0.5em 1em;
+  background-color: #f0f9ff;
+  border: solid 1px #c0c9ff;
+}
+div.autotoc ul { margin: 0; padding: 0; }
+div.autotoc li { list-style-type: none; margin: 0; }
+div.autotoc div.autotoc-title { margin-bottom: 0.5em; }
+div.autotoc div.autotoc { border: none; padding: 0; margin-top: 0; margin-bottom: 0.5em; }
+div.autotoc div.autotoc div.autotoc { margin-bottom: 0; }
+
+
+span.bibliolabel {
+  color: #3f3f3f;
+}
+
+
+div.admonition {
+  padding: 0.5em 6px 0.5em 6px;
+  border: solid 1px #e0e0df;
+  background-color: #fffff0;
+}
+div.caution-inner, div.important-inner, div.note-inner, div.tip-inner, div.warning-inner {
+  padding-left: 60px;
+  background-position: left top;
+  background-repeat: no-repeat;
+  min-height: 48px;
+}
+div.caution-inner { background-image: url("admon-caution.png"); }
+div.important-inner { background-image: url("admon-important.png"); }
+div.note-inner { background-image: url("admon-note.png"); }
+div.note-bug div.note-inner { background-image: url("admon-bug.png"); }
+div.tip-inner { background-image: url("admon-tip.png"); }
+div.warning-inner { background-image: url("admon-warning.png"); }
+div.blockquote {
+  
+  background-image: url('watermark-blockquote-201C.png');
+  background-repeat: no-repeat;
+  background-position: top left;
+  padding: 0.5em;
+  padding-left: 4em;
+}
+div.attribution {
+  margin-top: 0.5em;
+  color: #3f3f3f;
+}
+div.attribution::before {
+  
+  content: '― ';
+}
+div.epigraph {
+  text-align: right;
+  margin-left: 20%;
+  margin-right: 0;
+  color: #3f3f3f;
+}
+div.figure, div.informalfigure {
+  
+  display: table;
+  padding: 0.5em;
+  background-color: #f9f9f6;
+  border: solid 1px #e0e0df;
+}
+div.figure-inner, div.informalfigure-inner {
+  padding: 0.5em;
+  background-color: #ffffff;
+  border: solid 1px #e0e0df;
+}
+div.caption { margin-top: 0.5em; }
+div.programlisting {
+  padding: 0.5em;
+  
+  background-color: #f9f9f6;
+  border: solid 1px #e0e0df;
+}
+div.screen {
+  padding: 0.5em;
+  
+  background-color: #f9f9f6;
+  border: solid 1px #e0e0df;
+}
+div.screen .prompt {
+  color: #3f3f3f;
+}
+div.screen .userinput {
+  font-weight: bold;
+  color: #3f3f3f;
+}
+div.programlisting .userinput {
+  font-weight: bold;
+  color: #3f3f3f;
+}
+pre.linenumbering {
+  color: #3f3f3f;
+  margin: 0;
+  padding-right: 1em;
+  float: left;
+  text-align: right;
+}
+
+
+
+dl.index dt { margin-top: 0; }
+dl.index dd { margin-top: 0; margin-bottom: 0; }
+dl.indexdiv dt { margin-top: 0; }
+dl.indexdiv dd { margin-top: 0; margin-bottom: 0; }
+dl.setindex dt { margin-top: 0; }
+dl.setindex dd { margin-top: 0; margin-bottom: 0; }
+div.list div.title-formal span.title {
+  border-bottom: solid 1px #e0e0df;
+}
+div.simplelist {
+  margin-left: 1.72em;
+}
+div.simplelist table { margin-left: 0; border: none; }
+div.simplelist td {
+  padding: 0.5em;
+  border-left: solid 1px #e0e0df;
+}
+div.simplelist td.td-first {
+  padding-left: 0;
+  border-left: 0;
+}
+div.synopsis {
+  padding: 0.5em;
+  
+  background-color: #f9f9f6;
+  border-top: solid 2px #c0c9ff;
+  border-bottom: solid 2px #c0c9ff;
+}
+div.synopsis div.synopsis {
+  padding: 0;
+  border: none;
+}
+div.synopsis div.block { margin-top: 0.2em; }
+div.synopsis div.block-first { margin-top: 0; }
+div.cmdsynopsis { font-family: monospace; }
+
+span.accel { text-decoration: underline; }
+span.acronym { font-family: sans-serif; }
+span.application { font-style: italic; }
+span.classname, span.exceptionname, span.interfacename { font-family: monospace; }
+span.code {
+  font-family: monospace;
+  border: solid 1px #e0e0df;
+  padding-left: 0.2em;
+  padding-right: 0.2em;
+}
+pre span.code { border: none; padding: 0; }
+span.command {
+  font-family: monospace;
+  border: solid 1px #e0e0df;
+  padding-left: 0.2em;
+  padding-right: 0.2em;
+}
+pre span.command { border: none; padding: 0; }
+span.computeroutput { font-family: monospace; }
+
+span.constant { font-family: monospace; }
+span.database { font-family: monospace; }
+span.email { font-family: monospace; }
+span.emphasis { font-style: italic; }
+span.emphasis-bold { font-style: normal; font-weight: bold; }
+span.envar { font-family: monospace; }
+
+span.filename { font-family: monospace; }
+span.firstterm { font-style: italic; }
+span.foreignphrase { font-style: italic; }
+span.function { font-family: monospace; }
+
+dt.glossterm span.glossterm { font-style: normal; }
+
+
+span.glossterm { font-style: italic; }
+
+span.guibutton, span.guilabel, span.guimenu, span.guimenuitem, span.guisubmenu, span.interface {
+  font-weight: bold;
+  color: #3f3f3f;
+}
+span.keycap {
+  font-weight: bold;
+  color: #3f3f3f;
+}
+span.lineannotation { font-style: italic; }
+span.literal { font-family: monospace; }
+span.markup  { font-family: monospace; }
+span.medialabel { font-style: italic; }
+span.methodname { font-family: monospace; }
+span.ooclass, span.ooexception, span.oointerface { font-family: monospace; }
+span.option { font-family: monospace; }
+span.parameter { font-family: monospace; }
+span.paramdef span.parameter { font-style: italic; }
+span.prompt { font-family: monospace; }
+span.property { font-family: monospace; }
+span.replaceable  { font-style: italic; }
+span.returnvalue { font-family: monospace; }
+span.sgmltag { font-family: monospace; }
+span.structfield, span.structname { font-family: monospace; }
+span.symbol { font-family: monospace; }
+span.systemitem { font-family: monospace; }
+span.token { font-family: monospace; }
+span.type { font-family: monospace; }
+span.uri { font-family: monospace; }
+span.userinput { font-family: monospace; }
+span.varname { font-family: monospace; }
+span.wordasword { font-style: italic; }
+
+
+
+div.footnotes { font-style: italic; font-size: 0.8em; }
+div.footnote { margin-top: 1.44em; }
+span.footnote-number { display: inline; padding-right: 0.83em; }
+span.footnote-number + p { display: inline; }
+a.footnote { text-decoration: none; font-size: 0.8em; }
+a.footnote-ref { text-decoration: none; }
+
+span.co {
+  margin-left: 0.2em; margin-right: 0.2em;
+  padding-left: 0.4em; padding-right: 0.4em;
+  border: solid 1px #000000;
+  -moz-border-radius: 8px;
+  background-color: #000000;
+  color: #FFFFFF;
+  font-size: 8px;
+}
+span.co:hover {
+  border-color: #333333;
+  background-color: #333333;
+  color: #FFFFFF;
+}
+span.co a { text-decoration: none; }
+span.co a:hover { text-decoration: none; }
+
+dt.question { margin-left: 0em; }
+dt.question div.label { float: left; }
+dd + dt.question { margin-top: 1em; }
+dd.answer {
+  margin-top: 1em;
+  margin-left: 2em;
+  margin-right: 1em;
+}
+dd.answer div.label { float: left; }
+</style>
+</head>
+<body>
+<div class="navbar navbar-top"><table class="navbar"><tr>
+<td class="navbar-prev"><a class="navbar-prev" href="GuideReferencePixbufLoaders.html" title="Additional pixbuf loaders">Additional pixbuf loaders</a></td>
+<td class="navbar-next"><a class="navbar-next" href="GuideReferenceDecodeLatLong.html" title="Decoding Latitude and Longitude">Decoding Latitude and Longitude</a></td>
+</tr></table></div>
+<div class="sidebar"><div class="sidenav"><div class="autotoc"><ul>
+<li><a href="GuideIndex-info.html" title="About This Document">About This Document</a></li>
+<li>
+<a class="xref" href="GuideIndex.html" title="The Geeqie User Manual">The Geeqie User Manual</a><div class="autotoc"><ul>
+<li><a class="xref" href="GuideIntroduction.html" title="Introduction">Introduction</a></li>
+<li><a class="xref" href="GuideMainWindow.html" title="Main Window">Main Window</a></li>
+<li><a class="xref" href="GuideSidebars.html" title="Sidebars">Sidebars</a></li>
+<li><a class="xref" href="GuideOtherWindows.html" title="Stand-alone Windows">Stand-alone Windows</a></li>
+<li><a class="xref" href="GuideImageSearch.html" title="Search and Select">Search and Select</a></li>
+<li><a class="xref" href="GuideImageManagementPlugins.html" title="Plugins">Plugins</a></li>
+<li><a class="xref" href="GuideImageManagement.html" title="File Management">File Management</a></li>
+<li><a class="xref" href="GuideColorManagement.html" title="Color Management">Color Management</a></li>
+<li><a class="xref" href="GuideImagePresentation.html" title="Image Presentation">Image Presentation</a></li>
+<li><a class="xref" href="GuidePrinting.html" title="Printing">Printing</a></li>
+<li><a class="xref" href="GuideOptionsMain.html" title="Preferences">Preferences</a></li>
+<li><a class="xref" href="GuideOptionsAdditional.html" title="Additional Preferences">Additional Preferences</a></li>
+<li>
+<a class="xref" href="GuideReference.html" title="Reference">Reference</a><div class="autotoc"><ul>
+<li><a class="xref" href="GuideReferenceCommandLine.html" title="Command Line Options">Command Line Options</a></li>
+<li><a class="xref" href="GuideReferenceKeyboardShortcuts.html" title="Keyboard and Mouse Shortcuts">Keyboard and Mouse Shortcuts</a></li>
+<li><a class="xref" href="GuideReferenceThumbnails.html" title="Thumbnails">Thumbnails</a></li>
+<li><a class="xref" href="GuideReferenceMetadata.html" title="Metadata Processing">Metadata Processing</a></li>
+<li><a class="xref" href="GuideReferenceLua.html" title="Lua Extensions">Lua Extensions</a></li>
+<li><a class="xref" href="GuideReferenceConfig.html" title="Configuration Files and Locations">Configuration Files and Locations</a></li>
+<li><a class="xref" href="GuideReferenceLIRC.html" title="Infra-red controller">Infra-red controller</a></li>
+<li><a class="xref" href="GuideReferenceXmpExif.html" title="XMP, Exif and IPTC">XMP, Exif and IPTC</a></li>
+<li><a class="xref" href="GuideReferenceSupportedFormats.html" title="Supported File Formats">Supported File Formats</a></li>
+<li><a class="xref" href="GuideReferencePixbufLoaders.html" title="Additional pixbuf loaders">Additional pixbuf loaders</a></li>
+<li>UTC and Daylight Saving Time (DST)</li>
+<li><a class="xref" href="GuideReferenceDecodeLatLong.html" title="Decoding Latitude and Longitude">Decoding Latitude and Longitude</a></li>
+<li><a class="xref" href="GuideReferenceStandards.html" title="Standards">Standards</a></li>
+</ul></div>
+</li>
+<li><a class="xref" href="GuideFaq.html" title="Frequently Asked Questions">Frequently Asked Questions</a></li>
+<li><a class="xref" href="GuideLicence.html" title="Licence">Licence</a></li>
+<li><a class="xref" href="GuideCredits.html" title="Credits">Credits</a></li>
+<li><a class="xref" href="GuideGnuFdl.html" title="GNU Free Documentation License">GNU Free Documentation License</a></li>
+</ul></div>
+</li>
+</ul></div></div></div>
+<div class="body body-sidebar"><div class="division section">
+<a name="GuideReferenceUTC"></a><div class="header"><h1 class="section title"><span class="title"><a name="titleGuideReferenceUTC"></a>UTC and Daylight Saving Time (DST)</span></h1></div>
+<ul class="linktrail">
+<li class="linktrail linktrail-first"><a class="linktrail" href="GuideIndex.html" title="The Geeqie User Manual">The Geeqie User Manual</a></li>
+<li class="linktrail linktrail-last"><a class="linktrail" href="GuideReference.html" title="Reference">Reference</a></li>
+</ul>
+<p class="para block block-first">Geeqie can display the local time at which a photo was taken, adjusted for UTC offset and Daylight Saving Time.</p>
+<p class="para block">
+    If the image exif data contains the required parameters (see
+    <a class="link" href="GuideReferenceXmpExif.html" title="XMP, Exif and IPTC">Pre-formatted tags</a>
+    ), Geeqie will use the latitude and longitude to determine which timezone the image was taken in.
+    <p class="para block"></p>
+    The UTC offset and Daylight Saving Time Correction for that timezone, combined with the GPS UTC value, will then be used to compute the correct local time.
+    <p class="para block"></p>
+    This value may be displayed in either the Info Sidebar or Overlay Screen Display by using the parameter
+    <span class="code" dir="ltr">formatted.localtime</span>
+  </p>
+<p class="para block">
+    The timezone for the image may also be displayed by using the parameter
+    <span class="code" dir="ltr">formatted.timezone</span>
+    .
+  </p>
+</div></div>
+<div class="navbar navbar-bottom"><table class="navbar"><tr>
+<td class="navbar-prev"><a class="navbar-prev" href="GuideReferencePixbufLoaders.html" title="Additional pixbuf loaders">Additional pixbuf loaders</a></td>
+<td class="navbar-next"><a class="navbar-next" href="GuideReferenceDecodeLatLong.html" title="Decoding Latitude and Longitude">Decoding Latitude and Longitude</a></td>
+</tr></table></div>
+</body>
+</html>
index cf7c88f..95d67ca 100644 (file)
@@ -441,6 +441,7 @@ dd.answer div.label { float: left; }
 <li>XMP, Exif and IPTC</li>
 <li><a class="xref" href="GuideReferenceSupportedFormats.html" title="Supported File Formats">Supported File Formats</a></li>
 <li><a class="xref" href="GuideReferencePixbufLoaders.html" title="Additional pixbuf loaders">Additional pixbuf loaders</a></li>
+<li><a class="xref" href="GuideReferenceUTC.html" title="UTC and Daylight Saving Time (DST)">UTC and Daylight Saving Time (DST)</a></li>
 <li><a class="xref" href="GuideReferenceDecodeLatLong.html" title="Decoding Latitude and Longitude">Decoding Latitude and Longitude</a></li>
 <li><a class="xref" href="GuideReferenceStandards.html" title="Standards">Standards</a></li>
 </ul></div>
@@ -687,9 +688,54 @@ dd.answer div.label { float: left; }
             </td>
 </tr>
 <tr class="tr-shade">
-<td class="td-colsep">
+<td class="td-colsep td-rowsep">
               <span class="para">formatted.GPSPosition</span>
             </td>
+<td class="td-colsep td-rowsep">
+              <span class="para">
+                Exif.GPSInfo.GPSLatitude
+                <p class="para block block-first"></p>
+                Exif.GPSInfo.GPSLatitudeRef
+                <p class="para block"></p>
+                Exif.GPSInfo.GPSLongitude
+                <p class="para block"></p>
+                Exif.GPSInfo.GPSLongitudeRef
+              </span>
+            </td>
+<td class="td-rowsep">
+              <span class="para">Latitude, Longitude</span>
+            </td>
+</tr>
+<tr>
+<td class="td-colsep td-rowsep">
+              <span class="para">formatted.localtime</span>
+            </td>
+<td class="td-colsep td-rowsep">
+              <span class="para">
+                Exif.GPSInfo.GPSLatitude
+                <p class="para block block-first"></p>
+                Exif.GPSInfo.GPSLatitudeRef
+                <p class="para block"></p>
+                Exif.GPSInfo.GPSLongitude
+                <p class="para block"></p>
+                Exif.GPSInfo.GPSLongitudeRef
+                <p class="para block"></p>
+                Exif.GPSInfo.GPSDateStamp
+                <p class="para block"></p>
+                Exif.GPSInfo.GPSTimeStamp
+              </span>
+            </td>
+<td class="td-rowsep">
+              <span class="para">
+                Local time corrected for UTC offset, DST correction
+                <a name="-noteref-ref1"></a><sup><a class="footnote" href="#ref1">1</a></sup>
+              </span>
+            </td>
+</tr>
+<tr class="tr-shade">
+<td class="td-colsep">
+              <span class="para">formatted.timezone</span>
+            </td>
 <td class="td-colsep">
               <span class="para">
                 Exif.GPSInfo.GPSLatitude
@@ -702,7 +748,10 @@ dd.answer div.label { float: left; }
               </span>
             </td>
 <td>
-              <span class="para">Latitude, Longitude</span>
+              <span class="para">
+                Timezone indicated by lat/long
+                <a name="-noteref-ref1"></a><sup><a class="footnote" href="#ref1">2</a></sup>
+              </span>
             </td>
 </tr>
 </tbody>
@@ -787,6 +836,14 @@ dd.answer div.label { float: left; }
             </td>
 </tr>
 <tr>
+<td class="td-colsep td-rowsep">
+              <span class="para">formatted.timezone</span>
+            </td>
+<td class="td-rowsep">
+              <span class="para">Time zone</span>
+            </td>
+</tr>
+<tr class="tr-shade">
 <td class="td-colsep td-rowsep">
               <span class="para">Xmp.photoshop.Country</span>
             </td>
@@ -794,7 +851,7 @@ dd.answer div.label { float: left; }
               <span class="para">Country</span>
             </td>
 </tr>
-<tr class="tr-shade">
+<tr>
 <td class="td-colsep td-rowsep">
               <span class="para">
                 <p class="para block block-first">Xmp.iptc.CountryCode</p>
@@ -804,7 +861,7 @@ dd.answer div.label { float: left; }
               <span class="para">Country Code</span>
             </td>
 </tr>
-<tr>
+<tr class="tr-shade">
 <td class="td-colsep td-rowsep">
               <span class="para">Xmp.photoshop.State</span>
             </td>
@@ -812,7 +869,7 @@ dd.answer div.label { float: left; }
               <span class="para">State</span>
             </td>
 </tr>
-<tr class="tr-shade">
+<tr>
 <td class="td-colsep td-rowsep">
               <span class="para">Xmp.photoshop.City</span>
             </td>
@@ -820,7 +877,7 @@ dd.answer div.label { float: left; }
               <span class="para">City</span>
             </td>
 </tr>
-<tr>
+<tr class="tr-shade">
 <td class="td-colsep">
               <span class="para">Xmp.iptc.Location</span>
             </td>
@@ -899,6 +956,14 @@ dd.answer div.label { float: left; }
             </td>
 </tr>
 <tr>
+<td class="td-colsep td-rowsep">
+              <span class="para">formatted.localtime</span>
+            </td>
+<td class="td-rowsep">
+              <span class="para">Local time</span>
+            </td>
+</tr>
+<tr class="tr-shade">
 <td class="td-colsep td-rowsep">
               <span class="para">formatted.ShutterSpeed</span>
             </td>
@@ -906,7 +971,7 @@ dd.answer div.label { float: left; }
               <span class="para">Shutter speed</span>
             </td>
 </tr>
-<tr class="tr-shade">
+<tr>
 <td class="td-colsep td-rowsep">
               <span class="para">formatted.Aperture</span>
             </td>
@@ -914,7 +979,7 @@ dd.answer div.label { float: left; }
               <span class="para">Aperture</span>
             </td>
 </tr>
-<tr>
+<tr class="tr-shade">
 <td class="td-colsep td-rowsep">
               <span class="para">formatted.ExposureBias</span>
             </td>
@@ -922,7 +987,7 @@ dd.answer div.label { float: left; }
               <span class="para">Exposure bias</span>
             </td>
 </tr>
-<tr class="tr-shade">
+<tr>
 <td class="td-colsep td-rowsep">
               <span class="para">formatted.ISOSpeedRating</span>
             </td>
@@ -930,7 +995,7 @@ dd.answer div.label { float: left; }
               <span class="para">ISO sensitivity</span>
             </td>
 </tr>
-<tr>
+<tr class="tr-shade">
 <td class="td-colsep td-rowsep">
               <span class="para">formatted.FocalLength</span>
             </td>
@@ -938,7 +1003,7 @@ dd.answer div.label { float: left; }
               <span class="para">Focal length</span>
             </td>
 </tr>
-<tr class="tr-shade">
+<tr>
 <td class="td-colsep td-rowsep">
               <span class="para">formatted.FocalLength35mmFilm</span>
             </td>
@@ -946,7 +1011,7 @@ dd.answer div.label { float: left; }
               <span class="para">Focal length 35mm</span>
             </td>
 </tr>
-<tr>
+<tr class="tr-shade">
 <td class="td-colsep td-rowsep">
               <span class="para">formatted.SubjectDistance</span>
             </td>
@@ -954,7 +1019,7 @@ dd.answer div.label { float: left; }
               <span class="para">Subject distance</span>
             </td>
 </tr>
-<tr class="tr-shade">
+<tr>
 <td class="td-colsep td-rowsep">
               <span class="para">formatted.Flash</span>
             </td>
@@ -962,7 +1027,7 @@ dd.answer div.label { float: left; }
               <span class="para">Flash</span>
             </td>
 </tr>
-<tr>
+<tr class="tr-shade">
 <td class="td-colsep td-rowsep">
               <span class="para">formatted.Resolution</span>
             </td>
@@ -970,7 +1035,7 @@ dd.answer div.label { float: left; }
               <span class="para">Resolution</span>
             </td>
 </tr>
-<tr class="tr-shade">
+<tr>
 <td class="td-colsep td-rowsep">
               <span class="para">formatted.ColorProfile</span>
             </td>
@@ -978,7 +1043,7 @@ dd.answer div.label { float: left; }
               <span class="para">Color profile</span>
             </td>
 </tr>
-<tr>
+<tr class="tr-shade">
 <td class="td-colsep td-rowsep">
               <span class="para">Exif.Photo.ExposureProgram</span>
             </td>
@@ -986,7 +1051,7 @@ dd.answer div.label { float: left; }
               <span class="para">Exposure Program</span>
             </td>
 </tr>
-<tr class="tr-shade">
+<tr>
 <td class="td-colsep td-rowsep">
               <span class="para">Exif.Photo.MeteringMode</span>
             </td>
@@ -994,7 +1059,7 @@ dd.answer div.label { float: left; }
               <span class="para">Metering Mode</span>
             </td>
 </tr>
-<tr>
+<tr class="tr-shade">
 <td class="td-colsep">
               <span class="para">Exif.Photo.LightSource</span>
             </td>
@@ -1200,6 +1265,24 @@ dd.answer div.label { float: left; }
 </table>
 </div>
 </div>
+<div class="footnotes">
+<div class="footnote">
+<a name="ref1"></a><span class="footnote-number"><a class="footnote-ref" href="#-noteref-ref1">1</a></span>
+                  <p class="para block block-first">
+                    Refer to
+                    <a class="link" href="GuideReferenceUTC.html" title="UTC and Daylight Saving Time (DST)">UTC and DST</a>
+                    section.
+                  </p>
+                </div>
+<div class="footnote">
+<a name="ref1"></a><span class="footnote-number"><a class="footnote-ref" href="#-noteref-ref1">2</a></span>
+                  <p class="para block block-first">
+                    Refer to
+                    <a class="link" href="GuideReferenceUTC.html" title="UTC and Daylight Saving Time (DST)">UTC and DST</a>
+                    section.
+                  </p>
+                </div>
+</div>
 </div></div>
 <div class="navbar navbar-bottom"><table class="navbar"><tr>
 <td class="navbar-prev"><a class="navbar-prev" href="GuideReferenceLIRC.html" title="Infra-red controller">Infra-red controller</a></td>
index 44ba71d..cd78e8c 100644 (file)
@@ -708,6 +708,20 @@ dd.answer div.label { float: left; }
 <td class="td-rowsep">Latitude, Longitude</td>
 </tr>
 <tr class="tr-shade">
+<td class="td-colsep td-rowsep">formatted.localtime</td>
+<td class="td-rowsep">
+              Local time corrected for UTC offset, DST correction
+              <a name="-noteref-ref1"></a><sup><a class="footnote" href="#ref1">1</a></sup>
+            </td>
+</tr>
+<tr>
+<td class="td-colsep td-rowsep">formatted.timezone</td>
+<td class="td-rowsep">
+              Timezone indicated by GPS lat/long values
+              <a name="-noteref-ref1"></a><sup><a class="footnote" href="#ref1">2</a></sup>
+            </td>
+</tr>
+<tr class="tr-shade">
 <td class="td-colsep td-rowsep">file.size</td>
 <td class="td-rowsep">file size in bytes</td>
 </tr>
@@ -817,6 +831,24 @@ dd.answer div.label { float: left; }
       </li>
 </ul></div>
 </div>
+<div class="footnotes">
+<div class="footnote">
+<a name="ref1"></a><span class="footnote-number"><a class="footnote-ref" href="#-noteref-ref1">1</a></span>
+                <p class="para block block-first">
+                  Refer to
+                  <a class="link" href="GuideReferenceUTC.html" title="UTC and Daylight Saving Time (DST)">UTC and DST</a>
+                  section.
+                </p>
+              </div>
+<div class="footnote">
+<a name="ref1"></a><span class="footnote-number"><a class="footnote-ref" href="#-noteref-ref1">2</a></span>
+                <p class="para block block-first">
+                  Refer to
+                  <a class="link" href="GuideReferenceUTC.html" title="UTC and Daylight Saving Time (DST)">UTC and DST</a>
+                  section.
+                </p>
+              </div>
+</div>
 </div></div>
 <div class="navbar navbar-bottom"><table class="navbar"><tr>
 <td class="navbar-prev"><a class="navbar-prev" href="GuideSidebarsInfo.html" title="Info Sidebar">Info Sidebar</a></td>