I'm trying to follow these answers and get the elapsed seconds since Jan 1st 1970 for each element in my array (my_times). I'm then using these values to find the time intervals between each consecutive time. Either approach I take seems to give the wrong answer for at least one pair of times.
Mark Byers answer
To get the seconds since Jan 1st 1970, he suggested to try:
time.mktime(my_time.timetuple())
However this does not seem to work for times "2017-11-05 01:46:00+00" and "2017-11-05 01:47:00+00".
When I run the below code, it says the values are separated by 3660.0 seconds instead of 60.0 seconds
from datetime import datetime
import time
my_time1 = datetime.strptime("2017-11-05 01:46:00+00", "%Y-%m-%d %H:%M:%S+%f")
my_time2 = datetime.strptime("2017-11-05 01:47:00+00", "%Y-%m-%d %H:%M:%S+%f")
time.mktime(my_time2.timetuple()) - time.mktime(my_time1.timetuple())
Andrzej Pronobis' answer
To get the seconds since Jan 1st 1970, he suggested to try:
my_time.timestamp()
This fixed the two earlier times however it no longer works for times "2017-11-05 01:59:00+00" and "2017-11-05 02:00:00+00". The same issue appears, I get 3660.0 seconds instead of 60.0 seconds
from datetime import datetime
my_time1 = datetime.strptime("2017-11-05 01:59:00+00", "%Y-%m-%d %H:%M:%S+%f")
my_time2 = datetime.strptime("2017-11-05 02:00:00+00", "%Y-%m-%d %H:%M:%S+%f")
my_time2.timestamp() - my_time1.timestamp()
I'd like to know if I'm doing anything wrong? Also is there a better way to find all consecutive time intervals when the datetime is given as a String?
Edit:
Thank you John, that fixed the problem. Oddly, changing the format from +%f to %z still ran into the same issue.
What did work was running sudo ln -sf /usr/share/zoneinfo/UTC /etc/localtime (changes my computer's time to UTC) and then evaluating all the times
This is a case of "garbage in, garbage out." Here:
datetime.strptime("2017-11-05 01:59:00+00", "%Y-%m-%d %H:%M:%S+%f")
You probably think that +00 on the end means "UTC time", but the %f format specifier means "fractional seconds."
In any case, you're apparently running on a system where the time zone is set to one with daylight saving time part of the year. 2 AM happens twice on the DST changeover date in November, so your code is working as written (it's ambiguous, basically).
Put another way: your issue is not that you're computing time deltas incorrectly. Your issue is that you are loading the times from strings incorrectly (or ambiguously).
Related
I want to store a representation of a moment in time (date and time) in a binary file with Python.
My choice, for now, is to write an 8-byte representation in Unix time (seconds from 1970-1-1, 0h00). For this, I'm using time, specifically gmtime, localtime and mktime.
How much is this universal? From time, I got:
The epoch is the point where the time starts, and is platform dependent. For Unix, the epoch is January 1, 1970, 00:00:00 (UTC). To find out what the epoch is on a given platform, look at time.gmtime(0).
When it says "to find out what the epoch is on a given platform" does it mean that different values may be produced by mktime depending on I'm using Debian, Windows, Mac or some other system?
Example:
>>> from time import localtime
>>> localtime(1649352786)
time.struct_time(tm_year=2022, tm_mon=4, tm_mday=7, tm_hour=14, tm_min=33, tm_sec=6, tm_wday=3, tm_yday=97, tm_isdst=0)
In other words, can localtime(1649352786) produce another date/time when run in different platforms?
If the answer is yes, how can I store "universal" and compact representation of a date/time? Using pickle.dumps in a time.struct_time object gives 53 bytes, which is way too much.
EDIT
From time.time() in Docs:
time.time() -> float
Return the time in seconds since the epoch as a floating point number. The specific date of the epoch and the handling of leap seconds is platform dependent. On Windows and most Unix systems, the epoch is January 1, 1970, 00:00:00 (UTC) and leap seconds are not counted towards the time in seconds since the epoch. This is commonly referred to as Unix time. To find out what the epoch is on a given platform, look at gmtime(0).
As the docs indicate, it could be platform dependent. What you could do is instead of reading it in with local time, you could use datetimes 'fromtimestamp' method that returns the local date from the corresponding POSIX timestamp (See docs).
example:
import datetime as dt
dt.datetime.fromtimestamp(1649352786, tz=dt.timezone.utc)
This will give you the datetime, from a UTC timestamp, in the UTC timezone. If you leave off the tz argument, you will get the platform local time for the timestamp (i.e it will add/subtract the offset for the local timezone). This may or may not be desirable, depending on your use case.
Edit based off additional comments from OP.
Since the concern is that time.time() may give you an non-standard timestamp, in the cases that the platform isn't using the Unix Epoch (i'm not aware of any common/ non-embedded platforms not using it), Then you should do as the documetnation says and use time.gmtime(0) to get what the epoch is, and then i would suggest converting it into a valid UNIX timestamp, by calculating the offset from the platform epoch and the UNIX epoch, and then storing all timestamps as UNIX timestamps, so that any other platform reading the stored date will understand.
Can someone explain to me, how to check whether a given time in "hh:mm" format falls in between a given range.
Say, given time is 10:30 A.M IST and my range is between 10:00 A.M and 11:00 A.M. So given time falls in the range.
Is there any package in python to do this in the easiest way?
Would be happy if anyone can help with this :)
The simple way is just to use datetime.time and compare in an if statement:
import datetime
hhmm = "10:30"
current_time = datetime.datetime.strptime(hhmm, "%H:%M").time()
if datetime.time(10) <= current_time <= datetime.time(11):
print("Time is between 10am and 11am")
else:
print("Time is not between 10am and 11am")
The timezone info is removed from the datetime object when .time() is called on it - if you input a literal time without a timezone, this isn't an issue, while if you do have a timezone then as long as the datetime is transformed (via .astimezone(zoneinfo.ZoneInfo('IST'))) into the timezone you want, you should just be able to compare with the literal 10am and 11am.
See also strptime() behavior, if your input format is more complicated than the above. It's possible to accommodate for AM/PM, as well as timezone.
so I'm trying to make a discord bot in python and make a command that will display all timezones that I choose, but the problem is that all of these timezones are around 7-8 hours ahead of normal.
import datetime
from pytz import timezone
localFormat = "%Y-%m-%d %H:%M:%S, %Z%z"
UTC=datetime.datetime.utcnow()
timezonelist = ["US/Eastern", "US/Central", "US/Mountain", "US/Pacific", "Etc/UTC", "Europe/Berlin", "Australia/North", "Australia/South", "Australia/West"]
for tz in timezonelist:
localDatetime = UTC.astimezone(timezone(tz))
x = localDatetime.strftime(localFormat)
print(tz + " " + x)
for example, Etc/UTC outputs 05:56:25 when it should output 22:56:25, other timezones follow this example, EST outputs 00:56:25 when it should be 17:56:25, or MST (where I am), 22:56:25 instead of 15:56:25. However, datetime.utcnow() returns the correct time.
I had done some research and it said that PYTZ uses the LMT but since all are forward by an amount I do not think it has to do with that.
utcnow() gives you a naive datetime object - it is not aware that it's in UTC although the numbers show UTC. If you convert to another time zone, Python will assume all naive datetime objects are local time. Your local time (MST) is UTC-7, that's why you're off by 7 hours.
The behaviour of utcnow is confusing and can lead to unexpected results - Stop using utcnow and utcfromtimestamp. Instead, use now() and set the tz explicitly:
UTC = datetime.datetime.now(timezone('UTC'))
This question already has answers here:
Python: strftime, gmtime not respecting timezone
(2 answers)
Closed 3 years ago.
I am a beginner in programming and I was messing around with the time module in python, as I recently got a raspberry pi and want to start doing some projects. I imported the time module, and just made a loop to print out the time every second. The code runs correctly, but the time given is not accurate to my location. Currently, it is the 14th and a Friday, around 9 pm, but it is returning the 15th a Saturday, with 0 hours and 10 minutes. Does anyone know how I can obtain the correct time?
I tried a couple of the different functions to receive the current time like .localtime() and .gmtime() but they're all the same.
import time
while(True):
thisTime = time.gmtime()
print(time.asctime(thisTime))
time.sleep(1)
Go ahead and check out this post, I think this is your solution:
Python get current time in right timezone
So assuming your computer's time is configured correctly, you could use this:
from datetime import datetime
naive_dt = datetime.now()
It's unclear what else you've tried, although the following should work:
localtime = time.localtime()
print(time.asctime(localtime))
↳ https://docs.python.org/3/library/time.html#time.localtime
I have a datetime object created from which I subtract 13 days as follow:
(date.today()-timedelta(days=13)).strftime('%Y-%m-%d')
The strangeness occurs when I execute the code at 6AM and 8:30AM. At 6AM, the resulting string is returned as (if today is 2012-02-29):
2012-02-15
which is 14 days before the current! However, running the same line at 8:30AM, the resulting string is returned as:
2012-02-16
Which then correct. So far I have not been able to figure out what the difference is between the small period of time. I use timezone naive datetime objects, if that is important. I would like to know what could cause this change in the resulting string date.
Many thanks.
EDIT: (based on eumiro's suggestion below)
datetime.datetime.now() returns:
>>> datetime.datetime(2012, 2, 29, 10, 46, 20, 659862)
And the timezone is Europe/Vienna on the server and in the django application that runs the line of code.
I also tried running a similar line to the one you suggested:
(pytz.timezone(settings.TIME_ZONE).localize(datetime.now(), is_dst=True) - \
timedelta(days=13)).strftime('%Y-%m-%d')
But with the same results... which is why I think I don't think it has much to do with timezones also. But at the same time not sure where else to look.
You live somewhere in America? This is the place where the timezones are around 6-8 hours behind the UTC and that's the time of UTC midnight.
What does datetime.datetime.now() return?
If you want to get the real local time, use this (replace "America/New_York" with your timezone):
from datetime import datetime, timedelta
import pytz
now = datetime.datetime.now(pytz.timezone("America/New_York"))
dt = (now - timedelta(days=13)).strftime('%Y-%m-%d')
and it should return the same correct values from midnight until midnight.
Unfortunately DST is poorly supported in Python.
Even pytz is not perfect, but can be made to work with hacks.
You have to decide what it means to subtract 2 days from 10th, 1p.m., either 2 calendar days or 48 hours or 172800 seconds.