86601


freq='D'のDateTimeIndexで、ニューヨーク時刻の2022/02/07を92日前にずらすとAmbiguousTimeErrorが発生します。

freq属性をNoneにすればエラーを回避できることが確認できましたが、現在の振る舞い/仕様が不可解で納得できずにいます。  
タイムゾーンを変換するときに、夏時間によるあいまいさが発生するのは理解でできたのですが、freq属性の有無で振る舞いが変わることが理解できません。  
この振る舞いは仕様（期待どおりの振る舞い）なのでしょうか？  
もし仕様だとしたら、それを裏付ける背景/理由などがご存じでしょうか？

Windows10, Python 3.9.1, Pandas 1.4.1 で100%再現しました。

[code]

    import platform
    import pandas as pd
    print(f'- Python:[{platform.python_version()}], Pandas:[{pd.__version__}]')
    
    datetime_index = pd.DatetimeIndex([pd.Timestamp('2022-02-07',tz='America/New_York')], freq='D')
    # datetime_index.freq = None # <---この行を実行するとエラー回避できた
    print('入力:', datetime_index)
    
    datetime_index = datetime_index.shift(periods=-92, freq='D')
    print('出力:', datetime_index)
    
[/code]

[![画像の説明をここに入力](https://i.stack.imgur.com/J7lzv.png)](https://i.stack.imgur.com/J7lzv.png)


CC BY-SA 4.0
2022-02-27T13:44:17.000
86600
2022-02-27T23:42:03.297
2022-02-27T16:16:38.883
3060
35267
question
python python3 pandas
awareなDataTimeIndexのshiftによる、不可解なAmbiguousTimeErrorについて


> この振る舞いは仕様（期待どおりの振る舞い）なのでしょうか？

ソースコードの通りに動作しているので仕様と言えるのでしょう、おそらく。。。  
※ 本来であれば `shift` メソッドに `ceil` や `floor` メソッドと同様に `ambiguous`
キーワードが用意されているとよいのですけれども。

最初に、`pandas.core.indexes.datetimelike.DatetimeIndexOpsMixin.shift`
メソッドのソースコードは以下になります。

[pandas/datetimelike.py at 1.4.x · pandas-
dev/pandas](https://github.com/pandas-
dev/pandas/blob/1.4.x/pandas/core/indexes/datetimelike.py#L356)

[code]

    def shift(self: _T, periods: int = 1, freq=None) -> _T:
                      :
    
        arr = self._data.view()
        arr._freq = self.freq
        result = arr._time_shift(periods, freq=freq)
        return type(self)._simple_new(result, name=self.name)
    
[/code]

ここで、`pandas.core.arrays.datetimelike.DatetimeLikeArrayMixin._time_shift`
を呼び出しています。

[pandas/datetimelike.py at 1.4.x · pandas-
dev/pandas](https://github.com/pandas-
dev/pandas/blob/1.4.x/pandas/core/arrays/datetimelike.py#L1230)

[code]

    def _time_shift(
            self: DatetimeLikeArrayT, periods: int, freq=None
    ) -> DatetimeLikeArrayT:
                      :
    
        if freq is not None and freq != self.freq:
            if isinstance(freq, str):
                freq = to_offset(freq)
            offset = periods * freq
            return self + offset
                      :
    
    
[/code]

今回の場合、`freq` は `shift` の parameter で `-92` です。そして、

[code]

        datetime_index.freq = None
    
[/code]

を実行した場合、`self.freq` は `None` になります。つまり、この `if` statement が成立して(`True`)、

[code]

    >>> datetime_index + (-92) * pd._libs.tslibs.to_offset('D')
    DatetimeIndex(['2021-11-07 01:00:00-04:00'], dtype='datetime64[ns, America/New_York]', freq=None)
    
[/code]

が戻される事になります(DST は考慮されません)。


CC BY-SA 4.0
2022-02-27T18:04:33.677
86601
2022-02-27T18:04:33.677
47127
86600
answer


**freq属性の有無** よりも **freq属性が'D'である** ことと、 **時刻を指定していないので 00:00:00 を指定したと見做される**
ことの組み合わせが原因と思われます。

[DateOffset objects - Time series / date
functionality](https://pandas.pydata.org/pandas-
docs/stable/user_guide/timeseries.html#dateoffset-objects)  
pandasの上記説明に書かれている`'D'`より細かい単位の`'H'`,`'T'`,`'S'`,`'L'`,`'U'`,`'N'`を`freq=`に指定するとエラーは発生しません。

また`freq='D'`のままで`pd.Timestamp('2022-02-07',tz='America/New_York')`の`'2022-02-07'`の部分に午前2時以後の時刻を指定して`'2022-02-07
02:00'`や`'2022-02-07 23:59:59.999999999'`にするとエラーは発生しません。  
しかし時刻部分に`00:00`から`01:59:59.999999999`までを指定していると同様のエラーになります。

こちらの記事で、`'Europe/Berlin'`のタイムゾーンだと`02:00`から`02:59:59.999999999`までが同様に曖昧な時間として扱われるようです。  
[Why do I get 'Cannot infer dst time from '2017-10-29 02:04:15', try using the
'ambiguous' argument?](https://stackoverflow.com/q/51872791/9014308)

この辺のIssueが関連してそうで修正されているケースもあるようですね。  
[Fix naive-datetime timezone conversion when marshaling dataframes
#1061](https://github.com/streamlit/streamlit/issues/1061)  
[Fix datetime timezone handling in data frames
#2784](https://github.com/streamlit/streamlit/pull/2784)  
[BUG: round() on tz-aware DateTimeIndex (spanning DST switch) throws
AmbiguousTimeError as if tz-unaware #37485](https://github.com/pandas-
dev/pandas/issues/37485)  
[BUG: Timestamp.floor() method not able to handle DST change in local time
#44287](https://github.com/pandas-dev/pandas/issues/44287)

だからまだ修正しきれていないバグの可能性もありそうです。  
Issuesを検索して同様の物が無ければIssueを発行してみてはどうでしょう？


CC BY-SA 4.0
2022-02-27T23:42:03.297
86603
2022-02-27T23:42:03.297
26370
86600
answer