13

There are questions that addresses the same error TypeError: Timestamp subtraction must have the same timezones or no timezones but none faces the same issue as this one.

I have 2 UTC Timestamps that throw that error when substracted.

print(date, type(date), date.tzinfo)
>>> 2020-07-17 00:00:00+00:00 <class 'pandas._libs.tslibs.timestamps.Timestamp'> UTC
print(date2, type(date2), date2.tzinfo)
>>> 2020-04-06 00:00:00.000000001+00:00 <class 'pandas._libs.tslibs.timestamps.Timestamp'> UTC
date - date2
>>> TypeError: Timestamp subtraction must have the same timezones or no timezones

Edit: I'm using Python 3.6.9 and Pandas 1.0.1

room13
  • 883
  • 2
  • 10
  • 26

3 Answers3

11

Had same problem. If you're reading data using pandas read_csv, it uses <class 'pytz.UTC'>. So solution for me was to simply use same class everywhere.

Sample code generating error

from datetime import datetime, timedelta, timezone
import pandas as pd

now = datetime.now(tz=timezone.utc)
some_time_ago = now - timedelta(7)

print('Timezone info before reading_csv')
print(some_time_ago.tzinfo, type(some_time_ago.tzinfo))

time_passed = now - some_time_ago
print (time_passed)

df = pd.DataFrame([some_time_ago], columns=['date'])
df.to_csv('dates.csv', index=False)

df2 = pd.read_csv('dates.csv', parse_dates=['date'])
print('\nTimezone info after reading_csv')
print(df2.iloc[0,0].tzinfo, type(df2.iloc[0,0].tzinfo))

now = datetime.now(tz=timezone.utc)
some_time_ago = now - df2.iloc[0,0]
print(some_time_ago)
Timezone info before reading_csv
UTC <class 'datetime.timezone'>
7 days, 0:00:00

Timezone info after reading_csv
UTC <class 'pytz.UTC'>
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-23-b2815e32e8b7> in <module>
     19 
     20 now = datetime.now(tz=timezone.utc)
---> 21 some_time_ago = now - df2.iloc[0,0]
     22 print(some_time_ago)

pandas/_libs/tslibs/c_timestamp.pyx in pandas._libs.tslibs.c_timestamp._Timestamp.__sub__()

TypeError: Timestamp subtraction must have the same timezones or no timezones

Correct code with pytz

import pytz
from datetime import datetime, timedelta
import pandas as pd

now = datetime.now(tz=pytz.UTC)
some_time_ago = now - timedelta(7)

print('Timezone info before reading_csv')
print(some_time_ago.tzinfo, type(some_time_ago.tzinfo))

time_passed = now - some_time_ago
print (time_passed)

df = pd.DataFrame([some_time_ago], columns=['date'])
df.to_csv('dates.csv', index=False)

df2 = pd.read_csv('dates.csv', parse_dates=['date'])
print('\nTimezone info after reading_csv')
print(df2.iloc[0,0].tzinfo, type(df2.iloc[0,0].tzinfo))

now = datetime.now(tz=pytz.UTC)
some_time_ago = now - df2.iloc[0,0]
print(some_time_ago)
Timezone info before reading_csv
UTC <class 'pytz.UTC'>
7 days, 0:00:00

Timezone info after reading_csv
UTC <class 'pytz.UTC'>
7 days 00:00:00.024021
Maciałek
  • 264
  • 2
  • 8
6

After checking the timezone types: type(date.tzinfo) gives <class 'datetime.timezone'> and type(date2.tzinfo) gives <class 'pytz.UTC'> so acording of pandas source code they are not considered equal even even if they are both UTC.

So the solution was to make them have the same tzinfo type (either pytz or datitme.timezone)

This is an open issue in Github: https://github.com/pandas-dev/pandas/issues/32619

room13
  • 883
  • 2
  • 10
  • 26
1

You can use tz_localize() on the Timestamp if it is "tz-naive" and tz_convert on the datetime that has a timezone so as to equalize their timezones then do your subtraction operation:


import pytz

[date_without_tz].tz_localize(tz=pytz.UTC) - [date_with_tz].tz_convert(tz=pytz.UTC)

Lyrax
  • 331
  • 2
  • 6
  • In your example, aren't you converting the LHS from without tz to with tz, and the RHS, from with tz to without tz? So either one or the other method calls is required, but not both? Or do I have it wrong? Oh wait you are saying to put them both into a common tz e.g. UTC. Got it. Thanks! – jtlz2 Mar 22 '22 at 11:49
  • 1
    Yes, you figured it out. Converting both to common timezone. – Lyrax Mar 22 '22 at 19:28