Skip to content

Serious issues with timezone support in time functions #4637

Closed
@bperrybap

Description

@bperrybap

Platform

  • Hardware: [ESP-12]
  • Core Version: [2.4.1]
  • Development Env: [Arduino IDE]
  • Operating System: [Linux Mint 17.3]

Settings in IDE

  • Module: [Wemos D1]
  • Flash Mode: [qio|dio|other]
  • Flash Size: [4MB/1MB]
  • lwip Variant: [v1.4|v2 Lower Memory|Higher Bandwidth]
  • Reset Method: [ck|nodemcu]
  • Flash Frequency: [40Mhz]
  • CPU Frequency: [80Mhz|160MHz]
  • Upload Using: [OTA|SERIAL]
  • Upload Speed: [115200|other] (serial upload only)

Problem Description

The are some serious issues with how timezone offsets are being handled in various time functions.
There was mention of some issues in the discussion about the
NTP-TZ-DST.ino demo sketch in issue #3835
That issue mentioned issues with gmtime() and localtime() but the issues are much more serious.
Here is the behavior I've seen - using the NTP-TZ-DST.ino demo sketch with a few tweaks to see the behavior of gettimeofday() as well.
The results were the same regardless of whether NTP was used or the "fake" RTC mode was used.

  • The time_t returned by time() does not equal the tv_sec value returned by gettimeofday()
    They should always be the same value.

  • gettimeofday() in the tv_sec member returned, is always supposed to return the number of seconds since the epoch without any consideration or alteration based on local timezone.
    This is working correctly.

  • time() is always supposed to return the number of seconds since the epoch without any consideration or alteration based on local timezone.
    This is not working correctly
    time() is returning a time_t that has been adjusted/modified and is offset by the specified timezone information.
    This is incorrect. time() has modified that actual time_t timestamp it returns. time_t timestamp values are not be modified for the local time. Any correction for local time should be handled by localtime() or ctime()

  • gmtime() and localtime() are currently generating the same broken down time elements.
    This is incorrect.
    They both take the time_t value and break down it into its components based on the time_t value provided with no adjustments for timezone.
    The issue is actually with localtime()
    localtime() is behaving just like gmtime() and is not adjusting the time for the timezone offsets.
    This is easily be demonstrated by handing both localtime() and gmtime() a zero value time_t.
    Both will generate the identical GMT time at the epoch.

These issues have likely been masked/hidden since many users that are setting timezone information are then calling localtime() with the time_t value from time(). While the fields created by localtime() when handed a time_t from time() will be correct, the time adjustment is being done incorrectly since the time_t was adjusted by time() rather than localtime() doing the timezone adjustment.

localtime() will fail to work correctly when handed the tv_sec value from gettimeofday() (it will show GMT)
gmtime() will fail to work correctly when handed the time_t from time() (it will show local time since time() is returning an incorrect time_t value)


I'm not sure how this can be fixed since it appears to be an issue in code outside of this source tree.
It seems like until it is fixed, users using the time code with timezone offsets need to know and understand the issues.
Until it gets fixed, perhaps some notes and big warnings could be placed in the comments in the
NTP-TZ-DST.ino demo sketch

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions