How to create a datetime object with tzinfo set as 'UTC'? - python

I have a list of datetimes objects :
time_range = [datetime.datetime(2019, 7, 9, 0, 0, tzinfo=tzutc()),
datetime.datetime(2019, 7, 8, 0, 0, tzinfo=tzutc()),
datetime.datetime(2019, 7, 7, 0, 0, tzinfo=tzutc()),
datetime.datetime(2019, 7, 6, 0, 0, tzinfo=tzutc())
... ]
And I have an other datetime object :
time = datetime(2019, 7, 7)
I have to test if time is in time_range.
But each time I test :
time in time_range
I get the output False, because I don't have the tzinfo.
Here's what I've tried :
I tried to add the tzinfo :
time = datetime(2019, 7, 7, tzinfo=tzuct())
but I can't find where the tzutc() function is.
I also tried tu use pandas :
import pandas as pd
pd.to_datetime(str(time) + '+00:00')
I get the UTC :
Timestamp('2019-07-05 00:00:00+0000', tz='UTC')
But this is not a datetime.datetime object...
Do you have an idea how I could do ?
(Note : i'm compelled to use the form time in time_range, because of the rest of my program)

In datetime constructor, tzinfo parameter expects a type of timezone. It's not the clearest documentation. Try this:
from datetime import datetime, timezone
dt = datetime(2019, 7, 7, tzinfo=timezone.utc)

>>> from datetime import datetime, timezone
>>> time = datetime(2019, 7, 7, tzinfo=timezone.utc)
>>> print(time)
2019-07-07 00:00:00+00:00
>>> print(time.tzinfo)
UTC

After some research, I found an other solution, using pandas :
utc_time = pd.to_datetime(str(time) + '+00:00').to_pydatetime()
returns a datetime.datetime object :
datetime.datetime(2019, 7, 7, 0, 0, tzinfo=<UTC>)
However, to avoid importing pandas library, here's the solution I used :
from datetime import datetime, timezone
new_time = time.replace(tzinfo=timezone.utc)
new_time in time_range.
>>> True

Related

Why is only one date under DST influence?

I've been reading the pytz and datetime module documentation but I can't figure out why one date is under DST and the other is not.
import pytz
import datetime
mytz = pytz.timezone('America/New_York')
od = datetime.datetime(2021, 7, 1, 4, 0)
mytz.localize(od)
# Out: datetime.datetime(2021, 7, 1, 4, 0, tzinfo=<DstTzInfo 'America/New_York' EDT-1 day, 20:00:00 DST>)
mytz.localize(od).dst()
# Out: datetime.timedelta(0, 3600)
dt = datetime.datetime(2089, 7, 1, 4, 0)
mytz.localize(dt)
# Out: datetime.datetime(2089, 7, 1, 4, 0, tzinfo=<DstTzInfo 'America/New_York' EST-1 day, 19:00:00 STD>)
mytz.localize(dt).dst()
# Out: datetime.timedelta(0)
If you look at the source of the time zone rules, you find that they can have a keyword "max" specified that "is used to extend a rule’s application into the indefinite future" ref. For the US, you can find that here. Unless otherwise specified, DST just continues to be applied during the specified period of the year. But keep in mind that this does not mean that it will actually be the case in the future, since time zones are subject to political decisions.
As an addition to #balmy 's comment suggesting this is a deficiency of pytz, Python 3.9's zoneinfo gives the result to be expected from the above:
import datetime
from zoneinfo import ZoneInfo
od = datetime.datetime(2021, 7, 1, 4, 0, tzinfo=ZoneInfo('America/New_York'))
print(od.dst())
# 1:00:00
dt = datetime.datetime(2089, 7, 1, 4, 0, tzinfo=ZoneInfo('America/New_York'))
print(dt.dst())
# 1:00:00

Parse a list of numbers in datetime in Python Pandas

I have a dataframe of transportation data.
The datetime fields are logged in this format: [2020, 12, 10, 15, 0, 5, 18000000].
How do I parse these as datetime objects?
You can pass it with * to the datetime.datetime constructor and use any pandas function to apply this to every value in your pandas.Series.
>>> from datetime import datetime
>>> datetime(*[2020, 12, 10, 15, 0, 5, 18000])
datetime.datetime(2020, 12, 10, 15, 0, 5, 18000)
One additional moment: you will need to update microsecond field.
E.g.
from datetime import datetime
import pandas as pd
df = pd.DataFrame({"example": [[2020, 12, 10, 15, 0, 5, 18000000]]})
df.example = df.example.apply(lambda x: datetime(
*(v if i != len(x) - 1 else v // 1000 for i, v in enumerate(x))
))

Why is datetime being truncated in Pandas?

I would like to filter pandas using the time stamp. This works fine for all hours except 0. If I filter for dt.hour = 0, only the date is displayed and not the time. How can I have the time displayed too?
import datetime
df = pd.DataFrame({'datetime': [datetime.datetime(2005, 7, 14, 12, 30),
datetime.datetime(2005, 7, 14, 0, 0),
datetime.datetime(2005, 7, 14, 10, 30),
datetime.datetime(2005, 7, 14, 15, 30)]})
print(df[df['datetime'].dt.hour == 10])
print(df[df['datetime'].dt.hour == 0]
use strftime:
print(df[df['datetime'].dt.hour == 0].datetime.dt.strftime("%Y-%m-%d %H:%M:%S"))
The result is:
1 2005-07-14 00:00:00
Name: datetime, dtype: object

Datetime object from a string for 15 days frequency

I am trying to code a function called days15(). The function will be passed an argument called ‘myDateStr’. myDateStr is string representation of a date in the form 20170817 (that is YearMonthDay). The code in the function will create a datetime object from the string, it will then create a timedelta object with a length of 1 day. Then, it will use a list comprehension to produce a list of 15 datetime objects, starting with the date that is passed to the function
the function should return the following list.
[datetime.datetime(2017, 8, 17, 0, 0), datetime.datetime(2017, 8, 18, 0, 0), datetime.datetime(2017, 8, 19, 0, 0), datetime.datetime(2017, 8, 20, 0, 0), datetime.datetime(2017, 8, 21, 0, 0), datetime.datetime(2017, 8, 22, 0, 0), datetime.datetime(2017, 8, 23, 0, 0), datetime.datetime(2017, 8, 24, 0, 0), datetime.datetime(2017, 8, 25, 0, 0), datetime.datetime(2017, 8, 26, 0, 0), datetime.datetime(2017, 8, 27, 0, 0), datetime.datetime(2017, 8, 28, 0, 0), datetime.datetime(2017, 8, 29, 0, 0), datetime.datetime(2017, 8, 30, 0, 0), datetime.datetime(2017, 8, 31, 0, 0)]
I am stuck for the code. I have strted with the below.Please help. Thanks
from datetime import datetime, timedelta
myDateStr = '20170817'
def days15(myDateStr):
Pandas will help you in converting strings to datetime, so first you need to import it:
from datetime import datetime, timedelta
import pandas as pd
myDateStr = '20170817'
Then you can initialize an empty list that you'll later append:
datelist = []
And then you write a function:
def days15(myDateStr):
#converting to datetime
date = pd.to_datetime(myDateStr)
#loop to create 15 datetimes
for i in range(15):
newdate = date + timedelta(days=i)
#adding new dates to the list
datelist.append(newdate)
and then you can call your function and get a list of 15 datetimes:
days15(myDateStr)
As you said, there will be two steps to implement: firstly, convert the string date to a datetime object and secondly, iterate over the next 15 days using timedelta, with a list comprehension or a simple loop.
from datetime import datetime, timedelta
myDateStr = '20170817'
# Parse the string and return a datetime object
def getDateTime(date):
return datetime(int(date[:4]),int(date[4:6]),int(date[6:]))
# Iterate over the timedelta added to the starting date
def days15(myDateStr):
return [getDateTime(myDateStr) + timedelta(days=x) for x in range(15)]

How to get rrule.between() to only include start timestamp

How would I create an rrule that excludes only the end timestamp using dateutil? Would I have to create a custom function or is there a way to do it natively?
here is an example
rule = rrule.rrule(rule.HOURLY,tsstart=somedate,until=somedate_four_hours_later)
I want the output to EXCLUDE somedate_four_hours_later and only generate 4 timestamps, somedate, somedate+1 hour, etc.
One way to do this is to use an rruleset, which allows you to combine recurrence rules and specific dates as required. In this case, what you'd do is set the until date as an exdate (excluded date):
from dateutil import rrule
from datetime import datetime, timedelta
dtstart = datetime(2015, 1, 3, 12)
dtuntil = datetime(2015, 1, 3, 16)
rr = rrule.rrule(freq=rrule.HOURLY, dtstart=dtstart, until=dtuntil)
# Add your rrule to the ruleset, then exclude the until date from the rule set
rrset = rrule.rruleset()
rrset.rrule(rr)
l1 = list(rrset)
rrset.exdate(dtuntil)
l2 = list(rrset)
print(l1[-1]) # 2015-01-03 16:00:00
print(l2[-1]) # 2015-01-03 15:00:00
The rrule itself will include the until date, but the exdate will exclude it from the rruleset.
You can set the count:
In [1]: from dateutil import rrule
In [2]: from datetime import datetime, timedelta
In [3]: st = datetime(2016, 7, 5, 23, 30)
In [4]: rule = rrule.rrule(rrule.HOURLY, st, count=4)
In [5]: print(list(rule))
[datetime.datetime(2016, 7, 5, 23, 30), datetime.datetime(2016, 7, 6, 0, 30), datetime.datetime(2016, 7, 6, 1, 30), datetime.datetime(2016, 7, 6, 2, 30)]
Or use timedelta adding three hours to the start:
from datetime import datetime, timedelta
st = datetime(2016, 7, 5, 23, 30)
rule = rrule.rrule(rrule.HOURLY, st, until=(st + timedelta(hours=3)))

Categories

Resources