Mercurial > hg > forks > geeqie
changeset 2746:8bab8ac8ade0
Local time - UTC offset and daylight saving correction
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
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ZoneDetect.md Wed Apr 25 11:46:38 2018 +0100 @@ -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.
--- a/configure.in Thu Apr 12 11:34:52 2018 +0100 +++ b/configure.in Wed Apr 25 11:46:38 2018 +0100 @@ -590,6 +590,7 @@ plugins/ufraw/Makefile plugins/import/Makefile plugins/geocode-parameters/Makefile + plugins/ZoneDetect/Makefile geeqie.spec ])
--- a/doc/docbook/GuideReference.xml Thu Apr 12 11:34:52 2018 +0100 +++ b/doc/docbook/GuideReference.xml Wed Apr 25 11:46:38 2018 +0100 @@ -11,6 +11,7 @@ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="GuideReferenceTags.xml" /> <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="GuideReferenceSupportedFormats.xml" /> <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="GuideReferencePixbufLoaders.xml" /> + <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="GuideReferenceUTC.xml" /> <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="GuideReferenceDecodeLatLong.xml" /> <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="GuideReferenceStandards.xml" /> <para />
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/doc/docbook/GuideReferenceFileDates.xml Wed Apr 25 11:46:38 2018 +0100 @@ -0,0 +1,19 @@ +<?xml version="1.0" encoding="utf-8"?> +<section id="GuideReferenceFileDates"> + <title>File date types</title> + <para>Geeqie understands 4 types of file dates:</para> + <itemizedlist spacing="compact"> + <listitem> + <para>Standard date (mtime) - The date the file contents were last modified, or when the file was created if since unchanged.</para> + </listitem> + <listitem> + <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> + </listitem> + <listitem> + <para>Exif date original (Exif.Photo.DateTimeOriginal) - For images from a digital camera, this is the time the photo was taken.</para> + </listitem> + <listitem> + <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> + </listitem> + </itemizedlist> +</section>
--- a/doc/docbook/GuideReferenceTags.xml Thu Apr 12 11:34:52 2018 +0100 +++ b/doc/docbook/GuideReferenceTags.xml Wed Apr 25 11:46:38 2018 +0100 @@ -239,6 +239,66 @@ <para>Latitude, Longitude</para> </entry> </row> + <row> + <entry> + <para>formatted.localtime</para> + </entry> + <entry> + <para> + Exif.GPSInfo.GPSLatitude + <para /> + Exif.GPSInfo.GPSLatitudeRef + <para /> + Exif.GPSInfo.GPSLongitude + <para /> + Exif.GPSInfo.GPSLongitudeRef + <para /> + Exif.GPSInfo.GPSDateStamp + <para /> + Exif.GPSInfo.GPSTimeStamp + </para> + </entry> + <entry> + <para> + Local time corrected for UTC offset, DST correction + <footnote id='ref1'> + <para> + Refer to + <link linkend="GuideReferenceUTC">UTC and DST</link> + section. + </para> + </footnote> + </para> + </entry> + </row> + <row> + <entry> + <para>formatted.timezone</para> + </entry> + <entry> + <para> + Exif.GPSInfo.GPSLatitude + <para /> + Exif.GPSInfo.GPSLatitudeRef + <para /> + Exif.GPSInfo.GPSLongitude + <para /> + Exif.GPSInfo.GPSLongitudeRef + </para> + </entry> + <entry> + <para> + Timezone indicated by lat/long + <footnote id='ref1'> + <para> + Refer to + <link linkend="GuideReferenceUTC">UTC and DST</link> + section. + </para> + </footnote> + </para> + </entry> + </row> </tbody> </tgroup> </table> @@ -326,6 +386,14 @@ </row> <row> <entry> + <para>formatted.timezone</para> + </entry> + <entry> + <para>Time zone</para> + </entry> + </row> + <row> + <entry> <para>Xmp.photoshop.Country</para> </entry> <entry> @@ -442,6 +510,14 @@ </row> <row> <entry> + <para>formatted.localtime</para> + </entry> + <entry> + <para>Local time</para> + </entry> + </row> + <row> + <entry> <para>formatted.ShutterSpeed</para> </entry> <entry>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/doc/docbook/GuideReferenceUTC.xml Wed Apr 25 11:46:38 2018 +0100 @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="utf-8"?> +<section id="GuideReferenceUTC"> + <title id="titleGuideReferenceUTC">UTC and Daylight Saving Time (DST)</title> + <para>Geeqie can display the local time at which a photo was taken, adjusted for UTC offset and Daylight Saving Time.</para> + <para> + If the image exif data contains the required parameters (see + <link linkend="GuideReferenceXmpExif">Pre-formatted tags</link> + ), Geeqie will use the latitude and longitude to determine which timezone the image was taken in. + <para /> + 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. + <para /> + This value may be displayed in either the Info Sidebar or Overlay Screen Display by using the parameter + <code>formatted.localtime</code> + </para> + <para> + The timezone for the image may also be displayed by using the parameter + <code>formatted.timezone</code> + . + </para> +</section>
--- a/doc/docbook/GuideSidebarsInfo.xml Thu Apr 12 11:34:52 2018 +0100 +++ b/doc/docbook/GuideSidebarsInfo.xml Wed Apr 25 11:46:38 2018 +0100 @@ -251,6 +251,32 @@ <entry>Latitude, Longitude</entry> </row> <row> + <entry>formatted.localtime</entry> + <entry> + Local time corrected for UTC offset, DST correction + <footnote id='ref1'> + <para> + Refer to + <link linkend="GuideReferenceUTC">UTC and DST</link> + section. + </para> + </footnote> + </entry> + </row> + <row> + <entry>formatted.timezone</entry> + <entry> + Timezone indicated by GPS lat/long values + <footnote id='ref1'> + <para> + Refer to + <link linkend="GuideReferenceUTC">UTC and DST</link> + section. + </para> + </footnote> + </entry> + </row> + <row> <entry>file.size</entry> <entry>file size in bytes</entry> </row>
--- a/plugins/Makefile.am Thu Apr 12 11:34:52 2018 +0100 +++ b/plugins/Makefile.am Wed Apr 25 11:46:38 2018 +0100 @@ -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
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/plugins/ZoneDetect/Makefile.am Wed Apr 25 11:46:38 2018 +0100 @@ -0,0 +1,1 @@ +dist_gq_bin_SCRIPTS = timezone21.bin
--- a/src/Makefile.am Thu Apr 12 11:34:52 2018 +0100 +++ b/src/Makefile.am Wed Apr 25 11:46:38 2018 +0100 @@ -264,7 +264,9 @@ 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)
--- a/src/bar.c Thu Apr 12 11:34:52 2018 +0100 +++ b/src/bar.c Wed Apr 25 11:46:38 2018 +0100 @@ -99,6 +99,7 @@ " <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 @@ " <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' />"
--- a/src/exif-common.c Thu Apr 12 11:34:52 2018 +0100 +++ b/src/exif-common.c Wed Apr 25 11:46:38 2018 +0100 @@ -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 @@ 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 @@ 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},
--- a/src/main.h Thu Apr 12 11:34:52 2018 +0100 +++ b/src/main.h Wed Apr 25 11:46:38 2018 +0100 @@ -123,6 +123,8 @@ #include "options.h" #define DESKTOP_FILE_TEMPLATE GQ_APP_DIR "/template.desktop" + +#define TIMEZONE_DATABASE "timezone21.bin" /* *---------------------------------------------------------------------------- * main.c
--- a/src/preferences.c Thu Apr 12 11:34:52 2018 +0100 +++ b/src/preferences.c Wed Apr 25 11:46:38 2018 +0100 @@ -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 @@ 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 @@ "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 Thu Jan 01 00:00:00 1970 +0000 +++ b/src/zonedetect.c Wed Apr 25 11:46:38 2018 +0100 @@ -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"; +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/zonedetect.h Wed Apr 25 11:46:38 2018 +0100 @@ -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
--- a/web/help/GuideIndex.html Thu Apr 12 11:34:52 2018 +0100 +++ b/web/help/GuideIndex.html Wed Apr 25 11:46:38 2018 +0100 @@ -648,10 +648,13 @@ <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>
--- a/web/help/GuideReference.html Thu Apr 12 11:34:52 2018 +0100 +++ b/web/help/GuideReference.html Wed Apr 25 11:46:38 2018 +0100 @@ -440,6 +440,7 @@ <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 @@ <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>
--- a/web/help/GuideReferenceCommandLine.html Thu Apr 12 11:34:52 2018 +0100 +++ b/web/help/GuideReferenceCommandLine.html Wed Apr 25 11:46:38 2018 +0100 @@ -441,6 +441,7 @@ <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>
--- a/web/help/GuideReferenceConfig.html Thu Apr 12 11:34:52 2018 +0100 +++ b/web/help/GuideReferenceConfig.html Wed Apr 25 11:46:38 2018 +0100 @@ -441,6 +441,7 @@ <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>
--- a/web/help/GuideReferenceDecodeLatLong.html Thu Apr 12 11:34:52 2018 +0100 +++ b/web/help/GuideReferenceDecodeLatLong.html Wed Apr 25 11:46:38 2018 +0100 @@ -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 @@ </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 @@ <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 @@ </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>
--- a/web/help/GuideReferenceKeyboardShortcuts.html Thu Apr 12 11:34:52 2018 +0100 +++ b/web/help/GuideReferenceKeyboardShortcuts.html Wed Apr 25 11:46:38 2018 +0100 @@ -441,6 +441,7 @@ <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>
--- a/web/help/GuideReferenceLIRC.html Thu Apr 12 11:34:52 2018 +0100 +++ b/web/help/GuideReferenceLIRC.html Wed Apr 25 11:46:38 2018 +0100 @@ -441,6 +441,7 @@ <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>
--- a/web/help/GuideReferenceLua.html Thu Apr 12 11:34:52 2018 +0100 +++ b/web/help/GuideReferenceLua.html Wed Apr 25 11:46:38 2018 +0100 @@ -441,6 +441,7 @@ <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>
--- a/web/help/GuideReferenceMetadata.html Thu Apr 12 11:34:52 2018 +0100 +++ b/web/help/GuideReferenceMetadata.html Wed Apr 25 11:46:38 2018 +0100 @@ -441,6 +441,7 @@ <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>
--- a/web/help/GuideReferencePixbufLoaders.html Thu Apr 12 11:34:52 2018 +0100 +++ b/web/help/GuideReferencePixbufLoaders.html Wed Apr 25 11:46:38 2018 +0100 @@ -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 @@ <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 @@ <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 @@ </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>
--- a/web/help/GuideReferenceStandards.html Thu Apr 12 11:34:52 2018 +0100 +++ b/web/help/GuideReferenceStandards.html Wed Apr 25 11:46:38 2018 +0100 @@ -441,6 +441,7 @@ <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>
--- a/web/help/GuideReferenceSupportedFormats.html Thu Apr 12 11:34:52 2018 +0100 +++ b/web/help/GuideReferenceSupportedFormats.html Wed Apr 25 11:46:38 2018 +0100 @@ -441,6 +441,7 @@ <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>
--- a/web/help/GuideReferenceThumbnails.html Thu Apr 12 11:34:52 2018 +0100 +++ b/web/help/GuideReferenceThumbnails.html Wed Apr 25 11:46:38 2018 +0100 @@ -441,6 +441,7 @@ <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 Thu Jan 01 00:00:00 1970 +0000 +++ b/web/help/GuideReferenceUTC.html Wed Apr 25 11:46:38 2018 +0100 @@ -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>
--- a/web/help/GuideReferenceXmpExif.html Thu Apr 12 11:34:52 2018 +0100 +++ b/web/help/GuideReferenceXmpExif.html Wed Apr 25 11:46:38 2018 +0100 @@ -441,6 +441,7 @@ <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,8 +688,53 @@ </td> </tr> <tr class="tr-shade"> +<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.GPSPosition</span> + <span class="para">formatted.timezone</span> </td> <td class="td-colsep"> <span class="para"> @@ -702,7 +748,10 @@ </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> @@ -788,13 +837,21 @@ </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> <td class="td-rowsep"> <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 @@ <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 @@ <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 @@ <span class="para">City</span> </td> </tr> -<tr> +<tr class="tr-shade"> <td class="td-colsep"> <span class="para">Xmp.iptc.Location</span> </td> @@ -900,13 +957,21 @@ </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> <td class="td-rowsep"> <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 @@ <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 @@ <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 @@ <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 @@ <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 @@ <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 @@ <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 @@ <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 @@ <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 @@ <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 @@ <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 @@ <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 @@ </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>
--- a/web/help/GuideSidebarsInfo.html Thu Apr 12 11:34:52 2018 +0100 +++ b/web/help/GuideSidebarsInfo.html Wed Apr 25 11:46:38 2018 +0100 @@ -708,6 +708,20 @@ <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 @@ </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>