How can i actually create a timestamp for the next 6 o'clock, whether that's today or tomorrow?
I tried something with datetime.datetime.today() and replace the day with +1 and hour = 6 but i couldnt convert it into a timestamp.
Need your help
To generate a timestamp for tomorrow at 6 AM, you can use something like the following. This creates a datetime object representing the current time, checks to see if the current hour is < 6 o'clock or not, creates a datetime object for the next 6 o'clock (including adding incrementing the day if necessary), and finally converts the datetime object into a timestamp
from datetime import datetime, timedelta
import time
# Get today's datetime
dtnow = datetime.now()
# Create datetime variable for 6 AM
dt6 = None
# If today's hour is < 6 AM
if dtnow.hour < 6:
# Create date object for today's year, month, day at 6 AM
dt6 = datetime(dtnow.year, dtnow.month, dtnow.day, 6, 0, 0, 0)
# If today is past 6 AM, increment date by 1 day
else:
# Get 1 day duration to add
day = timedelta(days=1)
# Generate tomorrow's datetime
tomorrow = dtnow + day
# Create new datetime object using tomorrow's year, month, day at 6 AM
dt6 = datetime(tomorrow.year, tomorrow.month, tomorrow.day, 6, 0, 0, 0)
# Create timestamp from datetime object
timestamp = time.mktime(dt6.timetuple())
print(timestamp)
To get the next 6 o'clock while handling timezones that observe Daylight saving time (DST) correctly:
from datetime import datetime, time, timedelta
import pytz # $ pip install pytz
from tzlocal import get_localzone # $ pip install tzlocal
DAY = timedelta(1)
local_timezone = get_localzone()
now = datetime.now(local_timezone)
naive_dt6 = datetime.combine(now, time(6))
while True:
try:
dt6 = local_timezone.localize(naive_dt6, is_dst=None)
except pytz.NonExistentTimeError: # no such time today
pass
except pytz.AmbiguousTimeError: # DST transition (or similar)
dst = local_timezone.localize(naive_dt6, is_dst=True)
std = local_timezone.localize(naive_dt6, is_dst=False)
if now < min(dst, std):
dt6 = min(dst, std)
break
elif now < max(dst, std):
dt6 = max(dst, std)
break
else:
if now < dt6:
break
naive_dt6 += DAY
Once you have an aware datetime object that represents the next 6 o'clock in the local timezone, it is easy to get the timestamp:
timestamp = dt6.timestamp() # in Python 3.3+
Or on older Python versions:
timestamp = (dt6 - datetime(1970, 1, 1, tzinfo=pytz.utc)).total_seconds()
See Converting datetime.date to UTC timestamp in Python.
The solution works even if any of the following happens:
python (e.g., time.mktime() calls) has no access to a historical timezone database on a given system (notably: Windows)—pytz provides a portable access to the tz database
there is a DST transition between now and the next X hour (where X is 6am in your case) or if the UTC offset for the local timezone has changed for any other reason—"naive datetime object + relativedelta" solution would fail silently to find the correct number of seconds but timezone-aware datetime objects could enable to find the right time difference
the nominal next X hour (today or tomorrow) does not exist or ambiguous in the local time zone (most often, it happens during DST transitions—every year in many timezones). Solutions using dateutil tzinfos or pytz-based solutions that use .localize() without is_dst=None would fail silently. The application should handle NonExistentTimeError and AmbiguousTimeError exceptions explicitly in this case
the current time is after the first time an ambiguous X hour happens in the local timezone but before the second time the X hour happens —"rrule + return min(localize(ndt, is_dst=True), localize(ndt, is_dst=False))" solution would fail silently. The min/max code in the AmbiguousTimeError clause above handles it correctly.
Related
How to add hours to a timestamp in python?
I have a timestamp in UTC, and I want to add hours to it. If I convert it to DateTime, it changes to local time. So, I want to add hours directly to the timestamp without converting to datetime.
import time
from datetime import datetime, timedelta
input = datetime(year=datetime.now().year, month=datetime.now().month, day=datetime.now().day)
today = datetime.now()
days = (today - input).days
d = datetime(year=today.year, month=today.month, day=today.day) - timedelta(seconds=time.timezone) - timedelta(days=days)
utc_midnight_timestamp = int(time.mktime(d.utctimetuple()))
Now I want to keep adding 1 hour to the utc_midnight_timestamp many times
for x in range(1,24):
#Need to keep incrementing utc_midnight_timestamp by x hours
#use timestamp later
How can I compute the time differential between two time zones in Python? That is, I don't want to compare TZ-aware datetime objects and get a timedelta; I want to compare two TimeZone objects and get an offset_hours. Nothing in the datetime library handles this, and neither does pytz.
Here is a solution using the Python library Pytz which solves the issue of ambiguous times at the end of daylight saving time.
from pytz import timezone
import pandas as pd
def tz_diff(date, tz1, tz2):
'''
Returns the difference in hours between timezone1 and timezone2
for a given date.
'''
date = pd.to_datetime(date)
return (tz1.localize(date) -
tz2.localize(date).astimezone(tz1))\
.seconds/3600
The examples below calculate the difference in hours between UTC and Australia time for the first of January and first of June respectively. Notice how daylight savings are taken into consideration.
utc = timezone('UTC')
aus = timezone('Australia/Sydney')
tz_diff('2017-01-01', utc, aus)
# 11.0
tz_diff('2017-06-01', utc, aus)
# 10.0
Thanks
The first thing you have to know is that the offset between two time zones depends not only on the time zones in question, but on the date you're asking about. For example, the dates on which Daylight Savings Time began and ended changed in the US in 2007. While fundamental time zone logistics change only infrequently in any single location, the rate of change globally is impossible to ignore. Therefore, you have to incorporate the date in question into your function.
Having completed the necessary preface, the actual function isn't too hard to write if you take advantage of the pendulum library. It should look something like this:
import pendulum
def tz_diff(home, away, on=None):
"""
Return the difference in hours between the away time zone and home.
`home` and `away` may be any values which pendulum parses as timezones.
However, recommended use is to specify the full formal name.
See https://gist.github.com/pamelafox/986163
As not all time zones are separated by an integer number of hours, this
function returns a float.
As time zones are political entities, their definitions can change over time.
This is complicated by the fact that daylight savings time does not start
and end on the same days uniformly across the globe. This means that there are
certain days of the year when the returned value between `Europe/Berlin` and
`America/New_York` is _not_ `6.0`.
By default, this function always assumes that you want the current
definition. If you prefer to specify, set `on` to the date of your choice.
It should be a `Pendulum` object.
This function returns the number of hours which must be added to the home time
in order to get the away time. For example,
```python
>>> tz_diff('Europe/Berlin', 'America/New_York')
-6.0
>>> tz_diff('Europe/Berlin', 'Asia/Kabul')
2.5
```
"""
if on is None:
on = pendulum.today()
diff = (on.set(tz=home) - on.set(tz=away)).total_hours()
# what about the diff from Tokyo to Honolulu? Right now the result is -19.0
# it should be 5.0; Honolulu is naturally east of Tokyo, just not so around
# the date line
if abs(diff) > 12.0:
if diff < 0.0:
diff += 24.0
else:
diff -= 24.0
return diff
As stated in the documentation, you may not get a stable result for this between any two given locations as you sweep across the days of the year. However, implementing a variant which chooses the median result over the days of the current year is an exercise left for the reader.
Here's another solution:
from datetime import datetime
from pytz import timezone
from dateutil.relativedelta import relativedelta
utcnow = timezone('utc').localize(datetime.utcnow()) # generic time
here = utcnow.astimezone(timezone('US/Eastern')).replace(tzinfo=None)
there = utcnow.astimezone(timezone('Asia/Ho_Chi_Minh')).replace(tzinfo=None)
offset = relativedelta(here, there)
offset.hours
Here what we're doing is converting a time to two different time zones. Then, we remove the time zone information so that when you calculate the difference between the two using relativedelta, we trick it into thinking that these are two different moments in time instead of the same moment in different time zones.
The above result will return -11, however this amount can change throughout the year since US/Eastern observes DST and Asia/Ho_Chi_Minh does not.
I created two functions to deal with timezone.
import datetime
import pytz
def diff_hours_tz(from_tz_name, to_tz_name, negative=False):
"""
Returns difference hours between timezones
res = diff_hours_tz("UTC", "Europe/Paris") : 2
"""
from_tz = pytz.timezone(from_tz_name)
to_tz = pytz.timezone(to_tz_name)
utc_dt = datetime.datetime.now(datetime.timezone.utc)
dt_from = dt_to = datetime.datetime.utcnow()
dt_from = from_tz.localize(dt_from)
dt_to = to_tz.localize(dt_to)
from_d = dt_from - utc_dt
if from_d.days < 0:
return diff_hours_tz(to_tz_name, from_tz_name, True)
dt_delta = dt_from - dt_to
negative_int = -1 if negative else 1
return int(dt_delta.seconds/3600)*negative_int
def dt_tz_to_tz(dt, from_tz_name, to_tz_name):
"""
Apply difference hours between timezones to a datetime object
dt_new = dt_tz_to_tz(datetime.datetime.now(), "UTC", "Europe/Paris")
"""
hours = diff_hours_tz(from_tz_name, to_tz_name)
return dt+datetime.timedelta(hours=hours)
# Usage example
res = diff_hours_tz("Europe/Paris", "America/New_York")
# Result : -6
res = diff_hours_tz("UTC", "Europe/Paris")
# Result : 2
now = datetime.datetime.now()
# Result : 2019-06-18 15:10:31.720105
dt_new = dt_tz_to_tz(now, "UTC", "Europe/Paris")
# Result : 2019-06-18 17:10:31.720105
dt_new = dt_tz_to_tz(now, "Europe/Paris", "America/New_York")
# Result : 2019-06-18 09:10:31.720105
dt_new = dt_tz_to_tz(now, "America/New_York", "Europe/Paris")
# Result : 2019-06-18 21:10:31.720105
I hope it will help !
Here is a code snippet to get the difference between UTC and US/Eastern, but it should work for any two timezones.
# The following algorithm will work no matter what is the local timezone of the server,
# but for the purposes of this discussion, let's assume that the local timezone is UTC.
local_timestamp = datetime.now()
# Assume that utc_timestamp == 2019-01-01 12:00.
utc_timestamp = pytz.utc.localize(local_timestamp)
# If it was 12:00 in New York, it would be 20:00 in UTC. So us_eastern_timestamp is a UTC
# timestamp with the value of 2019-01-01 20:00.
us_eastern_timestamp = timezone("US/Eastern").localize(local_timestamp).astimezone(pytz.utc)
# delta is a Python timedelta object representing the interval between the two timestamps,
# which, in our example, is -8 hours.
delta = utc_timestamp - us_eastern_timestamp
# In the last line, we convert the timedelta into an integer representing the number of
# hours.
print round(delta.total_seconds() / 60.0 / 60.0)
(tz_from.localize(date) - tz_to.localize(date)).seconds/3600.0
Where tz_from and tz_to are the starting and ending timezones. You must specify a particular date.
from datetime import datetime
from zoneinfo import ZoneInfo
dt = datetime.now() # 2020-09-13
tz0, tz1 = "Europe/Berlin", "US/Eastern" # +2 vs. -4 hours rel. to UTC
utcoff0, utcoff1 = dt.astimezone(ZoneInfo(tz0)).utcoffset(), dt.astimezone(ZoneInfo(tz1)).utcoffset()
print(f"hours offset between {tz0} -> {tz1} timezones: {(utcoff1-utcoff0).total_seconds()/3600}")
>>> hours offset between Europe/Berlin -> US/Eastern timezones: -6.0
a way to do this with Python 3.9's standard library.
I am attempting to compare the current time (A) to a certain time (B) on the current day. Subsequently, based on the result of that comparison, I want to return the POSIX time for a specific time, either tomorrow (C) or the day after tomorrow (D).
To illustrate, an example:
Suppose we have the current time (A) to be 12:00.
I want to compare that to (B), which is 20:00 today.
Since A < B, I want to return 13:00 tomorrow, formatted as a POSIX time.
Another example:
Now suppose the current time (A) is 21:00.
I still want to compare that to (B), which is 20:00 today.
Since A > B, I want to return 13:00 the day after tomorrow, again formatted as a POSIX time.
I've been trying to make this work using the timeand datetime libraries, but when using time I have a hard time finding B and when using datetime I can't find a way to return C and D as a POSIX time.
Have I correctly identified which libraries I should use and if so, what am I missing?
There are two questions:
Find whether you need "13:00 tomorrow" or "13:00 the day after tomorrow" depending on the current time relative to 20:00
Convert the result e.g., "13:00 tomorrow" to POSIX time
The first one is simple:
#!/usr/bin/env python
import datetime as DT
current_time = DT.datetime.now()
one_or_two = 1 if current_time.time() < DT.time(20, 0) else 2
target_date = current_time.date() + DT.timedelta(days=one_or_two)
target_time = DT.datetime.combine(target_date, DT.time(13, 0))
Note: 00:00 is considered to be less than 20:00. You might want to use time intervals instead e.g., 20:00-8:00 vs. 8:00-20:00, to find out whether the current time is in between.
The second question is essentially the same as How do I convert local time to UTC in Python? In the general case, there is no exact answer e.g., the same local time may occur twice or it may be missing completely—what answer to use depends on the specific application. See more details in my answer to python converting string in localtime to UTC epoch timestamp.
To get the correct result taking into account possible DST transitions or other changes in the local UTC offset between now and the target time (e.g., "the day after tomorrow"):
import pytz # $ pip install pytz
import tzlocal # $ pip install tzlocal
epoch = DT.datetime(1970,1,1, tzinfo=pytz.utc)
local_timezone = tzlocal.getlocalzone()
timezone_aware_dt = local_timezone.localize(target_time, is_dst=None)
posix_time = (timezone_aware_dt - epoch).total_seconds()
Note: is_dst=None is used to assert that the given local time exists and unambiguous e.g., there is no DST transitions at 13:00 in your local time.
If time.mktime() has access to a historical timezone database on your platform (or you just don't care about changes in the local utc offset) then you could find the "epoch" time using only stdlib:
import time
unix_time = time.mktime(target_time.timetuple())
You can read more details on when it fails and how to workaround it in Find if 24 hrs have passed between datetimes - Python.
Or more than you probably wanted to know about finding POSIX timestamp in Python can be found in Converting datetime.date to UTC timestamp in Python.
import datetime
A = datetime.datetime.now()
# A = A.replace(hour=21, minute=5) # This line simlulates "after 21:00"
B = A.replace(hour=20, minute=0, second=0, microsecond=0) # 20:00 today
if A < B:
print A.replace(hour=13, minute=0, second=0, microsecond=0) + datetime.timedelta(days=1) # 13:00 tomorrow
else:
print A.replace(hour=13, minute=0, second=0, microsecond=0) + datetime.timedelta(days=2) # 13:00 the day after
in Python 3 you can then return
X.timestamp()
in Python 2 you can use
def timestamp(dt):
return (dt - datetime.datetime(1970, 1, 1)).total_seconds()
timestamp(X)
How can I take this date string:
"2015-01-01"
and, assuming it is in a specific timezone (say, "US-Mountain"), convert it to a POSIX timestamp?
Like so:
magic_parse_function("2015-01-01", pytz.timezone("US-Mountain")) -> 1420095600
I've spent quite some time scouring the docs and this site, playing with aware/unaware datetime objects, and am hoping for a not-too-crazy solution. The following does not work, the last two lines of output are identical, and they should be 3600 seconds apart:
import datetime
import time
import pytz
timestring = "2015-01-01"
pacific = pytz.timezone("US/Pacific")
mountain = pytz.timezone("US/Mountain")
(year, month, day) = timestring.split('-')
year = int(year)
month = int(month)
day = int(day)
unaware = datetime.datetime(year, month, day, 0, 0, 0, 0)
# aware_pacific = pacific.localize(unaware)
# aware_mountain = mountain.localize(unaware)
aware_mountain = unaware.replace(tzinfo=mountain)
aware_pacific = unaware.replace(tzinfo=pacific)
print time.mktime(aware_pacific.timetuple())
print time.mktime(aware_mountain.timetuple())
There are three steps:
Convert the date string into a naive datetime object:
from datetime import datetime
dt = datetime(*map(int ,'2015-01-01'.split('-')))
Get a timezone-aware datetime object:
import pytz # $ pip install pytz
aware = pytz.timezone("US/Mountain").localize(dt, is_dst=None)
is_dst=None raises an exception for ambiguous or non-existing times. Here're more details about what is is_dst flag and why do you need it, see "Can I just always set is_dst=True?" section
Get POSIX timestamp:
timestamp = aware.timestamp()
.timestamp() is available since Python 3.3+. See multiple solutions for older Python versions.
I have two operations I want to perform, one the inverse of the other.
I have a UNIX timestamp at UTC, say for instance, 1425508527. From this I want to get the year, month, day etc. given a UTC offset. EG. what is the year/month/day/time in (UTC -6 hours)? The answer is March 4, 2015 at 16:35:27. Without providing an offset (or offset zero) the answer should be March 4, 2015 at 22:35:27.
Now I have the date at some location, along with the UTC offset. For instance March 4, 2015 at 16:35:27 and the offset (UTC -6 hours). The UNIX UTC timestamp I should get should be 1425508527.
I am able to almost do 2. (using python datetime library) like this:
import datetime.datetime as datetime
import time
import dateutil.tz as tz
utc_offset = 6
time.mktime(datetime(2015,3,4,16,35,27,
tzinfo=tz.tzoffset(None, utc_offset*60*60)).utctimetuple())
# => 1425486927
The problem with the above is that utc_offset has to be given the wrong sign. According to this map, utc_offset should be set to -6. Number 1. I've had no luck with. I don't need/want to deal with timezone information like daylight savings time. How do I implement this in Python?
If your system uses Unix time, which
does not count leap seconds, then the conversion can be done as follows:
Part 1: timestamp and offset to local date
import datetime as DT
import calendar
timestamp = 1425508527
offset = -6
date = DT.datetime(1970,1,1) + DT.timedelta(seconds=timestamp)
print(date)
# 2015-03-04 22:35:27
localdate = date + DT.timedelta(hours=offset)
print(localdate)
# 2015-03-04 16:35:27
Part 2: local date and offset to timestamp
utcdate = localdate - DT.timedelta(hours=offset)
assert date == utcdate
timetuple = utcdate.utctimetuple()
timestamp2 = calendar.timegm(timetuple)
print(timestamp2)
# 1425508527
assert timestamp == timestamp2