2

There is another question that is eleven years old with a similar title.

I have a pandas dataframe with a column of datetime.time values.

val    time
a      12:30:01.323
b      12:48:04.583
c      14:38:29.162

I want to convert the time column from UTC to EST.

I tried to do dataframe.tz_localize('utc').tz_convert('US/Eastern') but it gave me the following error: RangeIndex Object has no attribute tz_localize

Cauder
  • 2,157
  • 4
  • 30
  • 69

3 Answers3

4

tz_localize and tz_convert work on the index of the DataFrame. So you can do the following:

  1. convert the "time" to Timestamp format
  2. set the "time" column as index and use the conversion functions
  3. reset_index()
  4. keep only the time

Try:

dataframe["time"] = pd.to_datetime(dataframe["time"],format="%H:%M:%S.%f")
output = (dataframe.set_index("time")
                   .tz_localize("utc")
                   .tz_convert("US/Eastern")
                   .reset_index()
          )
output["time"] = output["time"].dt.time

>>> output
              time val
0  15:13:12.349211   a
1  15:13:13.435233   b
2  15:13:14.345233   c
not_speshal
  • 22,093
  • 2
  • 15
  • 30
  • Got it. It sounds like I can't use pytz.timezone(). Is that right? – Cauder Mar 11 '22 at 20:25
  • You can if you set the "time" column as the index before you do whatever you need to (i.e `tz_localize`) – not_speshal Mar 11 '22 at 20:26
  • I got an error that says "dataframe has no attribute dt" – Cauder Mar 17 '22 at 19:27
  • This code works fine with the provided `dataframe` sample. – tdy Mar 18 '22 at 02:36
  • "dataframe has no attribute dt" doesn't make sense because not_speshal's code does not have `dataframe.dt` or `output.dt` anywhere, only `output["time"].dt.time` (which tries to use `dt` on a series, not dataframe) – tdy Mar 18 '22 at 02:38
4

to_datetime accepts an argument utc (bool) which, when true, coerces the timestamp to utc.

to_datetime returns a DateTimeIndex, which has a method tz_convert. this method will convert tz-aware timestamps from one timezeone to another.

So, this transformation could be concisely written as

df = pd.DataFrame(
       [['a', '12:30:01.323'],
        ['b', '12:48:04.583'],
        ['c', '14:38:29.162']],
       columns=['val', 'time']
)
df['time'] = pd.to_datetime(df.time, utc=True, format='%H:%M:%S.%f') 
# convert string to timezone aware field ^^^
df['time'] = df.time.dt.tz_convert('EST').dt.time
# convert timezone, discarding the date part ^^^

This produces the following dataframe:

  val             time
0   a  07:30:01.323000
1   b  07:48:04.583000
2   c  09:38:29.162000

This could also be a 1-liner as below:

pd.to_datetime(df.time, utc=True, format='%H:%M:%S.%f').dt.tz_convert('EST').dt.time
Haleemur Ali
  • 26,718
  • 5
  • 61
  • 85
1
list_temp = []
for row in df['time_UTC']:
    list_temp.append(Timestamp(row, tz = 'UTC').tz_convert('US/Eastern'))
df['time_EST'] = list_temp
Henry Ecker
  • 34,399
  • 18
  • 41
  • 57