Related
In current part of system pendulum v1.4 is used, but with croniter it causing error described in https://github.com/sdispater/pendulum/issues/214
This works fine with datetime.datetime type and i still have to stay with pendulum v1.4.
So i am looking for solution how to efficiently to convert pendulum to datetime.datetime type ?
Already tried formatting pendulum as string and parsing using dateutil.parser.
Another take on this:
>>> from datetime import datetime
>>> import pendulum
>>> datetime.fromtimestamp(pendulum.now().timestamp(), pendulum.tz.UTC)
datetime.datetime(2021, 1, 12, 11, 41, 32, 387753, tzinfo=Timezone('UTC'))
Usually there should be no need to do this since pendulum's DateTime inherits from datetime.datetime. Any code working with stdlib's datetime's should work with pendulum's as well.
I couldn't find a Pendulum helper for this either. So, back to basics:
import datetime as dt
tz_info = dateutil.tz.gettz(zone_name)
pend_time = pendulum.datetime(...)
dt_time = dt.datetime(
pend_time.year,
pend_time.month,
pend_time.day,
pend_time.hour,
pend_time.minute,
pend_time.second,
pend_time.microsecond,
).astimezone(tz_info)
Note the use of dateutil. As of Python 3.6, the tzinfo documentation recommends dateutil.tz rather than pytz as an IANA time zone provider.
pendulum==1.4.0 objects have the protected _datetime member:
import pendulum
p = pendulum.now()
p._datetime
This will give you something like
datetime.datetime(2021, 5, 24, 12, 44, 11, 812937, tzinfo=<TimezoneInfo [America/New_York, EDT, -4:00:00, DST]>)
Another way is as follows: and works for pendulum==1.4.0 and more recent pendulum==2.1.2
import pendulum
from datetime import datetime
p = pendulum.now()
datetime_string = p.to_datetime_string()
datetime.fromisoformat(datetime_string)
which will give
datetime.datetime(2021, 5, 24, 12, 44, 11)
The following code works for me:
In [1]: import pendulum
In [2]: import datetime
In [3]: pdt = pendulum.now()
In [4]: datetime.datetime.fromisoformat(pdt.to_iso8601_string())
Out[4]: datetime.datetime(2022, 2, 22, 14, 29, 36, 812772,tzinfo=datetime.timezone(datetime.timedelta(seconds=28800)))
use arrow module
to convert pendulum to datetime
>>> arrow.get(datetime(2013, 5, 5), 'US/Pacific')
<Arrow [2013-05-05T00:00:00-07:00]>
example:
In [90]: import numpy as np
...: import pandas as pd
...: import pendulum
...: import arrow
...:
...: def pendulum_to_datetime(x):
...: return arrow.get(x, x.tz.name).datetime
In [91]: dates = [pendulum.datetime(2011, 1, 2, tz='Asia/Seoul'),
...: pendulum.datetime(2011, 1, 5, tz='Asia/Seoul'),
...: pendulum.datetime(2011, 1, 7, tz='Asia/Seoul')]
In [92]: dates
Out[92]:
[DateTime(2011, 1, 2, 0, 0, 0, tzinfo=Timezone('Asia/Seoul')),
DateTime(2011, 1, 5, 0, 0, 0, tzinfo=Timezone('Asia/Seoul')),
DateTime(2011, 1, 7, 0, 0, 0, tzinfo=Timezone('Asia/Seoul'))]
In [93]: dates2 = [pendulum_to_datetime(x) for x in dates]
In [94]: dates2
Out[94]:
[datetime.datetime(2011, 1, 2, 0, 0, tzinfo=tzfile('ROK')),
datetime.datetime(2011, 1, 5, 0, 0, tzinfo=tzfile('ROK')),
datetime.datetime(2011, 1, 7, 0, 0, tzinfo=tzfile('ROK'))]
In [95]: s1 = pd.Series(np.random.randn(3), index=dates2)
In [96]: s1
Out[96]:
2011-01-02 00:00:00+09:00 -0.359771
2011-01-05 00:00:00+09:00 -0.208608
2011-01-07 00:00:00+09:00 -0.051233
dtype: float64
In [97]: s1.index
Out[97]:
DatetimeIndex(['2011-01-02 00:00:00+09:00', '2011-01-05 00:00:00+09:00',
'2011-01-07 00:00:00+09:00'],
dtype='datetime64[ns, tzfile('ROK')]', freq=None)
In [98]: s2 = pd.Series(dates2)
In [99]: s2
Out[99]:
0 2011-01-02 00:00:00+09:00
1 2011-01-05 00:00:00+09:00
2 2011-01-07 00:00:00+09:00
dtype: datetime64[ns, tzfile('ROK')]
How do you get a valid timedelta instance when differencing datetimes with different timezones in Python? I'm finding the timedelta is always 0 if the timezones are different.
>>> from dateutil.parser import parse
>>> dt0=parse('2017-02-06 18:14:32-05:00')
>>> dt0
datetime.datetime(2017, 2, 6, 18, 14, 32, tzinfo=tzoffset(None, -18000))
>>> dt1=parse('2017-02-06 23:14:32+00:00')
>>> dt1
datetime.datetime(2017, 2, 6, 23, 02, 12, tzinfo=tzutc())
>>> (dt1-dt0).total_seconds()
0.0
This doesn't make any sense to me. I would have thought that Python's datetime class would be smart enough to normalize both values to UTC internally, and then return a timedelta based on those values. Or throw an exception. Instead it returns 0, implying both datetimes are equal, which clearly they're not. What am I doing wrong here?
You are confused about what the timezone means; the two times you gave are identical, so of course their difference is zero. I can duplicate your results, except that I don't have the discrepancy between the second string and second datetime that you have:
>>> from dateutil.parser import parse
>>> dt0=parse('2017-02-06 18:14:32-05:00')
>>> dt0
datetime.datetime(2017, 2, 6, 18, 14, 32, tzinfo=tzoffset(None, -18000))
>>> dt1=parse('2017-02-06 23:14:32+00:00')
>>> dt1
datetime.datetime(2017, 2, 6, 23, 14, 32, tzinfo=tzutc())
>>> (dt1-dt0).total_seconds()
0.0
But watch what happens when I convert dt0 to UTC. The time gets adjusted by the 5 hour timezone difference, and it becomes identical to the second.
>>> dt0.astimezone(dt1.tzinfo)
datetime.datetime(2017, 2, 6, 23, 14, 32, tzinfo=tzutc())
I am attempting to build a program to handle alerts. I want it to be able to handle specific dates like 8/23/2015 7:00 and relative dates like 5 days and 7 hours from now. specific dates are fine but for relative dates if I try and just add 5 days and 7 hours to the date time it can overflow the values intended for that spot
import datetime
dt = datetime.datetime.now()
dayslater = 5
hourslater = 7
minuteslater = 30
alarmTime = datetime.datetime(dt.year, dt.month, dt.day + dayslater,
dt.hour + hourslater,
dt.minute + minuteslater, 0,0)
this is fine sometimes but if dayslater was 40 days it would overflow the value. I did set up a simple
if hours >= 24:
hours -= 24
days++
however this won't work for overflowing months whose length in days isn't consistent.
Don't. Dates are hard, and it's very easy to get it wrong.
Instead, use timedelta:
In [1]: from datetime import datetime, timedelta
In [2]: dt = datetime.now()
In [3]: dt
Out[3]: datetime.datetime(2015, 7, 23, 15, 2, 55, 836914)
In [4]: alarmTime = dt + timedelta(days=5, hours=7, minutes=30)
In [5]: alarmTime
Out[5]: datetime.datetime(2015, 7, 28, 22, 32, 55, 836914)
Use a datetime.timedelta() object and leave calculations to the datetime library:
import datetime
delta = datetime.timedelta(days=dayslater, hours=hourslater, minutes=minuteslater)
alarmTime = datetime.datetime.now() + delta
Demo:
>>> import datetime
>>> dt = datetime.datetime.now()
>>> dayslater = 5
>>> hourslater = 7
>>> minuteslater = 30
>>> delta = datetime.timedelta(days=dayslater, hours=hourslater, minutes=minuteslater)
>>> delta
datetime.timedelta(5, 27000)
>>> dt
datetime.datetime(2015, 7, 23, 21, 4, 59, 987926)
>>> dt + delta
datetime.datetime(2015, 7, 29, 4, 34, 59, 987926)
Note how the hours carried over to the next day (from 21:04 to 04:34), and thus the date went from the 23rd to the 29th. I did not have to worry about 'overflow' here.
This continues to work at month boundaries, at year boundaries, and in leap years, with February 29th:
>>> datetime.datetime(2015, 7, 26, 22, 42) + delta
datetime.datetime(2015, 8, 1, 6, 12)
>>> datetime.datetime(2015, 12, 26, 22, 42) + delta
datetime.datetime(2016, 1, 1, 6, 12)
>>> datetime.datetime(2016, 2, 23, 22, 42) + delta
datetime.datetime(2016, 2, 29, 6, 12)
I've got a column of timestamps (in ms) in a pandas DataFrame. From the timestamps, I'm trying to derive the hour, minute, day of week, and month of the timestamp in separate columns.
I've tried using the apply function across the column, but to no avail. So, I took a very naive (but not very concise) approach to create these columns:
import pandas
import datetime
df=pd.DataFrame( {'time':[1401811621559, 1402673694105, 1402673749561, 1401811615479, 1402673708254], 'person':['Harry', 'Ann', 'Sue', 'Jeremy', 'Anne']})
df['time'] = pandas.to_datetime(df.time, unit='ms')
days = []
tod = []
month = []
minutes = []
for row in df['time']:
days.append(row.strftime('%w'))
tod.append(row.strftime('%H'))
month.append(row.strftime('%m'))
minutes.append(row.strftime('%M'))
##
df['dayOfWeek'] = days
df['timeOfDay'] = tod
df['month'] = month
df['minutes'] = minutes
Is there a way to do this that is more like this?
df['dayOfWeek'] = df['time'].apply(strftime('%w'),axis = 1)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'strftime' is not defined
At the moment you have to wrap the column in a DatetimeIndex:
In [11]: dti = pd.DatetimeIndex(df['time'])
In [12]: dti.dayofweek
Out[12]: array([1, 4, 4, 1, 4])
In [13]: dti.time
Out[13]:
array([datetime.time(16, 7, 1, 559000), datetime.time(15, 34, 54, 105000),
datetime.time(15, 35, 49, 561000), datetime.time(16, 6, 55, 479000),
datetime.time(15, 35, 8, 254000)], dtype=object)
In [14]: dti.month
Out[14]: array([6, 6, 6, 6, 6])
In [15]: dti.minute
Out[15]: array([ 7, 34, 35, 6, 35])
etc.
See this issue for making these methods directly available from a datetime series.
You might also make it a lambda function:
df['dayOfWeek2'] = df.time.apply(lambda x:x.strftime('%w'))
Now typing
df.dayOfWeek2 == df.dayOfWeek
yields
0 True
1 True
2 True
3 True
4 True
dtype: bool
Yes there is, modifying your code slightly...
def timeGroups(row):
row['days'] = row['time'].strftime('%w'))
#do the same thing for month,seconds,etc.
return row
df['dayOfWeek'] = df['time'].apply(timeGroups,axis = 1)
I am having a strange issue in converting the following time from eastern to UTC/GMT. Can someone advise?
>>> import datetime
>>> import pytz
>>>
>>> ept_time = datetime.datetime(2014,03,21,7) # March 21st at 7am
>>> ept_time = ept_time.replace(tzinfo=pytz.timezone('US/Eastern'))
>>> print ept_time
2014-03-21 07:00:00-05:00
>>>
>>> gmt_time = pytz.utc.normalize(ept_time)
>>> print gmt_time
2014-03-21 12:00:00+00:00
>>>
However, according to Wolfram Alpha, the results should be 11am, not 12.
>>> gmt = pytz.timezone('GMT')
>>> eastern = pytz.timezone('US/Eastern')
>>> d = datetime.datetime(2014,03,21,7)
>>> dateeastern = eastern.localize(d)
>>> dateeastern
datetime.datetime(2014, 3, 21, 7, 0, tzinfo=<DstTzInfo 'US/Eastern' EDT-1 day, 20:00:00 DST>)
>>> dategmt = dateeastern.astimezone(gmt)
>>> dategmt
datetime.datetime(2014, 3, 21, 11, 0, tzinfo=<StaticTzInfo 'GMT'>)
Replace GMT with UTC:
>>> eastern = pytz.timezone('US/Eastern')
>>> d = datetime.datetime(2014,03,21,7)
>>> dateeastern = eastern.localize(d)
>>> dateeastern
datetime.datetime(2014, 3, 21, 7, 0, tzinfo=<DstTzInfo 'US/Eastern' EDT-1 day, 20:00:00 DST>)
>>> dateutc = dateeastern.astimezone(pytz.utc)
>>> dateutc
datetime.datetime(2014, 3, 21, 11, 0, tzinfo=<UTC>)
Ref: How to convert GMT time to EST time using python