Re: [Python-Dev] iso8601 parsing

2017-10-25 Thread Alex Walters


> -Original Message-
> From: Python-Dev [mailto:python-dev-bounces+tritium-
> [email protected]] On Behalf Of Alexander Belopolsky
> Sent: Tuesday, October 24, 2017 5:54 PM
> To: Chris Barker 
> Cc: Python-Dev 
> Subject: Re: [Python-Dev] iso8601 parsing
> 
> On Tue, Oct 24, 2017 at 5:26 PM, Chris Barker 
> wrote:
> > On Mon, Oct 23, 2017 at 5:33 PM, Hasan Diwan 
> wrote:
> >>
> > can anyone argue that it's not a good idea for datetime ot
> > be able to read the iso format it puts out?
> 
> No, but the last time I suggested that that datetime types should
> satisfy the same invariants as numbers, namely
> T(repr(x)) == x, the idea was met will silence.  I, on the other hand,
> am not very enthusiastic about named constructors such as
> date.isoparse().  Compared with date(s:str), this is one more method
> name to remember, plus the potential for abuse as an instance method.
> What is d.isoparse('2017-11-24')?

Datetime.datetime.fromiso() (classmethod) is much more in keeping with the
rest of the datetime api - in fact, I have tried calling that method more
than once, before remembering datetime *doesn't* have that classmethod.
Making it a classmethod solves any concerns about calling it as an instance
method (the same way d.now() and d.strptime() just create and return a new
datetime objects, not mutates the current).  In fact, looking at the docs,
most of the methods are classmethods, so an additional classmethod is
fitting.

I really do not like the idea of making the first positional argument of the
datetime constructor int or str.  What happens when you pass a string for
the first argument and ints for subsequent arguments?  You would have to
raise a typeerror or valueerror.  I don't like that API design - it means
the type of the first argument changes the semantic meaning of subsequent
arguments, and that just adds a level of confusion to any api.  You might be
able to get away with that in third party code, but this is the standard
library, and this is the time manipulation module in the standard library -
you have to assume that this is one of the first modules a new user uses, we
have to keep the api sane.

The only way I can think of keeping the api sane and still pass an iso
string to the constructor is to pass It as a keyword argument - and at that
point you have to remember the argument name anyways, so you might as well
make it a classmethod to match everything else in the library.

$0.02

> ___
> Python-Dev mailing list
> [email protected]
> https://mail.python.org/mailman/listinfo/python-dev
> Unsubscribe: https://mail.python.org/mailman/options/python-dev/tritium-
> list%40sdamon.com

___
Python-Dev mailing list
[email protected]
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] iso8601 parsing

2017-10-25 Thread Alexander Belopolsky


> On Oct 25, 2017, at 11:45 AM, Alex Walters  wrote:
> 
> it means
> the type of the first argument changes the semantic meaning of subsequent
> arguments, and that just adds a level of confusion to any api.

No, it does not. Passing a string a the first of three arguments will still be 
a type error. 
___
Python-Dev mailing list
[email protected]
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] iso8601 parsing

2017-10-25 Thread Alex Walters


> -Original Message-
> From: Alexander Belopolsky [mailto:[email protected]]
> Sent: Wednesday, October 25, 2017 12:07 PM
> To: Alex Walters 
> Cc: Chris Barker ; Python-Dev  [email protected]>
> Subject: Re: [Python-Dev] iso8601 parsing
> 
> 
> 
> > On Oct 25, 2017, at 11:45 AM, Alex Walters 
> wrote:
> >
> > it means
> > the type of the first argument changes the semantic meaning of
> subsequent
> > arguments, and that just adds a level of confusion to any api.
> 
> No, it does not. Passing a string a the first of three arguments will
still be a
> type error.

And that is a confusing api.  The problem has already been solved by
classmethod alternate constructors - they are already used widely in the
datetime api.  NOT using classmethod constructors is new and confusing for
the SINGLE use case of parsing iso formatted dates and times.  Why is that
special?  Why isn't ordinal time special to get into __init__?

___
Python-Dev mailing list
[email protected]
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] iso8601 parsing

2017-10-25 Thread Alex Walters


> -Original Message-
> From: Python-Dev [mailto:python-dev-bounces+tritium-
> [email protected]] On Behalf Of Elvis Pranskevichus
> Sent: Tuesday, October 24, 2017 8:12 PM
> To: [email protected]
> Cc: Chris Barker 
> Subject: Re: [Python-Dev] iso8601 parsing
> 
> On Tuesday, October 24, 2017 5:53:58 PM EDT Alexander Belopolsky wrote:
> > No, but the last time I suggested that that datetime types should
> > satisfy the same invariants as numbers, namely
> > T(repr(x)) == x, the idea was met will silence.  I, on the other hand,
> > am not very enthusiastic about named constructors such as
> > date.isoparse().  Compared with date(s:str), this is one more method
> > name to remember, plus the potential for abuse as an instance method.
> > What is d.isoparse('2017-11-24')?
> 
> Agreed.  datetime(s:str) seems like a far more natural and consistent
> choice.

It's inconsistent with the rest of the module.  All other constructions of
datetime objects are on classmethods.  Why make parsing ISO time special?

> 
>  Elvis
> ___
> Python-Dev mailing list
> [email protected]
> https://mail.python.org/mailman/listinfo/python-dev
> Unsubscribe: https://mail.python.org/mailman/options/python-dev/tritium-
> list%40sdamon.com

___
Python-Dev mailing list
[email protected]
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] iso8601 parsing

2017-10-25 Thread Alexander Belopolsky
On Wed, Oct 25, 2017 at 3:48 PM, Alex Walters  wrote:
>  Why make parsing ISO time special?

It's not the ISO format per se that is special, but parsing of str(x).
For all numeric types, int, float, complex and even
fractions.Fraction, we have a roundtrip invariant T(str(x)) == x.
Datetime types are a special kind of numbers, but they don't follow
this established pattern.  This is annoying when you deal with time
series where it is common to have text files with a mix of dates,
timestamps and numbers.  You can write generic code to deal with ints
and floats, but have to special-case anything time related.
___
Python-Dev mailing list
[email protected]
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] iso8601 parsing

2017-10-25 Thread Alex Walters


> -Original Message-
> From: Alexander Belopolsky [mailto:[email protected]]
> Sent: Wednesday, October 25, 2017 4:33 PM
> To: Alex Walters 
> Cc: Elvis Pranskevichus ; Python-Dev  [email protected]>; Chris Barker 
> Subject: Re: [Python-Dev] iso8601 parsing
> 
> On Wed, Oct 25, 2017 at 3:48 PM, Alex Walters 
> wrote:
> >  Why make parsing ISO time special?
> 
> It's not the ISO format per se that is special, but parsing of str(x).
> For all numeric types, int, float, complex and even
> fractions.Fraction, we have a roundtrip invariant T(str(x)) == x.
> Datetime types are a special kind of numbers, but they don't follow
> this established pattern.  This is annoying when you deal with time
> series where it is common to have text files with a mix of dates,
> timestamps and numbers.  You can write generic code to deal with ints
> and floats, but have to special-case anything time related.

>>> repr(datetime.datetime.now())
'datetime.datetime(2017, 10, 25, 17, 16, 20, 973107)'

You can already roundtrip the repr of datetime objects with eval (if you care 
to do so).  You get iso formatting from a method on dt objects, I don’t see why 
it should be parsed by anything but a classmethod.

___
Python-Dev mailing list
[email protected]
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] iso8601 parsing

2017-10-25 Thread Random832
On Wed, Oct 25, 2017, at 16:32, Alexander Belopolsky wrote:
> This is annoying when you deal with time
> series where it is common to have text files with a mix of dates,
> timestamps and numbers.  You can write generic code to deal with ints
> and floats, but have to special-case anything time related.

Generic code that uses a Callable[[str], ...] instead of a type works
fine with a class method.

column1.parser = int
column2.parser = float
column3.parser = datetime.parse_iso
column4.parser = json.loads

It is *very slightly* more complex than a model that needs the type also
for some reason and has the type pull double duty as the parser... but
why do that?
___
Python-Dev mailing list
[email protected]
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] iso8601 parsing

2017-10-25 Thread Chris Barker
+1 on a classmethod constructor
+0 on a based-on-type default constructor

+inf on SOMETHING!

Let's get passed the bike shedding and make this work!

-CHB


On Wed, Oct 25, 2017 at 2:18 PM, Alex Walters 
wrote:

>
>
> > -Original Message-
> > From: Alexander Belopolsky [mailto:[email protected]]
> > Sent: Wednesday, October 25, 2017 4:33 PM
> > To: Alex Walters 
> > Cc: Elvis Pranskevichus ; Python-Dev  > [email protected]>; Chris Barker 
> > Subject: Re: [Python-Dev] iso8601 parsing
> >
> > On Wed, Oct 25, 2017 at 3:48 PM, Alex Walters 
> > wrote:
> > >  Why make parsing ISO time special?
> >
> > It's not the ISO format per se that is special, but parsing of str(x).
> > For all numeric types, int, float, complex and even
> > fractions.Fraction, we have a roundtrip invariant T(str(x)) == x.
> > Datetime types are a special kind of numbers, but they don't follow
> > this established pattern.  This is annoying when you deal with time
> > series where it is common to have text files with a mix of dates,
> > timestamps and numbers.  You can write generic code to deal with ints
> > and floats, but have to special-case anything time related.
>
> >>> repr(datetime.datetime.now())
> 'datetime.datetime(2017, 10, 25, 17, 16, 20, 973107)'
>
> You can already roundtrip the repr of datetime objects with eval (if you
> care to do so).  You get iso formatting from a method on dt objects, I
> don’t see why it should be parsed by anything but a classmethod.
>
>
>


-- 

Christopher Barker, Ph.D.
Oceanographer

Emergency Response Division
NOAA/NOS/OR&R(206) 526-6959   voice
7600 Sand Point Way NE   (206) 526-6329   fax
Seattle, WA  98115   (206) 526-6317   main reception

[email protected]
___
Python-Dev mailing list
[email protected]
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] iso8601 parsing

2017-10-25 Thread Steven D'Aprano
On Wed, Oct 25, 2017 at 04:32:39PM -0400, Alexander Belopolsky wrote:
> On Wed, Oct 25, 2017 at 3:48 PM, Alex Walters  wrote:
> >  Why make parsing ISO time special?
> 
> It's not the ISO format per se that is special, but parsing of str(x).
> For all numeric types, int, float, complex and even
> fractions.Fraction, we have a roundtrip invariant T(str(x)) == x.
> Datetime types are a special kind of numbers, but they don't follow
> this established pattern.  This is annoying when you deal with time
> series where it is common to have text files with a mix of dates,
> timestamps and numbers.  You can write generic code to deal with ints
> and floats, but have to special-case anything time related.

Maybe I'm just being slow today, but I don't see how you can write 
"generic code" to convert text to int/float/complex/Fraction, but not 
times. The only difference is that instead of calling the type directly, 
you call the appropriate classmethod.

What am I missing?



-- 
Steven
___
Python-Dev mailing list
[email protected]
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] iso8601 parsing

2017-10-25 Thread Alexander Belopolsky
On Wed, Oct 25, 2017 at 5:30 PM, Steven D'Aprano  wrote:
> Maybe I'm just being slow today, but I don't see how you can write
> "generic code" to convert text to int/float/complex/Fraction, but not
> times. The only difference is that instead of calling the type directly,
> you call the appropriate classmethod.
>
> What am I missing?

Nothing. The only annoyance is that the data processing code typically
needs to know the type anyway, so the classmethod is one more variable
to keep track of.
___
Python-Dev mailing list
[email protected]
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] iso8601 parsing

2017-10-25 Thread Alexander Belopolsky
On Wed, Oct 25, 2017 at 5:30 PM, Chris Barker  wrote:

> Let's get passed the bike shedding and make this work!

Sure.  Submitting a pull request for
 would be a good start.
___
Python-Dev mailing list
[email protected]
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] iso8601 parsing

2017-10-25 Thread Chris Barker
On Wed, Oct 25, 2017 at 4:22 PM, Alexander Belopolsky <
[email protected]> wrote:

> > times. The only difference is that instead of calling the type directly,
> > you call the appropriate classmethod.
> >
> > What am I missing?
>
> Nothing. The only annoyance is that the data processing code typically
> needs to know the type anyway, so the classmethod is one more variable
> to keep track of.


I don't think anyone is arguing that is is hard to do either way, or that
hard to use either way.

I think it comes down to a trade-off between:

Having an API for datetime that is like the datetime for number types:

 int(str(an_int)) == an_int

 so:

 datetime(str(a_datetime)) == a_datetime

Alexander strongly supports that.

Or an API that is perhaps more like the rest of the datetime api, which has
a number of alternate constructors:

 datetime.now()

 datetime.fromordinal()

 datetime.fromtimestamp()

And has:

  datetime.isoformat()

So a

   datetime.fromisoformat()

would make a lot of sense.

I would note that the number types don't have all those alternate
constructors Also, the number types mostly have a single parameter (except
int has an optional base parameter). So I'm not sure the parallel is that
strong.

Would it be horrible if we did both?

After all, right now, datetime has:

In [16]: dt.isoformat()
Out[16]: '2017-10-25T16:30:48.744489'

and
In [18]: dt.__str__()
Out[18]: '2017-10-25 16:30:48.744489'

which do almost the same thing (I understand the "T" is option in iso 8601)

However, maybe they are different when you add a time zone?

ISO 8601 support offsets, but not time zones -- presumably the __str__
supports the full datetime tzinfo somehow. Which may be why .isoformat()
exists.

Though I don't think that means you couldn't have the __init__ parse proper
ISO strings, in addition to the full datetime __str__ results.

-CHB


-- 

Christopher Barker, Ph.D.
Oceanographer

Emergency Response Division
NOAA/NOS/OR&R(206) 526-6959   voice
7600 Sand Point Way NE   (206) 526-6329   fax
Seattle, WA  98115   (206) 526-6317   main reception

[email protected]
___
Python-Dev mailing list
[email protected]
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] iso8601 parsing

2017-10-25 Thread Guido van Rossum
I think this ship has long sailed. Sorry Alexander, but I see a new class
method in your future.

-- 
--Guido van Rossum (python.org/~guido)
___
Python-Dev mailing list
[email protected]
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] iso8601 parsing

2017-10-25 Thread Wes Turner
On Wednesday, October 25, 2017, Chris Barker  wrote:

> On Wed, Oct 25, 2017 at 4:22 PM, Alexander Belopolsky <
> [email protected]
> > wrote:
>
>> > times. The only difference is that instead of calling the type directly,
>> > you call the appropriate classmethod.
>> >
>> > What am I missing?
>>
>> Nothing. The only annoyance is that the data processing code typically
>> needs to know the type anyway, so the classmethod is one more variable
>> to keep track of.
>
>
> I don't think anyone is arguing that is is hard to do either way, or that
> hard to use either way.
>
> I think it comes down to a trade-off between:
>
> Having an API for datetime that is like the datetime for number types:
>
>  int(str(an_int)) == an_int
>
>  so:
>
>  datetime(str(a_datetime)) == a_datetime
>
> Alexander strongly supports that.
>
> Or an API that is perhaps more like the rest of the datetime api, which
> has a number of alternate constructors:
>
>  datetime.now()
>
>  datetime.fromordinal()
>
>  datetime.fromtimestamp()
>
> And has:
>
>   datetime.isoformat()
>
> So a
>
>datetime.fromisoformat()
>
> would make a lot of sense.
>
> I would note that the number types don't have all those alternate
> constructors Also, the number types mostly have a single parameter (except
> int has an optional base parameter). So I'm not sure the parallel is that
> strong.
>
> Would it be horrible if we did both?
>
> After all, right now, datetime has:
>
> In [16]: dt.isoformat()
> Out[16]: '2017-10-25T16:30:48.744489'
>
> and
> In [18]: dt.__str__()
> Out[18]: '2017-10-25 16:30:48.744489'
>
> which do almost the same thing (I understand the "T" is option in iso 8601)
>
> However, maybe they are different when you add a time zone?
>
> ISO 8601 support offsets, but not time zones -- presumably the __str__
> supports the full datetime tzinfo somehow. Which may be why .isoformat()
> exists.
>

ISO8601 does support timezones.
https://en.wikipedia.org/wiki/ISO_8601#Time_zone_designators

I might be wrong, but I think many of the third party libraries listed here
default to either UTC or timezone-naieve timezones:
https://github.com/vinta/awesome-python/blob/master/README.md#date-and-time

Ctrl-F for 'tzinfo=' in the docs really doesn't explain how to just do it
with my local time.

Here's an example with a *custom* GMT1 tzinfo subclass:
https://docs.python.org/3/library/datetime.html#datetime.time.tzname



> Though I don't think that means you couldn't have the __init__ parse
> proper ISO strings, in addition to the full datetime __str__ results.
>

What would you call the str argument? Does it accept strptime args or only
ISO8601? Would all of that string parsing logic be a performance regression
from the current constructor? Does it accept None or empty string?

...

Deserializing dates from JSON (without #JSONLD and xsd:dateTime (ISO8601))
types is nasty, regardless (try/except, *custom* schema awareness). And
pickle is dangerous.

AFAIU, we should not ever eval(repr(dt: datetime)).

...

Should the date time constructor support nanos= (just like time_ns())?

ENH: Add nanosecond support to the time and datetime constructors

...

The astropy Time class supports a string argument as the first parameter
sometimes:
http://docs.astropy.org/en/stable/time/#inferring-input-format

Astropy does support a "year zero".

>
___
Python-Dev mailing list
[email protected]
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] iso8601 parsing

2017-10-25 Thread Fred Drake
On Wed, Oct 25, 2017 at 10:37 PM, Wes Turner  wrote:
> What would you call the str argument? Does it accept strptime args or only
> ISO8601?

There'd be no reason to accept a format.  That wouldn't make sense.  A
.fromiso(s:str) should only accept an ISO 8601 string, though I'd
advocate tolerating both space and "T".

> Would all of that string parsing logic be a performance regression
> from the current constructor? Does it accept None or empty string?

It's an alternate constructor, so should not impact the existing
constructor (though it could employ the existing constructor to get
work done).

It should not accept anything but a valid ISO 8601 string.

> Should the date time constructor support nanos= (just like time_ns())?

No.  It should support exactly up to 6 decimal digits to populate the
microsecond field.

> ENH: Add nanosecond support to the time and datetime constructors

This should be left for a separate change, if we determine it should
be implemented for the datetime and timedelta types.


  -Fred

-- 
Fred L. Drake, Jr.
"A storm broke loose in my mind."  --Albert Einstein
___
Python-Dev mailing list
[email protected]
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] iso8601 parsing

2017-10-25 Thread Nick Coghlan
On 26 October 2017 at 07:30, Chris Barker  wrote:

> +1 on a classmethod constructor
> +0 on a based-on-type default constructor
>
> +inf on SOMETHING!
>
> Let's get passed the bike shedding and make this work!
>

I'll also note that these aren't either/or outcomes: adding a str-specific
classmethod *doesn't* preclude implicitly calling that class method from
the default constructor later based on the input type.

For example, decimal.Decimal.from_float() was added before the type
constructor gained native support for float inputs, due to concerns about
potential binary-vs-decimal rounding errors arising from doing such
conversions implicitly.

So we can add "datetime.fromisoformat(isotime: str)" now, and then *if* we
later decide to support the "type(x)(str(x)) == x" numeric invariant for
the datetime classes, that can be specified as "If the constructor
arguments consist of a single string, that is handled by calling the
fromisoformat class method".

Cheers,
Nick.

-- 
Nick Coghlan   |   [email protected]   |   Brisbane, Australia
___
Python-Dev mailing list
[email protected]
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com