I am having issues converting a datetime string of this format "%d %b %Y %X %Z" to "%Y-%m-%dT%X%z". The timezone information is stripped out. For example:
>> import datetime
>> datetime_string_raw = "18 Nov 2022 08:57:04 EST"
>> datetime_utc = datetime.datetime.strptime(datetime_string_raw, "%d %b %Y %X %Z").strftime("%Y-%m-%dT%X%z")
>> print(datetime_utc)
2022-11-18T08:57:04
How can I get it to print the UTC offset? Why doesn't the %Z and %z have any effect? Thanks!
Using dateutil's parser and a definition which abbreviated names should resemble which time zone:
import datetime
import dateutil # pip install python-dateutil
tzinfos = {"EST": dateutil.tz.gettz("America/New_York"),
"EDT": dateutil.tz.gettz("America/New_York")}
datetime_string_raw = "18 Nov 2022 08:57:04 EST"
datetime_ny = dateutil.parser.parse(datetime_string_raw, tzinfos=tzinfos)
print(datetime_ny)
# 2022-11-18 08:57:04-05:00
datetime_utc = datetime_ny.astimezone(datetime.timezone.utc)
print(datetime_utc)
# 2022-11-18 13:57:04+00:00
You can do basically the same using only the standard library, but it requires some pre-processing of the date/time string. Ex:
import datetime
import zoneinfo # Python >= 3.9
def parse_dt_with_tz(dt_string: str, fmt: str, tzinfos: dict) -> datetime.datetime:
"""Parse date/time string with abbreviated time zone name to aware datetime."""
parts = dt_string.split(" ")
tz = tzinfos.get(parts[-1]) # last element is the tz name
if not tz:
raise ValueError(f"no entry found for {parts[-1]} in tzinfos")
return datetime.datetime.strptime(" ".join(parts[:-1]), fmt).replace(tzinfo=tz)
# usage
tzinfos = {"EST": zoneinfo.ZoneInfo("America/New_York"),
"EDT": zoneinfo.ZoneInfo("America/New_York")}
s = "18 Nov 2022 08:57:04 EST"
dt = parse_dt_with_tz(s, "%d %b %Y %H:%M:%S", tzinfos)
print(dt, repr(dt))
# 2022-11-18 08:57:04-05:00 datetime.datetime(2022, 11, 18, 8, 57, 4, tzinfo=zoneinfo.ZoneInfo(key='America/New_York'))
I'm trying to convert UTC time to Europe/Warsaw time. Warsaw time is now UTC + 2 hours. I don't know why I get result with time 30 minutes eariler. I'm parsing date from string similar to: 7:27:02 AM or 2:16:28 PM.
print(time_str) #6:47:46 PM
format = '%I:%M:%S %p'
time_obj = datetime.strptime(time_str, format)
utc_time = time_obj.replace(tzinfo=ZoneInfo('Etc/UTC'))
converted_time = utc_time.astimezone(tz=ZoneInfo('Europe/Warsaw')).time()
print(utc_time.time(), converted_time)
Output is
6:47:46 PM
18:47:46
20:11:46
While I expect:
6:47:46 PM
18:47:46
20:47:46
EDIT - this line fixed it:
time_obj = datetime.strptime(time_str, format).replace(year=2021, month=7, day=14)
I have a UTC timestamp, I want to check if at that time, it was daylight savings in London. How would I do this in Python?
You can use os.environ to set your timezone. Here is an example checking for DST in two different timezones:
import time, os
os.environ['TZ'] = 'Europe/London'
timestamp = os.path.getmtime(filename)
isdst = time.localtime(timestamp).tm_isdst > 0
In [973]: timestamp
Out[973]: 1571900789.0347116
In [965]: isdst
Out[965]: True
os.environ['TZ'] = 'USA/Colorado'
timestamp = os.path.getmtime(filename)
isdst = time.localtime(timestamp).tm_isdst > 0
In [968]: isdst
Out[968]: False
I have an API to which I have to send a epoch time start and end date. The only issue is that it will not accept microseconds.
I built a time function using datatime, however it calculates the microseconds. I tried the .replace(microsecond=0), but that just leaves the .0 on the Epoch, which my API complains about. I also tried exporting to strptime, but then my .timestamp function fails to parse it as a string.
timestart = datetime.now() - timedelta(hours = 24)
timeend = datetime.now()
params = {'start_date':timestart.timestamp(), 'end_date':timeend.timestamp()}
i would like to basically calculate current time in Epoch and time 24 hours ago (this does not have to be super precise) that I can pass to my API.
You can simply cast (Type Conversion) the values of timestart.timestamp() and timeend.timestamp(), which are floats, to ints, i.e.:
from datetime import datetime, timedelta
timestart = datetime.now() - timedelta(hours = 24)
timeend = datetime.now()
s = int(timestart.timestamp())
e = int(timeend.timestamp())
params = {'start_date':s, 'end_date':e}
print(params)
Output:
{'start_date': 1554121647, 'end_date': 1554208047}
Demo
I usually use time.mktime() for converting datetimes to epoch time:
from datetime import datetime, timedelta
import time
timestart = datetime.now() - timedelta(hours = 24)
timeend = datetime.now()
params = {
'start_date': int(time.mktime(timestart.timetuple())),
'end_date': int(time.mktime(timeend.timetuple()))
}
# Output
{'start_date': 1554123099, 'end_date': 1554209499}
An alternative solution to Pedro's one:
from datetime import datetime
from datetime import timedelta
timestart = (datetime.now() - timedelta(hours = 24)).strftime("%s")
timeend = datetime.now().strftime("%s")
params = {'start_date':timestart,
'end_date':timeend}
Output:
{'start_date': '1554124346', 'end_date': '1554210746'}
How to increment the day of a datetime?
for i in range(1, 35)
date = datetime.datetime(2003, 8, i)
print(date)
But I need pass through months and years correctly? Any ideas?
date = datetime.datetime(2003,8,1,12,4,5)
for i in range(5):
date += datetime.timedelta(days=1)
print(date)
Incrementing dates can be accomplished using timedelta objects:
import datetime
datetime.datetime.now() + datetime.timedelta(days=1)
Look up timedelta objects in the Python docs: http://docs.python.org/library/datetime.html
All of the current answers are wrong in some cases as they do not consider that timezones change their offset relative to UTC. So in some cases adding 24h is different from adding a calendar day.
Proposed solution
The following solution works for Samoa and keeps the local time constant.
def add_day(today):
"""
Add a day to the current day.
This takes care of historic offset changes and DST.
Parameters
----------
today : timezone-aware datetime object
Returns
-------
tomorrow : timezone-aware datetime object
"""
today_utc = today.astimezone(datetime.timezone.utc)
tz = today.tzinfo
tomorrow_utc = today_utc + datetime.timedelta(days=1)
tomorrow_utc_tz = tomorrow_utc.astimezone(tz)
tomorrow_utc_tz = tomorrow_utc_tz.replace(hour=today.hour,
minute=today.minute,
second=today.second)
return tomorrow_utc_tz
Tested Code
# core modules
import datetime
# 3rd party modules
import pytz
# add_day methods
def add_day(today):
"""
Add a day to the current day.
This takes care of historic offset changes and DST.
Parameters
----------
today : timezone-aware datetime object
Returns
-------
tomorrow : timezone-aware datetime object
"""
today_utc = today.astimezone(datetime.timezone.utc)
tz = today.tzinfo
tomorrow_utc = today_utc + datetime.timedelta(days=1)
tomorrow_utc_tz = tomorrow_utc.astimezone(tz)
tomorrow_utc_tz = tomorrow_utc_tz.replace(hour=today.hour,
minute=today.minute,
second=today.second)
return tomorrow_utc_tz
def add_day_datetime_timedelta_conversion(today):
# Correct for Samoa, but dst shift
today_utc = today.astimezone(datetime.timezone.utc)
tz = today.tzinfo
tomorrow_utc = today_utc + datetime.timedelta(days=1)
tomorrow_utc_tz = tomorrow_utc.astimezone(tz)
return tomorrow_utc_tz
def add_day_dateutil_relativedelta(today):
# WRONG!
from dateutil.relativedelta import relativedelta
return today + relativedelta(days=1)
def add_day_datetime_timedelta(today):
# WRONG!
return today + datetime.timedelta(days=1)
# Test cases
def test_samoa(add_day):
"""
Test if add_day properly increases the calendar day for Samoa.
Due to economic considerations, Samoa went from 2011-12-30 10:00-11:00
to 2011-12-30 10:00+13:00. Hence the country skipped 2011-12-30 in its
local time.
See https://stackoverflow.com/q/52084423/562769
A common wrong result here is 2011-12-30T23:59:00-10:00. This date never
happened in Samoa.
"""
tz = pytz.timezone('Pacific/Apia')
today_utc = datetime.datetime(2011, 12, 30, 9, 59,
tzinfo=datetime.timezone.utc)
today_tz = today_utc.astimezone(tz) # 2011-12-29T23:59:00-10:00
tomorrow = add_day(today_tz)
return tomorrow.isoformat() == '2011-12-31T23:59:00+14:00'
def test_dst(add_day):
"""Test if add_day properly increases the calendar day if DST happens."""
tz = pytz.timezone('Europe/Berlin')
today_utc = datetime.datetime(2018, 3, 25, 0, 59,
tzinfo=datetime.timezone.utc)
today_tz = today_utc.astimezone(tz) # 2018-03-25T01:59:00+01:00
tomorrow = add_day(today_tz)
return tomorrow.isoformat() == '2018-03-26T01:59:00+02:00'
to_test = [(add_day_dateutil_relativedelta, 'relativedelta'),
(add_day_datetime_timedelta, 'timedelta'),
(add_day_datetime_timedelta_conversion, 'timedelta+conversion'),
(add_day, 'timedelta+conversion+dst')]
print('{:<25}: {:>5} {:>5}'.format('Method', 'Samoa', 'DST'))
for method, name in to_test:
print('{:<25}: {:>5} {:>5}'
.format(name,
test_samoa(method),
test_dst(method)))
Test results
Method : Samoa DST
relativedelta : 0 0
timedelta : 0 0
timedelta+conversion : 1 0
timedelta+conversion+dst : 1 1
Here is another method to add days on date using dateutil's relativedelta.
from datetime import datetime
from dateutil.relativedelta import relativedelta
print 'Today: ',datetime.now().strftime('%d/%m/%Y %H:%M:%S')
date_after_month = datetime.now()+ relativedelta(day=1)
print 'After a Days:', date_after_month.strftime('%d/%m/%Y %H:%M:%S')
Output:
Today: 25/06/2015 20:41:44
After a Days: 01/06/2015 20:41:44
Most Simplest solution
from datetime import timedelta, datetime
date = datetime(2003,8,1,12,4,5)
for i in range(5):
date += timedelta(days=1)
print(date)
This was a straightforward solution for me:
from datetime import timedelta, datetime
today = datetime.today().strftime("%Y-%m-%d")
tomorrow = datetime.today() + timedelta(1)
You can also import timedelta so the code is cleaner.
from datetime import datetime, timedelta
date = datetime.now() + timedelta(seconds=[delta_value])
Then convert to date to string
date = date.strftime('%Y-%m-%d %H:%M:%S')
Python one liner is
date = (datetime.now() + timedelta(seconds=[delta_value])).strftime('%Y-%m-%d %H:%M:%S')
A short solution without libraries at all. :)
d = "8/16/18"
day_value = d[(d.find('/')+1):d.find('/18')]
tomorrow = f"{d[0:d.find('/')]}/{int(day_value)+1}{d[d.find('/18'):len(d)]}".format()
print(tomorrow)
# 8/17/18
Make sure that "string d" is actually in the form of %m/%d/%Y so that you won't have problems transitioning from one month to the next.