Hi Wes,

Sounds good to me.

Br,

Zoltan

On Thu, Jul 11, 2019 at 4:14 PM Wes McKinney <[email protected]> wrote:
>
> On Thu, Jul 11, 2019 at 8:17 AM Zoltan Ivanfi <[email protected]> 
> wrote:
> >
> > Hi Wes,
> >
> > I did a little bit of testing using pyarrow 0.14.0. I know that this
> > is not the latest state of the code, but my understanding is that the
> > only planned change is that 0.14.1 will add the legacy types even for
> > local semantics. Here is what I did:
> >
> >     In [1]: import pandas as pd
> >        ...: from datetime import datetime
> >        ...: from pandas import Timestamp
> >        ...: from pytz import timezone
> >        ...: ts_dt = datetime(1970, 1, 1)
> >        ...: ts_pd = Timestamp(year=1970, month=1, day=1)
> >        ...: ts_pd_paris = Timestamp(year=1970, month=1, day=1, hour=1,
> > tz=timezone("Europe/Paris"))
> >        ...: ts_pd_helsinki = Timestamp(year=1970, month=1, day=1,
> > hour=2, tz=timezone("Europe/Helsinki"))
> >        ...: df = pd.DataFrame({
> >        ...:     'datetime': [ts_dt, None],
> >        ...:     'pd_no_tz': [ts_pd, None],
> >        ...:     'pd_paris': [ts_pd_paris, None],
> >        ...:     'pd_helsinki': [ts_pd_helsinki, None],
> >        ...:     'pd_mixed': [ts_pd_paris, ts_pd_helsinki]
> >        ...: })
> >        ...: df.to_parquet('test.parquet')
> >        ...: df
> >     Out[1]:
> >         datetime   pd_no_tz                  pd_paris
> > pd_helsinki                   pd_mixed
> >     0 1970-01-01 1970-01-01 1970-01-01 01:00:00+01:00 1970-01-01
> > 02:00:00+02:00  1970-01-01 01:00:00+01:00
> >     1        NaT        NaT                       NaT
> >      NaT  1970-01-01 02:00:00+02:00
> >
> > I picked these values because I expected all of these timestamps to be
> > saved as the numeric value 0. Checking the metadata using
> > parquet-tools:
> >
> >     > parquet-tools meta test.parquet
> >     datetime:    OPTIONAL INT64 L:TIMESTAMP(MILLIS,false) R:0 D:1
> >     pd_no_tz:    OPTIONAL INT64 L:TIMESTAMP(MILLIS,false) R:0 D:1
> >     pd_paris:    OPTIONAL INT64 L:TIMESTAMP(MILLIS,true) R:0 D:1
> >     pd_helsinki: OPTIONAL INT64 L:TIMESTAMP(MILLIS,true) R:0 D:1
> >     pd_mixed:    OPTIONAL INT64 L:TIMESTAMP(MILLIS,false) R:0 D:1
> >
> > This matched my expectations up until pd_mixed. I was surprised to see
> > that timestamps with mixed time zones were be stored using local
> > semantics instead of being normalized to UTC, but if it's an
> > intentional choice, I'm fine with it as long as the numbers are
> > correct:
> >
> >     > parquet-tools head test.parquet
> >     datetime = 0
> >     pd_no_tz = 0
> >     pd_paris = 0
> >     pd_helsinki = 0
> >     pd_mixed = 3600000
> >     pd_mixed = 7200000
> >
> > The numbers for the mixed column are not 0, but that is just the
> > result of not using UTC-normalized semantics there. The values can be
> > correctly interpreted by parquet-tools:
> >
> >     > parquet-tools dump test.parquet
> >     INT64 datetime
> >     
> > --------------------------------------------------------------------------------
> >     *** row group 1 of 1, values 1 to 2 ***
> >     value 1: R:0 D:1 V:1970-01-01T00:00:00.000
> >     value 2: R:0 D:0 V:<null>
> >
> >     INT64 pd_no_tz
> >     
> > --------------------------------------------------------------------------------
> >     *** row group 1 of 1, values 1 to 2 ***
> >     value 1: R:0 D:1 V:1970-01-01T00:00:00.000
> >     value 2: R:0 D:0 V:<null>
> >
> >     INT64 pd_paris
> >     
> > --------------------------------------------------------------------------------
> >     *** row group 1 of 1, values 1 to 2 ***
> >     value 1: R:0 D:1 V:1970-01-01T00:00:00.000+0000
> >     value 2: R:0 D:0 V:<null>
> >
> >     INT64 pd_helsinki
> >     
> > --------------------------------------------------------------------------------
> >     *** row group 1 of 1, values 1 to 2 ***
> >     value 1: R:0 D:1 V:1970-01-01T00:00:00.000+0000
> >     value 2: R:0 D:0 V:<null>
> >
> >     INT64 pd_mixed
> >     
> > --------------------------------------------------------------------------------
> >     *** row group 1 of 1, values 1 to 2 ***
> >     value 1: R:0 D:1 V:1970-01-01T01:00:00.000
> >     value 2: R:0 D:1 V:1970-01-01T02:00:00.000
> >
> > And naturally by pandas as well:
> >
> >     In [2]: df2 = pd.read_parquet('test.parquet')
> >        ...: df2
> >     Out[2]:
> >         datetime   pd_no_tz                  pd_paris
> > pd_helsinki            pd_mixed
> >     0 1970-01-01 1970-01-01 1970-01-01 01:00:00+01:00 1970-01-01
> > 02:00:00+02:00 1970-01-01 01:00:00
> >     1        NaT        NaT                       NaT
> >      NaT 1970-01-01 02:00:00
> >
> > Finally, let's try an older version of parquet-tools as well:
> >
> >     > parquet-tools meta test.parquet
> >     datetime:    OPTIONAL INT64 R:0 D:1
> >     pd_no_tz:    OPTIONAL INT64 R:0 D:1
> >     pd_paris:    OPTIONAL INT64 O:TIMESTAMP_MILLIS R:0 D:1
> >     pd_helsinki: OPTIONAL INT64 O:TIMESTAMP_MILLIS R:0 D:1
> >     pd_mixed:    OPTIONAL INT64 R:0 D:1
> >
>
> Just to confirm that in pyarrow 0.13.0 (which tracks
> parquet-cpp-in-development 1.6.0, prior to introduction of
> LogicalType), TIMESTAMP_* is set for all 5 columns. This is the
> forward compatibility that we are planning to restore.
>
> > This confirms that the legacy types are only written for
> > UTC-normalized timestamps in 0.14.0.
> >
> > In summary, when saving two timestamps from different time zones that
> > refer to the same instant, I would have expected pyarrow to normalize
> > to UTC and thereby sacrifice the local representations instead of
> > saving using local semantics and thereby sacrificing the instants. I
> > don't know whether that is the intended behaviour, but in any case,
> > based on this short manual testing, the new timestamp types written by
> > pyarrow are interopable with the Java library.
> >
> > Br,
> >
> > Zoltan
> >
> > On Wed, Jul 10, 2019 at 4:30 PM Wes McKinney <[email protected]> wrote:
> > >
> > > Correct
> > >
> > > On Wed, Jul 10, 2019 at 9:21 AM Zoltan Ivanfi <[email protected]> 
> > > wrote:
> > > >
> > > > Hi Wes,
> > > >
> > > > Do you mean that the new logical types have already been released in 
> > > > 0.14.0
> > > > and a 0.14.1 is needed ASAP to fix this regression?
> > > >
> > > > Thanks,
> > > >
> > > > Zoltan
> > > >
> > > > On Wed, Jul 10, 2019 at 4:13 PM Wes McKinney <[email protected]> 
> > > > wrote:
> > > >
> > > > > hi Zoltan -- given the raging fire that is 0.14.0 as a result of these
> > > > > issues and others we need to make a new release within the next 7-10
> > > > > days. We can point you to nightly Python builds to make testing for
> > > > > you easier so you don't have to build the project yourself.
> > > > >
> > > > > - Wes
> > > > >
> > > > > On Wed, Jul 10, 2019 at 9:11 AM Zoltan Ivanfi 
> > > > > <[email protected]>
> > > > > wrote:
> > > > > >
> > > > > > Hi,
> > > > > >
> > > > > > Oh, and one more thing: Before releasing the next Arrow version
> > > > > > incorporating the new logical types, we should definitely test that 
> > > > > > their
> > > > > > behaviour matches that of parquet-mr. When is the next release 
> > > > > > planned to
> > > > > > come out?
> > > > > >
> > > > > > Br,
> > > > > >
> > > > > > Zoltan
> > > > > >
> > > > > > On Wed, Jul 10, 2019 at 3:57 PM Zoltan Ivanfi <[email protected]> 
> > > > > > wrote:
> > > > > >
> > > > > > > Hi Wes,
> > > > > > >
> > > > > > > Yes, I agree that we should do that, but then we have a problem of
> > > > > what to
> > > > > > > do in the other direction, i.e. when we use the new logical types 
> > > > > > > API
> > > > > to
> > > > > > > read a TIMESTAMP_MILLIS or TIMESTAMP_MICROS, how should we set 
> > > > > > > the UTC
> > > > > > > normalized flag? Tim has started a discussion about that, 
> > > > > > > suggesting
> > > > > to use
> > > > > > > three states that I just answered.
> > > > > > >
> > > > > > > Br,
> > > > > > >
> > > > > > > Zoltan
> > > > > > >
> > > > > > > On Wed, Jul 10, 2019 at 3:52 PM Wes McKinney <[email protected]>
> > > > > wrote:
> > > > > > >
> > > > > > >> Thank for the comments.
> > > > > > >>
> > > > > > >> So in summary I think that we need to set the TIMESTAMP_* 
> > > > > > >> converted
> > > > > > >> types to maintain forward compatibility and stay consistent with 
> > > > > > >> what
> > > > > > >> we were doing in the C++ library prior to the introduction of the
> > > > > > >> LogicalType metadata.
> > > > > > >>
> > > > > > >> On Wed, Jul 10, 2019 at 8:20 AM Zoltan Ivanfi 
> > > > > > >> <[email protected]
> > > > > >
> > > > > > >> wrote:
> > > > > > >> >
> > > > > > >> > Hi Wes,
> > > > > > >> >
> > > > > > >> > Both of the semantics are deterministic in one aspect and
> > > > > > >> indeterministic
> > > > > > >> > in another. Timestamps of instant semantic will always refer 
> > > > > > >> > to the
> > > > > same
> > > > > > >> > instant, but their user-facing representation (how they get
> > > > > displayed)
> > > > > > >> > depends on the user's time zone. Timestamps of local semantics
> > > > > always
> > > > > > >> have
> > > > > > >> > the same user-facing representation but the instant they refer 
> > > > > > >> > to is
> > > > > > >> > undefined (or ambigous, depending on your point of view).
> > > > > > >> >
> > > > > > >> > My understanding is that Spark uses instant semantics, i.e.,
> > > > > timestamps
> > > > > > >> are
> > > > > > >> > stored normalized to UTC and are displayed adjusted to the 
> > > > > > >> > user's
> > > > > local
> > > > > > >> > time zone.
> > > > > > >> >
> > > > > > >> > Br,
> > > > > > >> >
> > > > > > >> > Zoltan
> > > > > > >> >
> > > > > > >> > On Tue, Jul 9, 2019 at 7:04 PM Wes McKinney 
> > > > > > >> > <[email protected]>
> > > > > > >> wrote:
> > > > > > >> >
> > > > > > >> > > Thanks Zoltan.
> > > > > > >> > >
> > > > > > >> > > This is definitely a tricky issue.
> > > > > > >> > >
> > > > > > >> > > Spark's application of localtime semantics to timestamp data 
> > > > > > >> > > has
> > > > > been
> > > > > > >> > > a source of issues for many people. Personally I don't find 
> > > > > > >> > > that
> > > > > > >> > > behavior to be particularly helpful since depending on the 
> > > > > > >> > > session
> > > > > > >> > > time zone, you will get different results on data not marked 
> > > > > > >> > > as
> > > > > > >> > > UTC-normalized.
> > > > > > >> > >
> > > > > > >> > > In pandas, as contrast, we apply UTC semantics to
> > > > > > >> > > naive/not-explicitly-normalized data so at least the code 
> > > > > > >> > > produces
> > > > > > >> > > deterministic results on all environments. That seems 
> > > > > > >> > > strictly
> > > > > better
> > > > > > >> > > to me -- if you want a localized interpretation of naive 
> > > > > > >> > > data, you
> > > > > > >> > > must opt into this rather than having it automatically 
> > > > > > >> > > selected
> > > > > based
> > > > > > >> > > on your locale. The instances of people shooting their toes 
> > > > > > >> > > off
> > > > > due to
> > > > > > >> > > time zones are practically non-existent, whereas I'm hearing 
> > > > > > >> > > about
> > > > > > >> > > Spark gotchas all the time.
> > > > > > >> > >
> > > > > > >> > > On Tue, Jul 9, 2019 at 11:34 AM Zoltan Ivanfi
> > > > > <[email protected]
> > > > > > >> >
> > > > > > >> > > wrote:
> > > > > > >> > > >
> > > > > > >> > > > Hi Wes,
> > > > > > >> > > >
> > > > > > >> > > > The rules for TIMESTAMP forward-compatibility were created
> > > > > based on
> > > > > > >> the
> > > > > > >> > > > assumption that TIMESTAMP_MILLIS and TIMESTAMP_MICROS have 
> > > > > > >> > > > only
> > > > > > >> been used
> > > > > > >> > > > in the instant aka. UTC-normalized semantics so far. This
> > > > > > >> assumption was
> > > > > > >> > > > supported by two sources:
> > > > > > >> > > >
> > > > > > >> > > > 1. The specification: parquet-format defined 
> > > > > > >> > > > TIMESTAMP_MILLIS
> > > > > and
> > > > > > >> > > > TIMESTAMP_MICROS as the number of milli/microseconds 
> > > > > > >> > > > elapsed
> > > > > since
> > > > > > >> the
> > > > > > >> > > Unix
> > > > > > >> > > > epoch, an instant specified in UTC, from which it follows 
> > > > > > >> > > > that
> > > > > they
> > > > > > >> have
> > > > > > >> > > > instant semantics (because timestamps of local semantics 
> > > > > > >> > > > do not
> > > > > > >> > > correspond
> > > > > > >> > > > to a single instant).
> > > > > > >> > > >
> > > > > > >> > > > 2. Anecdotal knowledge: We were not aware of any software
> > > > > component
> > > > > > >> that
> > > > > > >> > > > used these types differently from the specification.
> > > > > > >> > > >
> > > > > > >> > > > Based on your e-mail, we were wrong on #2.
> > > > > > >> > > >
> > > > > > >> > > > From this false premise it followed that TIMESTAMPs with 
> > > > > > >> > > > local
> > > > > > >> semantics
> > > > > > >> > > > were a new type and did not need to be annotated with the 
> > > > > > >> > > > old
> > > > > types
> > > > > > >> to
> > > > > > >> > > > maintain compatibility. In fact, annotating them with the 
> > > > > > >> > > > old
> > > > > types
> > > > > > >> were
> > > > > > >> > > > considered to be harmful, since it would have mislead older
> > > > > readers
> > > > > > >> into
> > > > > > >> > > > thinking that they can read TIMESTAMPs with local 
> > > > > > >> > > > semantics,
> > > > > when in
> > > > > > >> > > > reality they would have misinterpreted them as TIMESTAMPs 
> > > > > > >> > > > with
> > > > > > >> instant
> > > > > > >> > > > semantics. This would have lead to a difference of several
> > > > > hours,
> > > > > > >> > > > corresponding to the time zone offset.
> > > > > > >> > > >
> > > > > > >> > > > In the light of your e-mail, this misinterpretation of
> > > > > timestamps
> > > > > > >> may
> > > > > > >> > > > already be happening, since if Arrow annotates local 
> > > > > > >> > > > timestamps
> > > > > with
> > > > > > >> > > > TIMESTAMP_MILLIS or TIMESTMAP_MICROS, Spark probably
> > > > > misinterprets
> > > > > > >> them
> > > > > > >> > > as
> > > > > > >> > > > timestamps with instant semantics, leading to a difference 
> > > > > > >> > > > of
> > > > > > >> several
> > > > > > >> > > hours.
> > > > > > >> > > >
> > > > > > >> > > > Based on this, I think it would make sense from Arrow's 
> > > > > > >> > > > point of
> > > > > > >> view to
> > > > > > >> > > > annotate both semantics with the old types, since that is 
> > > > > > >> > > > its
> > > > > > >> historical
> > > > > > >> > > > behaviour and keeping it up is needed for maintaining
> > > > > compatibilty.
> > > > > > >> I'm
> > > > > > >> > > not
> > > > > > >> > > > so sure about the Java library though, since as far as I 
> > > > > > >> > > > know,
> > > > > these
> > > > > > >> > > types
> > > > > > >> > > > were never used in the local sense there (although I may be
> > > > > wrong
> > > > > > >> again).
> > > > > > >> > > > Were we to decide that Arrow and parquet-mr should behave
> > > > > > >> differently in
> > > > > > >> > > > this aspect though, it may be tricky to convey this 
> > > > > > >> > > > distinction
> > > > > in
> > > > > > >> the
> > > > > > >> > > > specification. I would be interested in hearing your and 
> > > > > > >> > > > other
> > > > > > >> > > developers'
> > > > > > >> > > > opinions on this.
> > > > > > >> > > >
> > > > > > >> > > > Thanks,
> > > > > > >> > > >
> > > > > > >> > > > Zoltan
> > > > > > >> > > >
> > > > > > >> > > > On Tue, Jul 9, 2019 at 5:39 PM Wes McKinney <
> > > > > [email protected]>
> > > > > > >> wrote:
> > > > > > >> > > >
> > > > > > >> > > > > hi folks,
> > > > > > >> > > > >
> > > > > > >> > > > > We have just recently implemented the new LogicalType 
> > > > > > >> > > > > unions
> > > > > in
> > > > > > >> the
> > > > > > >> > > > > Parquet C++ library and we have run into a forward
> > > > > compatibility
> > > > > > >> > > > > problem with reader versions prior to this 
> > > > > > >> > > > > implementation.
> > > > > > >> > > > >
> > > > > > >> > > > > To recap the issue, prior to the introduction of 
> > > > > > >> > > > > LogicalType,
> > > > > the
> > > > > > >> > > > > Parquet format had no explicit notion of time zones or 
> > > > > > >> > > > > UTC
> > > > > > >> > > > > normalization. The new TimestampType provides a flag to
> > > > > indicate
> > > > > > >> > > > > UTC-normalization
> > > > > > >> > > > >
> > > > > > >> > > > > struct TimestampType {
> > > > > > >> > > > > 1: required bool isAdjustedToUTC
> > > > > > >> > > > > 2: required TimeUnit unit
> > > > > > >> > > > > }
> > > > > > >> > > > >
> > > > > > >> > > > > When using this new type, the ConvertedType field must 
> > > > > > >> > > > > also be
> > > > > > >> set for
> > > > > > >> > > > > forward compatibility (so that old readers can still
> > > > > understand
> > > > > > >> the
> > > > > > >> > > > > data), but parquet.thrift says
> > > > > > >> > > > >
> > > > > > >> > > > > // use ConvertedType TIMESTAMP_MICROS for
> > > > > > >> TIMESTAMP(isAdjustedToUTC =
> > > > > > >> > > > > true, unit = MICROS)
> > > > > > >> > > > > // use ConvertedType TIMESTAMP_MILLIS for
> > > > > > >> TIMESTAMP(isAdjustedToUTC =
> > > > > > >> > > > > true, unit = MILLIS)
> > > > > > >> > > > > 8: TimestampType TIMESTAMP
> > > > > > >> > > > >
> > > > > > >> > > > > In Apache Arrow, we have 2 varieties of timestamps:
> > > > > > >> > > > >
> > > > > > >> > > > > * Timestamp without time zone (no UTC normalization 
> > > > > > >> > > > > indicated)
> > > > > > >> > > > > * Timestamp with time zone (values UTC-normalized)
> > > > > > >> > > > >
> > > > > > >> > > > > Prior to the introduction of LogicalType, we would set 
> > > > > > >> > > > > either
> > > > > > >> > > > > TIMESTAMP_MILLIS or TIMESTAMP_MICROS unconditional on UTC
> > > > > > >> > > > > normalization. So when reading the data back, any notion 
> > > > > > >> > > > > of
> > > > > > >> having had
> > > > > > >> > > > > a time zone is lost (it could be stored in schema 
> > > > > > >> > > > > metadata if
> > > > > > >> > > > > desired).
> > > > > > >> > > > >
> > > > > > >> > > > > I believe that setting the TIMESTAMP_* ConvertedType 
> > > > > > >> > > > > _only_
> > > > > when
> > > > > > >> > > > > isAdjustedToUTC is true creates a forward compatibility 
> > > > > > >> > > > > break
> > > > > in
> > > > > > >> this
> > > > > > >> > > > > regard. This was reported to us shortly after releasing 
> > > > > > >> > > > > Apache
> > > > > > >> Arrow
> > > > > > >> > > > > 0.14.0:
> > > > > > >> > > > >
> > > > > > >> > > > > https://issues.apache.org/jira/browse/ARROW-5878
> > > > > > >> > > > >
> > > > > > >> > > > > We are discussing setting the ConvertedType 
> > > > > > >> > > > > unconditionally in
> > > > > > >> > > > >
> > > > > > >> > > > > https://github.com/apache/arrow/pull/4825
> > > > > > >> > > > >
> > > > > > >> > > > > This might need to be a setting that is toggled when 
> > > > > > >> > > > > data is
> > > > > > >> coming
> > > > > > >> > > > > from Arrow, but I wonder if the text in parquet.thrift 
> > > > > > >> > > > > is the
> > > > > > >> intended
> > > > > > >> > > > > forward compatibility interpretation, and if not should 
> > > > > > >> > > > > we
> > > > > amend.
> > > > > > >> > > > >
> > > > > > >> > > > > Thanks,
> > > > > > >> > > > > Wes
> > > > > > >> > > > >
> > > > > > >> > >
> > > > > > >>
> > > > > > >
> > > > >

Reply via email to