classification
Title: Manual entry for time.daylight can be misleading
Type: behavior Stage: resolved
Components: Documentation Versions: Python 3.1, Python 3.2, Python 2.7, Python 2.6
process
Status: closed Resolution: rejected
Dependencies: Superseder: Don't use east/west of UTC in date/time documentation
View: 9305
Assigned To: belopolsky Nosy List: belopolsky, docs@python, georg.brandl, kralph, napik, techtonik
Priority: normal Keywords: needs review, patch

Created on 2009-10-28 09:44 by napik, last changed 2014-06-30 03:36 by berker.peksag. This issue is now closed.

Files
File name Uploaded Description Edit
issue7229_daylight_doc_misleading.diff techtonik, 2010-02-09 09:32 patch review
time_reword.diff brian.curtin, 2010-02-09 16:28 review
Messages (25)
msg94621 - (view) Author: Tomas Kubes (napik) Date: 2009-10-28 09:44
Hello,

it is not obvious that the time.daylight data item reports nonzero
values even when DST is currently not being used (ie. in winter) but the
active timezone has DST defined for some other parts of the year.

Current manual entry can be misleadingly interpreted that time.daylight
acts as a current DST idicator (which it does not).

Suggested FIX: Add a sentence:
This value does not idicate that DST is currently active, but rather
describes that current timezone can have DST. Use localtime() dst flag
to determine if DST applies to the given time.


Tomas
msg99099 - (view) Author: anatoly techtonik (techtonik) Date: 2010-02-09 09:32
Run into the same problem in issue #7582. Patch attached, but wording can be improved.

http://docs.python.org/library/time.html#time.daylight
msg99103 - (view) Author: anatoly techtonik (techtonik) Date: 2010-02-09 11:02
Perhaps altzone() documentation is also wrong.  Brian, can you comment on this? 

http://docs.python.org/library/time.html#time.altzone
msg99122 - (view) Author: Brian Curtin (brian.curtin) * (Python committer) Date: 2010-02-09 16:28
I don't think altzone was incorrect, but it could also use a little rewording. Attached is a patch which rewords daylight and altzone. Thoughts?
msg107142 - (view) Author: anatoly techtonik (techtonik) Date: 2010-06-05 15:48
issue8907 seems related.
msg107148 - (view) Author: Alexander Belopolsky (belopolsky) * (Python committer) Date: 2010-06-05 16:32
It may be a bit off-topic for this issue, but I don't like that the python manual uses UTC as if it was a geographical location.  UTC is a time scale.  You cannot be to the east or to the west of UTC just as you cannot be to the north of the Gregorian calendar.

Even if we replace UTC with Prime or Greenwich Meridian, the manual would still be incorrect because some regions in the western hemisphere use positive offsets from UTC.  For example, Madrid is at 3° 42' West, but uses Central European Time which is UTC+1.

Since there are no plans to include any kind of geographical database in  the standard library, I think the manual should avoid use of geographical terms.

What I need to know from the manual is how to get local time from utc and daylight savings time from the standard time.

From the top of my head, I know that localtime = utctime + utcoffset, but I am not sure whether dsttime = stdtime + dst or dsttime = stdtime - dst and the manual, reworded or not, does not immediately help me.

As for the original issue, do we really need time.daylight at all?  ISTM that in timezones without DST, time.altzone = time.timezone, so the software that unconditionally accounts for DST will still work correctly and software that wants to optimize for no DST case can simply chsck time.altzone == time.timezone.

$ TZ=UTC ./python.exe -c "import time; print(time.daylight, time.tzname, (time.timezone, time.altzone))"
0 ('UTC', 'UTC') (0, 0)

In other words, time.daylight is strictly redundant.
msg107153 - (view) Author: anatoly techtonik (techtonik) Date: 2010-06-05 17:24
It is too hard to track this issue without quotes from manual. Let's bring context into discussion:

http://docs.python.org/library/time.html#time.altzone
  UTC offset of the local DST timezone if one is defined. Only use this if daylight is nonzero.
http://docs.python.org/library/time.html#time.daylight
  Nonzero if a DST timezone is defined.
http://docs.python.org/library/time.html#time.timezone
  UTC offset of the local (non-DST) timezone


So, to answer a question "What is the current UTC offset?" you need to:
if time.daylight:
  if time.altzone: # using only if defined
     use time.altzone
  else:
     use time.timezone
else:
  use time.timezone


1. Is that really works like described above?
2. Should we at least group these timezone variables?


As for offtopic UTC vs GMT - I doubt there is a way to clearly express that the offset sign of the returned values is negated in comparison with real "UTC offsets" without resorting to some king of alternative east/west scale.
msg107155 - (view) Author: Alexander Belopolsky (belopolsky) * (Python committer) Date: 2010-06-05 17:43
On Sat, Jun 5, 2010 at 1:24 PM, anatoly techtonik
<report@bugs.python.org> wrote:
..
> As for offtopic UTC vs GMT - I doubt there is a way to clearly express that the offset sign of the
> returned values is negated in comparison with real "UTC offsets" without resorting to some
> king of alternative east/west scale.

Sure there is.  Here is how RFC 3339 handles this:

"""
   Numeric offsets are calculated as "local time minus UTC".  So the
   equivalent time in UTC can be determined by subtracting the offset
   from the local time.
"""

and here is a quote from MacOS man page for tzset:

"""
           offset       Indicates the value one must add to the local
time to arrive at Coor-
                        dinated Universal Time.
"""

No geographic reference needed.  (And the issue is not UTC vs. GMT:
both UTC and GMT are timescales, sometimes even considered the same.
The off-topic issue is UTC vs. Prime Meridian.)
msg107157 - (view) Author: Alexander Belopolsky (belopolsky) * (Python committer) Date: 2010-06-05 18:09
On Sat, Jun 5, 2010 at 1:24 PM, anatoly techtonik
<report@bugs.python.org> wrote:
..
> So, to answer a question "What is the current UTC offset?" you need to:
> if time.daylight:
>  if time.altzone: # using only if defined
>     use time.altzone
>  else:
>     use time.timezone
> else:
>  use time.timezone
>

No, if time.daylight is non-zero, you still need to check the current
value of tm_isdst from localtime().

Here is how bzr reportedly handles this:

def local_time_offset(t=None):
    """Return offset of local zone from GMT, either at present or at time t."""
    # python2.3 localtime() can't take None
    if t is None:
        t = time.time()

    if time.localtime(t).tm_isdst and time.daylight:
        return -time.altzone
    else:
        return -time.timezone

http://blogs.gnome.org/jamesh/2006/12/31/python-timetimezone-timealtzone-edge-case/

> 1. Is that really works like described above?

That works for current time, but subject to race condition twice a
year.  You should get time and dst indormation from the same
localtime() call.  For problems with  arbitrary time t, see the link
above.

> 2. Should we at least group these timezone variables?
>

The come from existing C library practice.  POSIX defines tzname[2],
timezone, and daylight.

http://www.opengroup.org/onlinepubs/009695399/basedefs/time.h.html

altzone is a popular non-standard addition which is strictly
redundant.  Since POSIX does not define anything about daylight
variable other than it has to be zero when DST is not in effect,
compliant implementations can define is so that altzone = timezone -
daylight.

These variables are already grouped in tzinfo API.  What is missing is
method to get concrete tzinfo implementation in stdlib.  See
issue5094.
msg110709 - (view) Author: Alexander Belopolsky (belopolsky) * (Python committer) Date: 2010-07-19 02:30
Georg,

Do you mind if I take this over?

While I have issues with east/west of UTC terminology, it is the accepted terminology throughout the manual and Brian's rewording is an improvement.
msg110714 - (view) Author: Georg Brandl (georg.brandl) * (Python committer) Date: 2010-07-19 06:40
Please do!
msg110777 - (view) Author: Alexander Belopolsky (belopolsky) * (Python committer) Date: 2010-07-19 16:42
After reading the new wording on a formatted page, I don't like the proposed changes:

"""
time.altzone

When daylight is nonzero, altzone specifies the offset of the local DST timezone, in seconds west of UTC. This is negative if the local DST timezone is east of UTC ...
"""

In the second sentence, it is not clear whether "this" refers to altzone or daylight.

"""
time.daylight

Whether or not DST is in effect, daylight specifies the DST offset. 
"""

This is simply wrong.  time.daylight does not necessarily specify the DST offset (and I think it does not on most systems.)  POSIX requires that "The tzset() function also shall set the external variable daylight to 0 if Daylight Savings Time conversions should never be applied for the timezone in use; otherwise, non-zero." [1]  This means that a compliant system may store just 0 or 1 in daylight rather than the DST offset.

For example, on my OSX system:

$ TZ=America/New_York python -c "import time; print(time.daylight)"
1
$ TZ=UTC python -c "import time; print(time.daylight)"
0
$ TZ=EDT python -c "import time; print(time.daylight)"
0

I will think some more on how to improve the current documentation, but at least with respect to time.daylight, current language is better than the proposed change.




[1] http://www.opengroup.org/onlinepubs/009695399/functions/tzset.html
msg125981 - (view) Author: Alexander Belopolsky (belopolsky) * (Python committer) Date: 2011-01-11 02:18
I am going to reject this.  None of the proposed changes seem to be better than the current documentation. The time.daylight variable has the same meaning as eponymous C variable defined in time.h header.  The latter is described in widely available and well known C and POSIX standards. Users that find Python manual description confusing or incomplete can easily find clarifications or details in other sources.
msg125986 - (view) Author: Tomas Kubes (napik) Date: 2011-01-11 08:37
I am sorry, but as an original initiator of the the issue I find the argumentation of Alexander Belopolsky vastly ridiculous. Are you really seriously convinced that an average person responsible for Python application development and maintenance would be aware of a necessity to look for an ANSI C documentation to find a description and definitions of time functions?

You sound like Marie Antoinette who replied to peasants complaining the they do not have any bread to eat that they should eat brioches instead. Maybe in the context of the “royal programmers family” documentation to ANSI C is wildly known and even memorized, but I do insist that Python documentation should be accessible and understandable even to ordinary peasants of the computer kingdom.

And I keep my case that the current description might trick programmers to think that it holds information whether the summer time currently applies rather than just plain information about current time zone being able to use summer time.

Regards
Tomas
msg125989 - (view) Author: anatoly techtonik (techtonik) Date: 2011-01-11 09:55
Classic user developer impedance mismatch. =)

I agree that Python should guard its users against crazy standards that creep into standard lib, because nobody had time to think about pythonic API.

I propose the following change:

http://docs.python.org/library/time.html#time.altzone
-  UTC offset of the local DST timezone if one is defined. Only use this if daylight is nonzero.
+  UTC offset of the current timezone with Daylight Savings Time (DST) correction. To check if DST is currently active, use `time.localtime(t).tm_isdst`

http://docs.python.org/library/time.html#time.daylight
-  Nonzero if a DST timezone is defined.
+  Flag indicating that current timezone has Daylight Savings Time (DST) offset. To check if DST is currently active, use `time.localtime(t).tm_isdst`

http://docs.python.org/library/time.html#time.timezone
-  UTC offset of the local (non-DST) timezone
+  UTC offset of the current timezone. It doesn't include Daylight Savings Time (DST) correction. See `time.altzone` for that.


BTW, isn't the following check redundant?
    if time.localtime(t).tm_isdst and time.daylight:
msg125997 - (view) Author: Tomas Kubes (napik) Date: 2011-01-11 11:26
Hello,

I find this version very clear.

Thanks
Tomas
msg126010 - (view) Author: Alexander Belopolsky (belopolsky) * (Python committer) Date: 2011-01-11 14:52
On Tue, Jan 11, 2011 at 4:55 AM, anatoly techtonik
<report@bugs.python.org> wrote:
..
> I propose the following change:
..
> http://docs.python.org/library/time.html#time.daylight
> -  Nonzero if a DST timezone is defined.
> + .. To check if DST is currently active, use `time.localtime(t).tm_isdst`

This is simply wrong. Your time.localtime(t).tm_isdst expression will
return the DST flag for the POSIX time value t, not for the current
time.  This could be fixed by replacing your proposed expression with
time.localtime().tm_isdst, but why do you think someone  reading about
time.daylight actually wants to "check if DST is currently active"?

What can be improved, though, is the documentation of time.tzset().
The current version fails to mention that  time.tzset() resets the
values of tzname, timezone, altzone and daylight.  This would be the
proper place to document the meaning of all three variables in greater
detail.  Individual entries can then refer to it with say "See
time.tzset() for details."

Here is how POSIX tzset() is defined:

"""
The tzset() function sets the external variable tzname as follows:

tzname[0] = "std";
tzname[1] = "dst";

where std and dst are as described in the XBD specification,
Environment Variables .

The tzset() function also sets the external variable daylight to 0 if
Daylight Savings Time conversions should never be applied for the time
zone in use; otherwise non-zero. The external variable timezone is set
to the difference, in seconds, between Coordinated Universal Time
(UTC) and local standard time.
"""  http://pubs.opengroup.org/onlinepubs/007908799/xsh/tzset.html
msg126019 - (view) Author: Tomas Kubes (napik) Date: 2011-01-11 16:20
>>why do you think someone  reading about
time.daylight actually wants to "check if DST is currently active"?

If you are not familiar with the cryptic names of POSIX but live in normal world, time.daylight sounds like a quite probable place where to check if the daylight savings are active. That's why I think the help text should explicitely note it has other meaning.

You should try to think like a person that does not have any background knowledge of underlying libraries but just looks through the time library trying to solve the question - how can I check if my machine uses daylight savings now.

Regards
Tomas
msg126021 - (view) Author: Alexander Belopolsky (belopolsky) * (Python committer) Date: 2011-01-11 16:39
On Tue, Jan 11, 2011 at 11:20 AM, Tomas Kubes <report@bugs.python.org> wrote:
..
> You should try to think like a person that does not have any background knowledge of underlying libraries but
> just looks through the time library trying to solve the question - how can I check if my machine uses daylight
> savings now.

I think you are confusing the purposes of a reference manual with that
of a tutorial or an FAQ collection.

I will keep this issue open, however, in case someone will come up
with a patch that does not introduce factual mistakes.   As I
suggested, the place to present details about tzname, timezone,
altzone and daylight variables is the section on time.tzset().  It is
currently devoted to a rather useless discussion of the TZ environment
variable syntax.  Instead, it should describe these variables and list
the functions whose behavior depends on the value of TZ
(time.localtime(), time.ctime(), time.mktime() and time.strftime()).
msg126022 - (view) Author: Tomas Kubes (napik) Date: 2011-01-11 16:57
> I think you are confusing the purposes of a reference manual with that
of a tutorial or an FAQ collection.

There is a fine line between them. Even though reference manual should not be a substitute for a tutorial, I still believe it should try to clarify potential confusions - after all it is the less experienced users who will most likely spend their time with it looking for something.
msg126032 - (view) Author: Georg Brandl (georg.brandl) * (Python committer) Date: 2011-01-11 18:56
It seems to me that the quoted function from bzr

def local_time_offset(t=None):
    """Return offset of local zone from GMT, either at present or at time t."""
    # python2.3 localtime() can't take None
    if t is None:
        t = time.time()

    if time.localtime(t).tm_isdst and time.daylight:
        return -time.altzone
    else:
        return -time.timezone

would be very helpful to add to the `time` module docs as an example.  I have to agree with the OP that the current state of the docs is not as clear as it could be.
msg126033 - (view) Author: Alexander Belopolsky (belopolsky) * (Python committer) Date: 2011-01-11 19:42
On Tue, Jan 11, 2011 at 1:56 PM, Georg Brandl <report@bugs.python.org> wrote:
..
> It seems to me that the quoted function from bzr ...
> would be very helpful to add to the `time` module docs as an example.

The problem with this function is the same as with the doc patches
that have been proposed so far.  It is subtly wrong.  See issue
#1647654.  Specifically, see the link to a bug in Hg mentioned in
msg122166.

> I have to agree with the OP that the current state of the docs is not as clear as it could be.

In some ways the state of the docs is reflective of the state of the
code.  C/POSIX API on which time module design is based is not very
well suited to the age of smart phones and distributed VC systems.
The whole idea that there is a static "system timezone" is absurd when
a "system" is in your pocket or in the cloud.

I agree that the docs can be improved, but I don't see patches that
would constitute an improvement.  I've explained what I would see as
an improvement in my prior comments.
msg126036 - (view) Author: anatoly techtonik (techtonik) Date: 2011-01-11 21:14
On Tue, Jan 11, 2011 at 4:52 PM, Alexander Belopolsky
<report@bugs.python.org> wrote:
> ..
>> http://docs.python.org/library/time.html#time.daylight
>> -  Nonzero if a DST timezone is defined.
>> + .. To check if DST is currently active, use `time.localtime(t).tm_isdst`
>
> This is simply wrong. Your time.localtime(t).tm_isdst expression will
> return the DST flag for the POSIX time value t, not for the current
> time.  This could be fixed by replacing your proposed expression with
> time.localtime().tm_isdst, but why do you think someone  reading about
> time.daylight actually wants to "check if DST is currently active"?

Sorry, I've just copy/pasted this snippet and haven't noticed t argument.

As for your question, I think that someone reading about time.daylight
is reading about it to know how it can be used, and if you're quoting,
please quote without removing words inside the quote, or else I won't
be able to give you the answers that will be appropriate in your
context.

> What can be improved, though, is the documentation of time.tzset().
> The current version fails to mention that  time.tzset() resets the
> values of tzname, timezone, altzone and daylight.  This would be the
> proper place to document the meaning of all three variables in greater
> detail.  Individual entries can then refer to it with say "See
> time.tzset() for details."

How about making it in iterations and keep the steps as small as
possible, i.e. split the big problem into munchable chunks? First we
can accept the version of doc from my previous comment and then open a
new RFE for further work. Considering how much time this issue took
already, I see this approach as the only viable one.

> Here is how POSIX tzset() is defined:
> ...

I am sorry Alexander, but I can't really follow up on this issue. It
is interesting, but unfortunately right now I can only dedicate my
time to things that take don't more than 15 minutes of my attention,
and there are about 50 out of 700 of these in my inbox right now. We
need to split these datetime problems into smaller ones somehow. They
are really too complex for users.

To summarize: What is wrong with my previous proposal if we remove t
from params?

P.S. Looks like we need a PEP for this. =)
msg126037 - (view) Author: anatoly techtonik (techtonik) Date: 2011-01-11 21:22
On Tue, Jan 11, 2011 at 9:42 PM, Alexander Belopolsky
<report@bugs.python.org> wrote:
>
>> I have to agree with the OP that the current state of the docs is not as clear as it could be.
>
> In some ways the state of the docs is reflective of the state of the
> code.  C/POSIX API on which time module design is based is not very
> well suited to the age of smart phones and distributed VC systems.
> The whole idea that there is a static "system timezone" is absurd when
> a "system" is in your pocket or in the cloud.
>
> I agree that the docs can be improved, but I don't see patches that
> would constitute an improvement.  I've explained what I would see as
> an improvement in my prior comments.

Absurd need to be eliminated, but every time I touch datetime issues I
am confused by the complexity of additional information and
incompatibility of low-level C API with user needs. We need datetime
FAQ for a reference and a collection of user stories to see what it
possible (with examples/recipes) and what is impossible (with
proposals/PEP) in current state. If I was in charge - I'd mark all
datetime issues as release blockers for Py3k, so that all who wanted
Py3k released ASAP dedicate their time to this problem.
msg126038 - (view) Author: Alexander Belopolsky (belopolsky) * (Python committer) Date: 2011-01-11 21:27
On Tue, Jan 11, 2011 at 4:15 PM, anatoly techtonik
<report@bugs.python.org> wrote:
..
> To summarize: What is wrong with my previous proposal if we remove t
> from params?

Not much is wrong with it.   If it would come in a form of a patch and
without typos or mark-up mistakes, I or another committer would
probably apply it as an incremental improvement.   However, given that
additional effort is needed to apply your suggestion, I would rather
wait until a better solution is available.  Specifically, I don like
the duplication of time.localtime().tm_isdst recipe in daylight and
altzone.  Also, these variables should really be grouped together in
the docs.   I would like this to be done before a committer spends
time proofreading, fixing reST markup and committing the change.
History
Date User Action Args
2014-06-30 03:36:47berker.peksagsetstage: patch review -> resolved
2014-06-29 22:54:33belopolskysetstatus: open -> closed
resolution: rejected
2011-07-09 07:34:48kralphsetnosy: + kralph
2011-01-11 21:27:23belopolskysetnosy: georg.brandl, belopolsky, techtonik, napik, docs@python
messages: + msg126038
2011-01-11 21:22:22techtoniksetnosy: georg.brandl, belopolsky, techtonik, napik, docs@python
messages: + msg126037
2011-01-11 21:14:17techtoniksetnosy: georg.brandl, belopolsky, techtonik, napik, docs@python
messages: + msg126036
2011-01-11 19:42:06belopolskysetnosy: georg.brandl, belopolsky, techtonik, napik, docs@python
messages: + msg126033
2011-01-11 18:56:52georg.brandlsetnosy: georg.brandl, belopolsky, techtonik, napik, docs@python
messages: + msg126032
2011-01-11 16:57:06napiksetnosy: georg.brandl, belopolsky, techtonik, napik, docs@python
messages: + msg126022
2011-01-11 16:39:48belopolskysetnosy: georg.brandl, belopolsky, techtonik, napik, docs@python
messages: + msg126021
2011-01-11 16:22:28brian.curtinsetnosy: - brian.curtin
2011-01-11 16:20:05napiksetnosy: georg.brandl, belopolsky, techtonik, brian.curtin, napik, docs@python
messages: + msg126019
2011-01-11 14:52:53belopolskysetnosy: georg.brandl, belopolsky, techtonik, brian.curtin, napik, docs@python
messages: + msg126010
2011-01-11 11:26:08napiksetnosy: georg.brandl, belopolsky, techtonik, brian.curtin, napik, docs@python
messages: + msg125997
2011-01-11 09:55:44techtoniksetnosy: georg.brandl, belopolsky, techtonik, brian.curtin, napik, docs@python
messages: + msg125989
2011-01-11 08:37:22napiksetstatus: pending -> open
nosy: georg.brandl, belopolsky, techtonik, brian.curtin, napik, docs@python
messages: + msg125986
2011-01-11 02:18:25belopolskysetstatus: open -> pending
nosy: georg.brandl, belopolsky, techtonik, brian.curtin, napik, docs@python
messages: + msg125981
2010-07-19 16:42:17belopolskysetsuperseder: Don't use east/west of UTC in date/time documentation
messages: + msg110777
2010-07-19 16:42:05belopolskylinkissue9305 dependencies
2010-07-19 06:40:22georg.brandlsetassignee: georg.brandl -> belopolsky
messages: + msg110714
2010-07-19 02:30:35belopolskysetmessages: + msg110709
2010-06-05 18:09:45belopolskysetmessages: + msg107157
2010-06-05 17:43:58belopolskysetmessages: + msg107155
2010-06-05 17:24:00techtoniksetmessages: + msg107153
2010-06-05 16:32:18belopolskysetmessages: + msg107148
2010-06-05 15:52:27r.david.murraysettitle: [PATCH] Manual entry for time.daylight can be misleading -> Manual entry for time.daylight can be misleading
2010-06-05 15:48:29techtoniksetnosy: + belopolsky, docs@python
messages: + msg107142
2010-02-09 16:28:36brian.curtinsetfiles: + time_reword.diff
priority: normal
versions: - Python 2.5, Python 2.4, Python 3.0
messages: + msg99122

keywords: + needs review
stage: patch review
2010-02-09 11:02:06techtoniksetnosy: + brian.curtin
messages: + msg99103
2010-02-09 09:32:39techtoniksetfiles: + issue7229_daylight_doc_misleading.diff

type: enhancement -> behavior
title: Manual entry for time.daylight can be misleading -> [PATCH] Manual entry for time.daylight can be misleading
keywords: + patch
nosy: + techtonik

messages: + msg99099
2009-10-28 09:44:10napikcreate