--- /dev/null
+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.
plugins/ufraw/Makefile
plugins/import/Makefile
plugins/geocode-parameters/Makefile
+ plugins/ZoneDetect/Makefile
geeqie.spec
])
<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
--- /dev/null
+<?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
<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
--- /dev/null
+<?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
<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
#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
--- /dev/null
+dist_gq_bin_SCRIPTS = timezone21.bin
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)
" <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' />"
" <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' />"
#include "ui_fileops.h"
#include "cache.h"
#include "jpeg_parser.h"
+#include "zonedetect.h"
static gdouble exif_rational_to_double(ExifRational *r, gint sign)
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 }
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},
#include "options.h"
#define DESKTOP_FILE_TEMPLATE GQ_APP_DIR "/template.desktop"
+
+#define TIMEZONE_DATABASE "timezone21.bin"
/*
*----------------------------------------------------------------------------
* main.c
#include "ui_tabcomp.h"
#include "ui_utildlg.h"
#include "window.h"
+#include "zonedetect.h"
#include <math.h>
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);
"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)
{
--- /dev/null
+/*
+ * 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";
+}
+
--- /dev/null
+/*
+ * 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
<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>
<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>
<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>
<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>
<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>
<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">
</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>
<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>
</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>
<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>
<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>
<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>
<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>
<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">
<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>
<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>
</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>
<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>
<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>
<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>
--- /dev/null
+<!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>
<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>
</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
</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>
</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>
<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>
<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>
<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>
<span class="para">City</span>
</td>
</tr>
-<tr>
+<tr class="tr-shade">
<td class="td-colsep">
<span class="para">Xmp.iptc.Location</span>
</td>
</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>
<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>
<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>
<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>
<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>
<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>
<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>
<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>
<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>
<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>
<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>
<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>
<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>
</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>
<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>
</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>