FAQ
hello,

I want to handle datetime vars in a general way, so I use the default
time-format,
so I can use the standard cinversion procedures.
Time format is the time difference since 1-1-1970.

So how do I handle dates before 1-1-1970 ?

I'ld expect times before 1-1-1970, simply to become negative numbers
(I'm interested in the age of living people, so that would suffice).

Is there a general solution, (other library)
or would it be better to handle all dates in the Delphi format (number
of days since 1-1-1900

thanks,
Stef Mientki


From http Tue Oct 6 02:27:19 2009
From: http (Paul Rubin)
Date: 05 Oct 2009 17:27:19 -0700
Subject: Q: sort's key and cmp parameters
References: <ha2nmh$2l3$2@reader1.panix.com>
<7x1vln2bzh.fsf@ruckus.brouhaha.com>
<85f89926-6a1c-40ec-8f29-3acb2f4bd00f@2g2000prl.googlegroups.com>
<7x4oqh5d79.fsf@ruckus.brouhaha.com>
<9494594b-1001-4f8b-97b6-9390a902172a@f18g2000prf.googlegroups.com>
<7xhbuht00d.fsf@ruckus.brouhaha.com>
<7x8wft7x7f.fsf@ruckus.brouhaha.com>
<e74a9213-06ac-4d27-b06d-23327e3e3fb7@j9g2000prh.googlegroups.com>
<7x8wfqup6u.fsf@ruckus.brouhaha.com>
<9d050660-2ab8-4161-992c-85c2376469b0@f20g2000prn.googlegroups.com>
Message-ID: <7x4oqdcqoo.fsf@ruckus.brouhaha.com>

Raymond Hettinger <python at rcn.com> writes:
FWIW, you could also just flatten it to: [(1,3,7,5), (19,23)].

The point is that the tree comparisons you presented have a
predetermined order of values to compare, so they either be recast a
flattened list of comparison values or the tree itself can be cast
in a list of lists form. Either way, the O(n log n) step of doing
the actual comparisons runs much faster than if you coded a
recursive cmp function written in pure python.
Possibly so, but asymptotically it's the same, and anyway
Say you want to change the numeric comparisons so that
even numbers always sort before odd numbers, ie.
-4 < -2 < 0 < 2 < 4 < ... < -999 < ... -1 < 1 < 3 ...
This is too easy:
s = [-2, 4, 2, -1, -3, 1, -4, 0, 3]
s.sort()
s.sort(key=lambda x: x%2)
s
[-4, -2, 0, 2, 4, -3, -1, 1, 3]
I don't think so:
s = [0, 2, -2, 3, 1, -1, 4, -4, -3]
s.sort(key=lambda x:x%2)
s
[0, 2, -2, 4, -4, 3, 1, -1, -3]

s.sort(key=lambda x:(x%2,x)) might work but why are you so opposed
to being able to write one's natural thought pattern if that pattern
happens to be a comparison function? Who wants to concoct these
ad-hoc encodings for every ordering?
As long as the values of a tree get compared in a predetermined order,
there will always be a flattened list equivalent that works faster
using a key function. If you're going to concoct something isn't
easily transformable to a key function, I think your best bet is to
create a comparison where the trees have an interaction other than
comparing values at identical node positions;
How about this: gen_e, gen_pi, gen_sqrt2, etc. all generate
representations of various real numbers as possibly infinite sequences
of digits:

def gen_pi():
yield 3
yield 1
yield 4
# ... compute infinite stream one digit at a time

Comparison is obvious if (hmmm....) you can guarantee that you're
sorting unique elements and that the sort function won't compare an
element with itself (otherwise I guess you could cut off comparison at
a million digits or whatever):

def cmp(gen1, gen2):
for d,e in izip(gen1(), gen2()):
c = cmp(d,e)
if c: return c

I don't see any clean way to handle that with key=, though of course
maybe I'm missing something.
P.S. I accept than you hate sorting in Py3.x. There's no need to
convince me of that. I was just curious about your one real-world
use case and whether I could find a straight-forward key function
that would get the job done.
I don't hate sorting in py3.x. I understand the concept that py3.x
introduces incompatibilities to make things better. What I don't like
is the approach of breaking stuff gratutiously with no benefit. If
the positional arg for cmp is a kludge, why not switch it to a keyword
arg instead of eliminating it?

I don't subscribe to the cult of the real-world use case. I'm not
smart enough to anticipate every way anyone might ever want to use
code that I write. So I try to identify the obvious "basis vectors"
of sensible functionality, implement those, and make sure that the
entire space of combinations works the way it should, without worrying
about whether anyone will care about any specific combination. There
is no real-world use case for the constant assignment

a = 0x36b20b32c927eaf68bb40d87d251049db98da0c03a0e8c791f04ee486ec2f7ee

which I'm sure nobody has ever seen before (I just made it from
os.urandom). But if Python somehow failed to parse that number (and
only that number), that would be considered an unacceptable bug,
because a straightforward combination of primitives had failed to work
as it should.

Any book on sorting spends most of its time on comparison sorting,
which is the primitive operation. key= is very useful but it is
a derived operation, not the other way around.

Search Discussions

  • Stephen Hansen at Oct 6, 2009 at 12:25 am

    On Mon, Oct 5, 2009 at 4:54 PM, Stef Mientki wrote:

    hello,

    I want to handle datetime vars in a general way, so I use the default
    time-format,
    so I can use the standard cinversion procedures.
    Personally, I love mx.DateTime; its the best date/time library around. But,
    Python's built in datetime isn't too bad and is similar and built-in if you
    don't want to use a third-party library.

    But:
    birthday = mx.DateTime.Date(1960,3,3)
    birthday
    <mx.DateTime.DateTime object for '1960-03-03 00:00:00.00' at 6211e0>
    age = mx.DateTime.now() - birthday
    print "Age in days", age.days
    18113.722499758693
    print "Age in years", age.days / 365
    49.626636985640253

    I really can't quite fathom why you'd want to use something so low-level as
    time.mktime... or just about anything in the time module :) If you want to
    handle dates in a general way, I'd use one of the general-purpose date/time
    handling libraries. They're far more capable and easier to use.

    HTH,

    --S
    -------------- next part --------------
    An HTML attachment was scrubbed...
    URL: <http://mail.python.org/pipermail/python-list/attachments/20091005/84652125/attachment.htm>
  • Stef Mientki at Oct 6, 2009 at 8:10 pm

    Stephen Hansen wrote:
    On Mon, Oct 5, 2009 at 4:54 PM, Stef Mientki <stef.mientki at gmail.com
    wrote:

    hello,

    I want to handle datetime vars in a general way, so I use the
    default time-format,
    so I can use the standard cinversion procedures.


    Personally, I love mx.DateTime; its the best date/time library around.
    But, Python's built in datetime isn't too bad and is similar and
    built-in if you don't want to use a third-party library.
    thanks guys,
    mx works a bit better ....
    But:
    birthday = mx.DateTime.Date(1960,3,3)
    birthday
    <mx.DateTime.DateTime object for '1960-03-03 00:00:00.00' at 6211e0>
    age = mx.DateTime.now() - birthday
    print "Age in days", age.days
    18113.722499758693
    print "Age in years", age.days / 365
    49.626636985640253

    I really can't quite fathom why you'd want to use something so
    low-level as time.mktime... or just about anything in the time module :)
    I didn't know anything better,
    but (forgive me if I'm wrong) I find mx almost as low-level :
    mx.DateTime.strptime('01-01-53',"%d-%m-%y")
    <mx.DateTime.DateTime object for '2053-01-01 00:00:00.00' at 1cddc60>
    while all we human know ..

    I agree it's better not to work with string dates, but that's the way
    how we human write things down ;-)
    So I must use at least something like strptime.

    cheers,
    Stef
    If you want to handle dates in a general way, I'd use one of the
    general-purpose date/time handling libraries. They're far more capable
    and easier to use.

    HTH,

    --S
  • Stephen Hansen at Oct 6, 2009 at 9:13 pm

    I really can't quite fathom why you'd want to use something so low-level as
    time.mktime... or just about anything in the time module :)
    I didn't know anything better,
    but (forgive me if I'm wrong) I find mx almost as low-level :
    mx.DateTime.strptime('01-01-53',"%d-%m-%y")
    <mx.DateTime.DateTime object for '2053-01-01 00:00:00.00' at 1cddc60>
    while all we human know ..

    I agree it's better not to work with string dates, but that's the way how
    we human write things down ;-)
    So I must use at least something like strptime.
    mx.DateTime provides all the low-level tools if you must use them of course,
    but it has high level tools too.
    mx.DateTime.Parser.DateFromString("01-01-1953")
    <mx.DateTime.DateTime object for '1953-01-01 00:00:00.00' at 6211e0>

    Now if you're storing your years as 2-digits, yeah, it'll run into trouble
    and you'll have to deal with issues related to that manually. It can't know
    by default if you mean 01-01-53 as someone's birthdate in 1953, or some
    future event in 2053.

    It also parses the common "standardized" date representations (and faster if
    its a known format, as mx.DateTime.Parser has to guess at the format until
    it finds one that matches/works)-- ISO 8601 and the ARPA formats, for
    example. The mx.DateTime.ISO and mx.DateTime.ARPA modules are for that.

    Personally, while /users/ may write a date in a lazy way like "01-01-53",
    I'd never store that and would avoid having them enter them directly. At the
    UI level I'd validate and normalize it to a standard format before storing
    it.

    E.g. instead of users entering someone's birthday into a control, I'd use a
    calendar control, and store it with (in wx terms) date.FormatISODate(). Or
    use date.toString(ISODate) in QT terms (ish).

    I might not display it in ISO format, but.. storing it in a standard format
    makes processing easier. Faster to import into mx.DateTime, and then I just
    display it as dt.Format("%x") so they see a date like they expect.

    HTH,

    --S
    -------------- next part --------------
    An HTML attachment was scrubbed...
    URL: <http://mail.python.org/pipermail/python-list/attachments/20091006/3a984246/attachment.htm>
  • Stef Mientki at Oct 8, 2009 at 8:05 pm

    Stephen Hansen wrote:
    <snip>
    Personally, while /users/ may write a date in a lazy way like
    "01-01-53", I'd never store that and would avoid having them enter
    them directly. At the UI level I'd validate and normalize it to a
    standard format before storing it.
    yes I agree, but the data is coming from all kind of programs,
    some more than 10 years old.
    E.g. instead of users entering someone's birthday into a control, I'd
    use a calendar control, and store it with (in wx terms)
    date.FormatISODate(). Or use date.toString(ISODate) in QT terms (ish).
    I don't know your age,
    but with my age it takes hours to look up my birthday on a windows
    calender control ;-)

    cheers,
    Stef
  • John Yeung at Oct 8, 2009 at 9:36 pm

    On Oct 6, 4:10?pm, Stef Mientki wrote:
    thanks guys,
    mx works a bit better ?....
    Another popular Python date library is dateutil:

    http://labix.org/python-dateutil

    It gives a certain amount of credit to mxDateTime (praising it but not
    being very clear how they are related; there is some mention of "using
    the specification" of mxDateTime).

    I would say mxDateTime and dateutil are the two heavyweights in this
    arena. As you would expect, they have a lot of overlapping
    functionality and which one is used is often just a matter of taste,
    or whichever one you happened to find first.

    One thing that dateutil provides that mxDateTime doesn't is support
    for "lay person" month operations. That is, as far as I can tell,
    mxDateTime tries not to dirty itself with the messy business of month
    arithmetic, whereas dateutil rolls up its sleeves and takes an honest
    stab at it. If you are writing a calendar/appointment application, or
    other end-user-facing program, I would expect dateutil to be a little
    more helpful.

    John
  • M.-A. Lemburg at Oct 9, 2009 at 10:10 am

    John Yeung wrote:
    On Oct 6, 4:10 pm, Stef Mientki wrote:

    thanks guys,
    mx works a bit better ....
    Another popular Python date library is dateutil:

    http://labix.org/python-dateutil

    It gives a certain amount of credit to mxDateTime (praising it but not
    being very clear how they are related; there is some mention of "using
    the specification" of mxDateTime).
    History goes a bit like this:

    mxDateTime was the first Python library to implement native
    date/time types for Python. I started the project in 1997.

    Back then I had a good look around at the various date/time
    libs and then decided to take a little more academic approach
    to the whole thing. The result was that you only need two basic
    types in mxDateTime: the DateTime object, which refers to a point
    in time, and the DateTimeDelta object, which allows measuring
    the time span between two such points. Note the absence of
    a Date object. These would be date/time range objects since they
    apply to the timespan of a full day with a time reference point
    at midnight. I decided to leave such ranges for a later stage
    in development - and have so far, never needed them :-)

    A bit later in 1998, I also added the RelativeDateTime object,
    which allows doing date/time calculations based on relative terms,
    e.g. x minus one year (which could mean 356 or 366 days
    depending on the year), first of next month (which could
    mean anything from 1-31 days), last of next month, Tuesday
    in 3 weeks, last Monday next month, etc.

    And again a bit later in 2000, I added the RelativeDateTimeDiff
    object which works a bit like an age function in that it tries to
    determine the RelativeDateTime value which has to be applied
    to a DateTime object in order to reach another one, say
    from your birthday to today. The result reads is more user-
    friendly than a bare DateTimeDelta, e.g. you get 40 years,
    6 months, 3 days instead of 14796 days.

    In 2002 Zope Corp initiated the development of the datetime
    module, which borrowed a lot of design and API ideas from
    mxDateTime.

    However, it did not provide a date/time string parser and also
    misses out on lots of the other good stuff you can find in
    mxDateTime.

    Gustavo Niemeyer started to work on a date/time parser based
    on the datetime module - that's the python-dateutil library.
    He also added a relative date/time object which was one of the
    bits Zope Corp left out in the datetime module from mxDateTime
    and added some other things that are not currently part of
    mxDateTime: recurring events and time zones.

    mxDateTime continues to be actively developed - mostly driven
    by eGenix' own needs and experience we find in projects. Whenever
    we need something new, we can just add it to mxDateTime and since
    its release cycle is not bound to Python's, such enhancement
    are more readily available to others as well.

    Overall, my impression is that the datetime module was designed
    on the drawing board without actually touching real life
    usage scenarios.

    We've just done a project that used the datetime module for
    date/time related things instead of mxDateTime and
    found that while the implementation is similar to mxDateTime
    (naturally, see above), many useful features you find in mxDateTime
    are not available on the datetime objects.

    For future releases, we'll make the interaction between the
    two implementations more user friendly, e.g. it should be
    possible to pass a datetime object to mx.DateTime.DateTimeFrom()
    and call a method on DateTime objects to get a datetime
    module object with the same values.
    I would say mxDateTime and dateutil are the two heavyweights in this
    arena. As you would expect, they have a lot of overlapping
    functionality and which one is used is often just a matter of taste,
    or whichever one you happened to find first.

    One thing that dateutil provides that mxDateTime doesn't is support
    for "lay person" month operations. That is, as far as I can tell,
    mxDateTime tries not to dirty itself with the messy business of month
    arithmetic, whereas dateutil rolls up its sleeves and takes an honest
    stab at it. If you are writing a calendar/appointment application, or
    other end-user-facing program, I would expect dateutil to be a little
    more helpful.
    Month arithmetic is a bit of a mess, since it's not clear how
    to map e.g. Jan 31 + one month.

    mxDateTime does support month arithmetic via the RelativeDateTime
    object, but I'm not all that happy with the solution to the above
    problem. The alternatives are basically deciding between loosing
    data or raising an exception - both aren't really all that nice.

    Perhaps I'll just add a parameter to allow customization of the
    behavior depending on application needs.

    --
    Marc-Andre Lemburg
    eGenix.com

    Professional Python Services directly from the Source (#1, Oct 09 2009)
    Python/Zope Consulting and Support ... http://www.egenix.com/
    mxODBC.Zope.Database.Adapter ... http://zope.egenix.com/
    mxODBC, mxDateTime, mxTextTools ... http://python.egenix.com/
    ________________________________________________________________________

    ::: Try our new mxODBC.Connect Python Database Interface for free ! ::::


    eGenix.com Software, Skills and Services GmbH Pastor-Loeh-Str.48
    D-40764 Langenfeld, Germany. CEO Dipl.-Math. Marc-Andre Lemburg
    Registered at Amtsgericht Duesseldorf: HRB 46611
    http://www.egenix.com/company/contact/
  • Tim Chase at Oct 9, 2009 at 12:39 pm

    Month arithmetic is a bit of a mess, since it's not clear how
    to map e.g. Jan 31 + one month.
    "Jan 31 + one month" usually means "add one to the month value
    and then keep backing off the day if you get an exception making
    the date", so you'd get Feb 31, exception, Feb 30, exception, Feb
    29, possibly an exception, and possibly/finally Feb 28th. This
    makes pretty intuitive sense to most folks and is usually what's
    meant.

    I've found that issues and confusion stem more from the
    non-commutative reality that "Jan 31 + (1 month) + (-1 month) !=
    Jan 31 + (-1 month) + (1 month)" or the non-associative "Jan 31 +
    (1 month + 1 month) != (Jan 31 + 1 month) + 1 month" :-/

    So yes, messy it is!

    -tkc
  • Rhodri James at Oct 11, 2009 at 12:33 pm

    On Fri, 09 Oct 2009 13:39:43 +0100, Tim Chase wrote:
    Month arithmetic is a bit of a mess, since it's not clear how
    to map e.g. Jan 31 + one month.
    "Jan 31 + one month" usually means "add one to the month value and then
    keep backing off the day if you get an exception making the date", so
    you'd get Feb 31, exception, Feb 30, exception, Feb 29, possibly an
    exception, and possibly/finally Feb 28th. This makes pretty intuitive
    sense to most folks and is usually what's meant.

    I've found that issues and confusion stem more from the non-commutative
    reality that "Jan 31 + (1 month) + (-1 month) != Jan 31 + (-1 month) +
    (1 month)" or the non-associative "Jan 31 + (1 month + 1 month) != (Jan
    31 + 1 month) + 1 month" :-/
    I'd hazard a guess that what we're actually seeing is people mentally
    rebasing their indices, i.e. counting from the end of the month rather
    than the start, which makes "the last day of January" and "January 31"
    not the same thing really. Unfortunately we're very fuzzy about when
    we do things like this, which makes it hard on a poor programmer.

    --
    Rhodri James *-* Wildebeest Herder to the Masses
  • MRAB at Oct 11, 2009 at 3:55 pm

    Rhodri James wrote:
    On Fri, 09 Oct 2009 13:39:43 +0100, Tim Chase
    wrote:
    Month arithmetic is a bit of a mess, since it's not clear how
    to map e.g. Jan 31 + one month.
    "Jan 31 + one month" usually means "add one to the month value and
    then keep backing off the day if you get an exception making the
    date", so you'd get Feb 31, exception, Feb 30, exception, Feb 29,
    possibly an exception, and possibly/finally Feb 28th. This makes
    pretty intuitive sense to most folks and is usually what's meant.

    I've found that issues and confusion stem more from the
    non-commutative reality that "Jan 31 + (1 month) + (-1 month) != Jan
    31 + (-1 month) + (1 month)" or the non-associative "Jan 31 + (1 month
    + 1 month) != (Jan 31 + 1 month) + 1 month" :-/
    I'd hazard a guess that what we're actually seeing is people mentally
    rebasing their indices, i.e. counting from the end of the month rather
    than the start, which makes "the last day of January" and "January 31"
    not the same thing really. Unfortunately we're very fuzzy about when
    we do things like this, which makes it hard on a poor programmer.
    And when someone says "January 30", do they really mean the day before
    the last day of the month? Where would it end? :-)
  • Greg at Oct 12, 2009 at 9:10 am

    MRAB wrote:

    And when someone says "January 30", do they really mean the day before
    the last day of the month?
    No, no, that's January -2, a *completely* different thing!

    --
    Greg
  • Piet van Oostrum at Oct 12, 2009 at 11:27 am

    greg (g) wrote:
    g> MRAB wrote:
    And when someone says "January 30", do they really mean the day before
    the last day of the month?
    g> No, no, that's January -2, a *completely* different thing!
    But for someone else it would be February -2.
    --
    Piet van Oostrum <piet at vanoostrum.org>
    WWW: http://pietvanoostrum.com/
    PGP key: [8DAE142BE17999C4]
  • Chris Rebert at Oct 12, 2009 at 11:59 am

    On Mon, Oct 12, 2009 at 4:27 AM, Piet van Oostrum wrote:
    greg (g) wrote:
    g> MRAB wrote:
    And when someone says "January 30", do they really mean the day before
    the last day of the month?
    g> No, no, that's January -2, a *completely* different thing!
    But for someone else it would be February -2.
    And for still others, it's the last $DAYOFWEEK of the month, which
    just happened to fall on the 30th.

    Cheers,
    Chris
  • M.-A. Lemburg at Oct 12, 2009 at 6:34 pm

    Chris Rebert wrote:
    On Mon, Oct 12, 2009 at 4:27 AM, Piet van Oostrum wrote:
    greg (g) wrote:
    g> MRAB wrote:
    And when someone says "January 30", do they really mean the day before
    the last day of the month?
    g> No, no, that's January -2, a *completely* different thing!
    But for someone else it would be February -2.
    And for still others, it's the last $DAYOFWEEK of the month, which
    just happened to fall on the 30th.
    That's a little more complicated:
    mx.DateTime.DateTime(2009, 1, 31).day_of_week
    5
    # which is a ...
    mx.DateTime.Weekday[mx.DateTime.DateTime(2009, 1, 31).day_of_week]
    'Saturday'

    Now:
    # "next month, last Saturday"
    mx.DateTime.DateTime(2009, 1, 31) + mx.DateTime.RelativeDateTime(months=+1, day=1, weekday=(5, -1))
    <mx.DateTime.DateTime object for '2009-02-28 00:00:00.00' at 2ba43f93ebe0>

    --
    Marc-Andre Lemburg
    eGenix.com

    Professional Python Services directly from the Source (#1, Oct 12 2009)
    Python/Zope Consulting and Support ... http://www.egenix.com/
    mxODBC.Zope.Database.Adapter ... http://zope.egenix.com/
    mxODBC, mxDateTime, mxTextTools ... http://python.egenix.com/
    ________________________________________________________________________

    ::: Try our new mxODBC.Connect Python Database Interface for free ! ::::


    eGenix.com Software, Skills and Services GmbH Pastor-Loeh-Str.48
    D-40764 Langenfeld, Germany. CEO Dipl.-Math. Marc-Andre Lemburg
    Registered at Amtsgericht Duesseldorf: HRB 46611
    http://www.egenix.com/company/contact/
  • MRAB at Oct 12, 2009 at 1:56 pm

    Piet van Oostrum wrote:
    greg (g) wrote:
    g> MRAB wrote:
    And when someone says "January 30", do they really mean the day before
    the last day of the month?
    g> No, no, that's January -2, a *completely* different thing!
    But for someone else it would be February -2.
    When is February 0? :-)
  • M.-A. Lemburg at Oct 12, 2009 at 6:02 pm

    Rhodri James wrote:
    On Fri, 09 Oct 2009 13:39:43 +0100, Tim Chase
    wrote:
    Month arithmetic is a bit of a mess, since it's not clear how
    to map e.g. Jan 31 + one month.
    "Jan 31 + one month" usually means "add one to the month value and
    then keep backing off the day if you get an exception making the
    date", so you'd get Feb 31, exception, Feb 30, exception, Feb 29,
    possibly an exception, and possibly/finally Feb 28th. This makes
    pretty intuitive sense to most folks and is usually what's meant.

    I've found that issues and confusion stem more from the
    non-commutative reality that "Jan 31 + (1 month) + (-1 month) != Jan
    31 + (-1 month) + (1 month)" or the non-associative "Jan 31 + (1 month
    + 1 month) != (Jan 31 + 1 month) + 1 month" :-/
    I'd hazard a guess that what we're actually seeing is people mentally
    rebasing their indices, i.e. counting from the end of the month rather
    than the start, which makes "the last day of January" and "January 31"
    not the same thing really. Unfortunately we're very fuzzy about when
    we do things like this, which makes it hard on a poor programmer.
    Ah, for that we have RelativeDateTime:
    # "next month, last day of the month"
    mx.DateTime.DateTime(2009, 1, 31) + mx.DateTime.RelativeDateTime(months=+1, day=-1)
    <mx.DateTime.DateTime object for '2009-02-28 00:00:00.00' at 2ba43f95c088>

    --
    Marc-Andre Lemburg
    eGenix.com

    Professional Python Services directly from the Source (#1, Oct 12 2009)
    Python/Zope Consulting and Support ... http://www.egenix.com/
    mxODBC.Zope.Database.Adapter ... http://zope.egenix.com/
    mxODBC, mxDateTime, mxTextTools ... http://python.egenix.com/
    ________________________________________________________________________

    ::: Try our new mxODBC.Connect Python Database Interface for free ! ::::


    eGenix.com Software, Skills and Services GmbH Pastor-Loeh-Str.48
    D-40764 Langenfeld, Germany. CEO Dipl.-Math. Marc-Andre Lemburg
    Registered at Amtsgericht Duesseldorf: HRB 46611
    http://www.egenix.com/company/contact/
  • M.-A. Lemburg at Oct 12, 2009 at 6:00 pm

    Tim Chase wrote:
    Month arithmetic is a bit of a mess, since it's not clear how
    to map e.g. Jan 31 + one month.
    "Jan 31 + one month" usually means "add one to the month value and then
    keep backing off the day if you get an exception making the date", so
    you'd get Feb 31, exception, Feb 30, exception, Feb 29, possibly an
    exception, and possibly/finally Feb 28th. This makes pretty intuitive
    sense to most folks and is usually what's meant.
    Well, yes, but that's just one way to solve the problem. I guess
    I'll just add all possible solutions and then let the user decide
    what's best in some way.
    I've found that issues and confusion stem more from the non-commutative
    reality that "Jan 31 + (1 month) + (-1 month) != Jan 31 + (-1 month) +
    (1 month)" or the non-associative "Jan 31 + (1 month + 1 month) != (Jan
    31 + 1 month) + 1 month" :-/
    That's why mxDateTime actually returning a day in March...
    mx.DateTime.DateTime(2009, 1, 31) + mx.DateTime.RelativeDateTime(months=+1)
    <mx.DateTime.DateTime object for '2009-03-03 00:00:00.00' at 2ba43f93ebe0>

    That's intuitive for mathematicians only, though ;-)
    So yes, messy it is!
    Indeed.

    --
    Marc-Andre Lemburg
    eGenix.com

    Professional Python Services directly from the Source (#1, Oct 12 2009)
    Python/Zope Consulting and Support ... http://www.egenix.com/
    mxODBC.Zope.Database.Adapter ... http://zope.egenix.com/
    mxODBC, mxDateTime, mxTextTools ... http://python.egenix.com/
    ________________________________________________________________________

    ::: Try our new mxODBC.Connect Python Database Interface for free ! ::::


    eGenix.com Software, Skills and Services GmbH Pastor-Loeh-Str.48
    D-40764 Langenfeld, Germany. CEO Dipl.-Math. Marc-Andre Lemburg
    Registered at Amtsgericht Duesseldorf: HRB 46611
    http://www.egenix.com/company/contact/
  • Gabriel Genellina at Oct 6, 2009 at 12:35 am
    En Mon, 05 Oct 2009 20:54:18 -0300, Stef Mientki <stef.mientki at gmail.com>
    escribi?:
    I want to handle datetime vars in a general way, so I use the default
    time-format,
    so I can use the standard cinversion procedures.
    Time format is the time difference since 1-1-1970.

    So how do I handle dates before 1-1-1970 ?
    Use the datetime module and manage the dates as actual datetime objects,
    not as formatted strings.

    py> import datetime
    py> birthdate = datetime.datetime(1914, 7, 23)
    py> birthdate
    datetime.datetime(1914, 7, 23, 0, 0)
    py> now = datetime.datetime.now()
    py> now - birthdate
    datetime.timedelta(34773, 77146, 765000)
    py> _.days // 365
    95


    py> datetime.datetime(1931, 8, 23)
    datetime.datetime(1931, 8, 23, 0, 0)
    py> datetime.datetime(1851, 6, 12)
    datetime.datetime(1851, 6, 12, 0, 0)
    py> datetime.datetime(1492, 10, 12)
    datetime.datetime(1492, 10, 12, 0, 0)
    py> a = datetime.datetime(1492, 10, 12)
    py> b = datetime.datetime(2009, 10, 5)
    py> (b - a) // 365
    datetime.timedelta(517, 27932, 54794)
    py> b = datetime.datetime.now()
    py> _.days
    34773
    py> _.days // 365
    Traceback (most recent call last):
    File "<stdin>", line 1, in <module>
    AttributeError: 'int' object has no attribute 'days'
    py> now - birthdate
    datetime.timedelta(34773, 77146, 765000)
    I'ld expect times before 1-1-1970, simply to become negative numbers
    (I'm interested in the age of living people, so that would suffice).

    Is there a general solution, (other library)
    or would it be better to handle all dates in the Delphi format (number
    of days since 1-1-1900
    py> birthdate.toordinal()
    698912

    (number of days since 1 AD, approximately)

    --
    Gabriel Genellina
  • Ben Finney at Oct 6, 2009 at 1:06 am

    Stef Mientki <stef.mientki at gmail.com> writes:

    I'ld expect times before 1-1-1970, simply to become negative numbers
    (I'm interested in the age of living people, so that would suffice).

    Is there a general solution, (other library) or would it be better to
    handle all dates in the Delphi format (number of days since 1-1-1900
    There are many epochs that have been used in computing
    <URL:http://en.wikipedia.org/wiki/Epoch_(reference_date)#Notable_epoch_dates_in_computing>,
    all of which have their problems. Switching from the Unix epoch to some
    other involves data conversion, and (as you point out) raises concerns
    about library support.

    If you're committed to changing the epoch anyway, I would recommend
    using <URL:http://en.wikipedia.org/wiki/Astronomical_year_numbering>
    (epoch at 4004 BCE) since it is widely used to unify dates referring to
    human history.

    --
    \ ?The surest way to corrupt a youth is to instruct him to hold |
    `\ in higher esteem those who think alike than those who think |
    _o__) differently.? ?Friedrich Nietzsche |
    Ben Finney
  • Ben Finney at Oct 6, 2009 at 1:12 am

    Ben Finney <ben+python at benfinney.id.au> writes:

    There are many epochs that have been used in computing
    <URL:http://en.wikipedia.org/wiki/Epoch_(reference_date)#Notable_epoch_dates_in_computing>,
    all of which have their problems. Switching from the Unix epoch to some
    other involves data conversion, and (as you point out) raises concerns
    about library support.
    Hmm, none of this addressed your question about what *data type* to use.
    For that, the answer is: use the standard-library ?datetime? module's
    types (?date?, ?timestamp?, etc.) in your code for representing the
    actual values.

    The advice for date and time values is similar to the advice for text
    values: convert input to ?datetime? types as soon as possible, and
    render output as late as possible; do all processing on the ?datetime?
    types to ensure preservation of information.

    --
    \ ?I filled my humidifier with wax. Now my room is all shiny.? |
    `\ ?Steven Wright |
    _o__) |
    Ben Finney
  • Christian Heimes at Oct 6, 2009 at 9:11 pm

    Ben Finney wrote:
    If you're committed to changing the epoch anyway, I would recommend
    using <URL:http://en.wikipedia.org/wiki/Astronomical_year_numbering>
    (epoch at 4004 BCE) since it is widely used to unify dates referring to
    human history.
    I prefer JDN or MJD (http://en.wikipedia.org/wiki/JDN) for dates long
    before or after the unix epoch. The conversion from JDN as float to a
    datetime object is trivial.

    Christian
  • M.-A. Lemburg at Oct 7, 2009 at 12:13 pm

    Christian Heimes wrote:
    Ben Finney wrote:
    If you're committed to changing the epoch anyway, I would recommend
    using <URL:http://en.wikipedia.org/wiki/Astronomical_year_numbering>
    (epoch at 4004 BCE) since it is widely used to unify dates referring to
    human history.
    I prefer JDN or MJD (http://en.wikipedia.org/wiki/JDN) for dates long
    before or after the unix epoch. The conversion from JDN as float to a
    datetime object is trivial.
    FWIW, mxDateTime can help you with all of those:
    import mx.DateTime
    mx.DateTime.DateTimeFrom('1.1.4004 BCE')
    <mx.DateTime.DateTime object for '-4003-01-01 00:00:00.00' at 2b534a46a2f0>
    mx.DateTime.DateTimeFrom('1.1.4004 BCE').jdn
    258994.5
    mx.DateTime.DateTimeFromJDN(258994.5)
    <mx.DateTime.DateTime object for '-4003-01-01 00:00:00.00' at 2b534aeb72f0>
    mx.DateTime.DateTimeFrom('1.1.4004 BCE').mjd
    -2141006.0
    mx.DateTime.DateTimeFromMJD(-2141006.0)
    <mx.DateTime.DateTime object for '-4003-01-01 00:00:00.00' at 2b534a46a2f0>

    The supported date range is limited by the number of days
    that fit into a C long. Should be enough for most use cases :-)

    --
    Marc-Andre Lemburg
    eGenix.com

    Professional Python Services directly from the Source (#1, Oct 07 2009)
    Python/Zope Consulting and Support ... http://www.egenix.com/
    mxODBC.Zope.Database.Adapter ... http://zope.egenix.com/
    mxODBC, mxDateTime, mxTextTools ... http://python.egenix.com/
    ________________________________________________________________________

    ::: Try our new mxODBC.Connect Python Database Interface for free ! ::::


    eGenix.com Software, Skills and Services GmbH Pastor-Loeh-Str.48
    D-40764 Langenfeld, Germany. CEO Dipl.-Math. Marc-Andre Lemburg
    Registered at Amtsgericht Duesseldorf: HRB 46611
    http://www.egenix.com/company/contact/
  • Christian Heimes at Oct 7, 2009 at 1:02 pm

    M.-A. Lemburg schrieb:
    Christian Heimes wrote:
    Ben Finney wrote:
    If you're committed to changing the epoch anyway, I would recommend
    using <URL:http://en.wikipedia.org/wiki/Astronomical_year_numbering>
    (epoch at 4004 BCE) since it is widely used to unify dates referring to
    human history.
    I prefer JDN or MJD (http://en.wikipedia.org/wiki/JDN) for dates long
    before or after the unix epoch. The conversion from JDN as float to a
    datetime object is trivial.
    FWIW, mxDateTime can help you with all of those:
    import mx.DateTime
    mx.DateTime.DateTimeFrom('1.1.4004 BCE')
    <mx.DateTime.DateTime object for '-4003-01-01 00:00:00.00' at 2b534a46a2f0>
    mx.DateTime.DateTimeFrom('1.1.4004 BCE').jdn
    258994.5
    mx.DateTime.DateTimeFromJDN(258994.5)
    <mx.DateTime.DateTime object for '-4003-01-01 00:00:00.00' at 2b534aeb72f0>
    mx.DateTime.DateTimeFrom('1.1.4004 BCE').mjd
    -2141006.0
    mx.DateTime.DateTimeFromMJD(-2141006.0)
    <mx.DateTime.DateTime object for '-4003-01-01 00:00:00.00' at 2b534a46a2f0>

    The supported date range is limited by the number of days
    that fit into a C long. Should be enough for most use cases :-)
    Nice ... :) I didn't know that mxDateTime has support for Julian Date.

    Christian
  • M.-A. Lemburg at Oct 7, 2009 at 2:47 pm

    Christian Heimes wrote:
    M.-A. Lemburg schrieb:
    Christian Heimes wrote:
    Ben Finney wrote:
    If you're committed to changing the epoch anyway, I would recommend
    using <URL:http://en.wikipedia.org/wiki/Astronomical_year_numbering>
    (epoch at 4004 BCE) since it is widely used to unify dates referring to
    human history.
    I prefer JDN or MJD (http://en.wikipedia.org/wiki/JDN) for dates long
    before or after the unix epoch. The conversion from JDN as float to a
    datetime object is trivial.
    FWIW, mxDateTime can help you with all of those:
    import mx.DateTime
    mx.DateTime.DateTimeFrom('1.1.4004 BCE')
    <mx.DateTime.DateTime object for '-4003-01-01 00:00:00.00' at 2b534a46a2f0>
    mx.DateTime.DateTimeFrom('1.1.4004 BCE').jdn
    258994.5
    mx.DateTime.DateTimeFromJDN(258994.5)
    <mx.DateTime.DateTime object for '-4003-01-01 00:00:00.00' at 2b534aeb72f0>
    mx.DateTime.DateTimeFrom('1.1.4004 BCE').mjd
    -2141006.0
    mx.DateTime.DateTimeFromMJD(-2141006.0)
    <mx.DateTime.DateTime object for '-4003-01-01 00:00:00.00' at 2b534a46a2f0>

    The supported date range is limited by the number of days
    that fit into a C long. Should be enough for most use cases :-)
    Nice ... :) I didn't know that mxDateTime has support for Julian Date.
    It also implements the TJD that's sometimes used in the US (the NIST
    definition of it):
    mx.DateTime.DateTimeFrom('1.1.4004 BCE').tjd
    -1006.0
    mx.DateTime.DateTimeFrom('1.1.4004 BCE').tjd_myriad
    26
    mx.DateTime.DateTimeFromTJD(-1006.0, 26)
    <mx.DateTime.DateTime object for '-4003-01-01 00:00:00.00' at 2b81d4a58558>

    And has support for the Julian calendar:
    mx.DateTime.JulianDateTime(1752, 9, 2).Gregorian()
    <mx.DateTime.DateTime object for '1752-09-13 00:00:00.00' at 2b81d4a6eb88>

    which is sometimes handy for historical dates:

    http://en.wikipedia.org/wiki/Julian_calendar

    --
    Marc-Andre Lemburg
    eGenix.com

    Professional Python Services directly from the Source (#1, Oct 07 2009)
    Python/Zope Consulting and Support ... http://www.egenix.com/
    mxODBC.Zope.Database.Adapter ... http://zope.egenix.com/
    mxODBC, mxDateTime, mxTextTools ... http://python.egenix.com/
    ________________________________________________________________________

    ::: Try our new mxODBC.Connect Python Database Interface for free ! ::::


    eGenix.com Software, Skills and Services GmbH Pastor-Loeh-Str.48
    D-40764 Langenfeld, Germany. CEO Dipl.-Math. Marc-Andre Lemburg
    Registered at Amtsgericht Duesseldorf: HRB 46611
    http://www.egenix.com/company/contact/
  • John Yeung at Oct 8, 2009 at 9:08 pm

    On Oct 6, 5:11?pm, Christian Heimes wrote:
    Ben Finney wrote:
    If you're committed to changing the epoch anyway, I would recommend
    using <URL:http://en.wikipedia.org/wiki/Astronomical_year_numbering>
    (epoch at 4004 BCE) since it is widely used to unify dates referring to
    human history.
    I prefer JDN or MJD (http://en.wikipedia.org/wiki/JDN) for dates long
    before or after the unix epoch. The conversion from JDN as float to a
    datetime object is trivial.
    I think the choice of epoch is not a big deal, once you pick one far
    enough back. Ben Finney's suggestion to use 4004 BCE is not
    appreciably different (computationally) from JDN. (Though I will say
    that the Wikipedia link he provided doesn't mention 4004 BCE, and if
    anything suggests using 1 CE as the epoch.)

    If there is any difficulty, it would be determining whether historical
    records used (for example) the Julian calendar or Gregorian. This
    doesn't seem to be a factor for the OP's use case, so my
    recommendation would be to just pick whatever's convenient (either
    because some library or program uses it, or because it makes intuitive
    sense to the programmer).

    John
  • Ben Finney at Oct 8, 2009 at 10:36 pm

    John Yeung <gallium.arsenide at gmail.com> writes:

    I think the choice of epoch is not a big deal, once you pick one far
    enough back. Ben Finney's suggestion to use 4004 BCE is not
    appreciably different (computationally) from JDN. (Though I will say
    that the Wikipedia link he provided doesn't mention 4004 BCE, and if
    anything suggests using 1 CE as the epoch.)
    My apologies, I gave the wrong year. I was intending to refer to the
    <URL:http://en.wikipedia.org/wiki/Julian_date> system, which begins at
    the year ?4712 (4713 BCE).

    This has the advantages of:

    * clearly covering spans of human history more recent than ancient
    civilisations

    * having a long-recognised standard specification

    * being commonly used in computing (for astronomy and other scientific
    computing applications)

    * making arithmetic on dates simple (it uses a year zero, making the
    time line an uninterrupted number line)

    --
    \ ?When we talk to God, we're praying. When God talks to us, |
    `\ we're schizophrenic.? ?Jane Wagner, via Lily Tomlin, 1985 |
    _o__) |
    Ben Finney

Related Discussions

Discussion Navigation
viewthread | post
Discussion Overview
grouppython-list @
categoriespython
postedOct 5, '09 at 11:54p
activeOct 12, '09 at 6:34p
posts26
users13
websitepython.org

People

Translate

site design / logo © 2022 Grokbase