Python strftime clock - python

I am trying to write a countdown clock script. I want to use a set date in the future and have it count down in a nice readable format. Hours, Min, Sec. I am going to print to a 16x2 lCD display. The problem I'm having is trying to take the output of the difference between dates into a nice format. I have attached what I have so far. I receive the error:
AttributeError: 'datetime.timedelta' object has no attribute 'strftime'
This is my code:
from datetime import datetime
from time import strftime
deploy = datetime(2015, 3, 21, 0, 0)
mydate = datetime.now() - deploy
print (mydate.strftime("%b %d %H:%M:%S"))
I know how to print to my LCD and create a loop, just need help with this part.

There are two issues:
the time difference may be incorrect if you use local time represented as a naive datetime object if the corresponding local times have different utc offsets e.g., around a DST transition
the difference is timedelta object that has no strftime() method
To fix it, convert deploy from local timezone to UTC:
#!/usr/bin/env python
import time
from datetime import datetime, timedelta
deploy = datetime(2015, 3, 21, 0, 0) # assume local time
timestamp = time.mktime(deploy.timetuple()) # may fail, see the link below
deploy_utc = datetime.utcfromtimestamp(timestamp)
elapsed = deploy_utc - datetime.utcnow() # `deploy` is in the future
where elapsed is the elapsed time not counting leap seconds (such as 2015-07-01 00:59:60 BST+0100).
More details on when time.mktime() may fail see at Find if 24 hrs have passed between datetimes - Python.
To convert timedelta to string, you could use str() function:
print(elapsed) # print full timedelta
# remove microseconds
trunc_micros = timedelta(days=elapsed.days, seconds=elapsed.seconds)
print(trunc_micros) # -> 20 days, 13:44:14 <- 17 chars
# remove comma
print(str(trunc_micros).replace(',', ''))
# -> 20 days 13:44:14 <- 16 chars
If you want a different format then convert to hours, minutes, second using divmod() function:
seconds = elapsed.days*86400 + elapsed.seconds # drop microseconds
minutes, seconds = divmod(seconds, 60)
hours, minutes = divmod(minutes, 60)
print("{hours:02d}:{minutes:02d}:{seconds:02d}".format(**vars()))
# -> 493:44:14

Related

Converting millisecond to timestamp

1634515205001 converted to date & timer is : Mon Oct 18 2021 00:00:05
I attempt to convert 1634515205001 to date and time using :
import datetime
dt1 = datetime.datetime.strptime(
str(datetime.datetime.fromtimestamp(1634515205001 / 1000)),
"%Y-%m-%d %H:%M:%S.%f").strftime(
'%Y-%m-%dT%H:%M:%SZ')
print('dt1' , dt1)
which prints :
dt1 2021-10-18T01:00:05Z
Why is a division by 1000 (1634515205001 / 1000) required ? Using :
dt1 = datetime.datetime.strptime(
str(datetime.datetime.fromtimestamp(1634515205001)),
"%Y-%m-%d %H:%M:%S.%f").strftime(
'%Y-%m-%dT%H:%M:%SZ')
print('dt1', dt1)
renders :
str(datetime.datetime.fromtimestamp(1634515205001)),
OSError: [Errno 22] Invalid argument
Does fromtimestamp not accept millisecond as parameter ?
The datetime.fromtimestamp() function converts time in seconds (not millseconds) so epoch times in milliseconds need to be converted to seconds (divide by 1000).
This call is trying to compute 1634515205001 seconds since 1-Jan-1970 which is year 53765, and raises an exception.
dt = datetime.fromtimestamp(1634515205001)
Can get the number of expected digits for fromtimestamp() for the current time by calling time.time() to get the time in seconds for the current time.
print(time.time())
Output:
1649365827.417279 <= 10 digits before the decimal place
Time zones
The function fromtimestamp() is timezone aware so if the timezone argument is not provided then date time is converted to the local time zone. If the timezone is not specified and the timestamp time zone is different than the local time zone then the converted date time will be computed incorrectly. Below the local time zone is UTC-4.
dt = datetime.fromtimestamp(1634515205.001, tz=timezone.utc)
print(dt) # => 2021-10-18 00:00:05.001000+00:00
dt = datetime.fromtimestamp(1634515205.001)
print(dt) # => 2021-10-17 20:00:05.001000
Warning: Because naive datetime objects are treated by many datetime methods as
local times, it is preferred to use aware datetimes to represent times
in UTC. As such, the recommended way to create an object representing
a specific timestamp in UTC is by calling
datetime.fromtimestamp(timestamp, tz=timezone.utc).
To answer your question, yes, Python takes seconds instead of milliseconds when computing the dates.
From the documentation, datetime.datetime.fromtimestamp function definition says:
Return the local date corresponding to the POSIX timestamp, such as is returned by time.time().
The POSIX timestamp is the number of seconds that have elapsed since the 1st of January from 1970 (UTC).
So yes, fromtimestamp does not accept milliseconds, since POSIX timestamps are defined as seconds
If you are working with milliseconds, you have also the alternative to use something like:
datetime = datetime(1970, 1, 1) + timedelta(milliseconds=1634515205001)

how to convert datetime-like string into milliseconds

I have a user-defined function (return_times) that takes json file and returns two datetime-like strings.
time_1, time_2= return_times("file.json")
print(time_1, time_2) # outputs: 00:00:11.352 00:01:51.936
By datetime-like string I mean 00:00:11.352 which suits '%H:%M:%S.%f' formatting. However, when I try to convert them into milliseconds, I get negative values.
from datetime import datetime
dt_obj_1 = datetime.strptime(time_1, '%H:%M:%S.%f')
start_ms = dt_obj_1.timestamp() * 1000
dt_obj_2 = datetime.strptime(time_2, '%H:%M:%S.%f')
end_ms = dt_obj_2.timestamp() * 1000
print(start_ms, end_ms ) # outputs: -2209019260648.0 -2209019160064.0
If I success I would like to trim a video with the following command:
from moviepy.video.io.ffmpeg_tools import ffmpeg_extract_subclip
ffmpeg_extract_subclip("long_video.mp4", start_ms, end_ms, targetname="video_trimmed.mp4"), so just delete ` * 1000` part.
Note that ffmpeg_extract_subclip requires its t1 and t2 parameters to be in seconds, not in milliseconds as I initially thought.
Because of those negative integers I am not able to successfully run the trimming process.
I searched the web that mainly discusses several formats for the year, month and day, but not '%H:%M:%S.%f'.
What may I be overlooking?
What may I be overlooking?
time.strptime docs
The default values used to fill in any missing data when more accurate
values cannot be inferred are (1900, 1, 1, 0, 0, 0, 0, 1, -1).
whilst start of epoch is 1970. You might get what you want by computing delta between what you parsed and default strptime as follows:
import datetime
time1 = "00:00:11.352"
delta = datetime.datetime.strptime(time1, "%H:%M:%S.%f") - datetime.datetime.strptime("", "")
time_s = delta.total_seconds()
print(time_s)
output
11.352
You need to add the year date (year, month, day) to datetime, else this will default to 1 January 1900.
What you do is this:
from datetime import datetime
s = "00:00:11.352"
f = '%H:%M:%S.%f'
datetime.strptime(s, f) # datetime.datetime(1900, 1, 1, 0, 0, 11, 352000)
One way to do this is to append the date-string to the time-string you receive from return_times
From https://stackoverflow.com/a/59200108/2681662
The year 1900 was before the beginning of the UNIX epoch, which
was in 1970, so the number of seconds returned by timestamp must be
negative.
What to do?
It's better to use a time object instead of a datetime object.
from datetime import time
time_1 = "00:00:11.352"
hours, minutes, seconds = time_1.split(":")
print(time(hour=int(hours), minute=int(minutes), second=int(float(seconds)),
microsecond=int(float(seconds) % 1 * 1000000)))
You can split the time string into hours, minutes, seconds and miliseconds and with some simple math calculations, you get the whole time in miliseconds

How to define a difference in time in seconds between a timestamp saved as a string and a current UTC timestamp

I am testing the difference between an actual UTC time and timestamp when my object was saved in a table (UTC). It must be not more than 60 seconds.
Example of timestamp_from_table (string from my site): 2021-02-05 13:51:52
After researching for options to make this, I came to this approach:
timestamp_from_table = driver.find_element_by_css_selector("my_locator").text
current_time = time.strftime('%Y-%m-%d %H:%M:%S', time.gmtime()) # current time converted to string
current_time_truncated = datetime.strptime(current_time, "%Y-%m-%d %H:%M:%S") # cutting milliseconds
date_time_obj = datetime.strptime(timestamp_from_table, '%Y-%m-%d %H:%M:%S') # converting string timestamp to a datetime object
time_difference = current_time_truncated - date_time_obj
result = time_difference.seconds # datetime.timedelta represented in seconds
assert result in range(1, 60), error()
It works just fine, but probably there is a shorter way to compare a difference between a timestamp saved as string and actual utc timestamp. Thanks for any advice.
I'm reading between the lines a bit, but it sounds like at a high level your goal is to calculate the elapsed seconds between two times. If I'm right about that, here is a typical way to do it in Python:
import datetime
import time
previous = datetime.datetime.now()
time.sleep(5) # Added to simulate the passing of time for demonstration purposes
current = datetime.datetime.now()
elapsed_seconds = (current - previous) / datetime.timedelta(seconds=1)
"Division" by timedelta is the key to getting elapsed seconds (or any other time unit) between two datetime objects. While not UTC specific hopefully this shines a light on an approach that works for you.

Python - get elapsed time using datetime

With the datetime module, I can get the current time, like so:
>>> datetime.now().strftime('%Y-%m-%d %H:%M:%S')
'2017-08-29 23:01:32'
I have access to the time at which a file was created, in the same format:
>>> data['created']
'2017-08-29 20:59:09'
Is there a way, using the datetime module, that I can calculate the time between the two, in hours?
Performing subtraction on two datetime objects will result in a timedelta. You can use datetime.strptime to get that second datetime object, access the seconds attribute of that timedelta and calculate the hours from there:
from datetime import datetime
...
file_created = datetime.strptime(data['created'], '%Y-%m-%d %H:%M:%S')
difference = (datetime.now() - file_created).seconds
print("Hours since creation: " + str(difference // 3600)) # 3600 seconds in 1 hour

Does Python's time.time() return the local or UTC timestamp?

Does time.time() in the Python time module return the system's time or the time in UTC?
The time.time() function returns the number of seconds since the epoch, as a float. Note that "the epoch" is defined as the start of January 1st, 1970 in UTC. So the epoch is defined in terms of UTC and establishes a global moment in time. No matter where on Earth you are, "seconds past epoch" (time.time()) returns the same value at the same moment.
Here is some sample output I ran on my computer, converting it to a string as well.
>>> import time
>>> ts = time.time()
>>> ts
1355563265.81
>>> import datetime
>>> datetime.datetime.fromtimestamp(ts).strftime('%Y-%m-%d %H:%M:%S')
'2012-12-15 01:21:05'
>>>
The ts variable is the time returned in seconds. I then converted it to a human-readable string using the datetime library.
This is for the text form of a timestamp that can be used in your text files. (The title of the question was different in the past, so the introduction to this answer was changed to clarify how it could be interpreted as the time. [updated 2016-01-14])
You can get the timestamp as a string using the .now() or .utcnow() of the datetime.datetime:
>>> import datetime
>>> print datetime.datetime.utcnow()
2012-12-15 10:14:51.898000
The now differs from utcnow as expected -- otherwise they work the same way:
>>> print datetime.datetime.now()
2012-12-15 11:15:09.205000
You can render the timestamp to the string explicitly:
>>> str(datetime.datetime.now())
'2012-12-15 11:15:24.984000'
Or you can be even more explicit to format the timestamp the way you like:
>>> datetime.datetime.now().strftime("%A, %d. %B %Y %I:%M%p")
'Saturday, 15. December 2012 11:19AM'
If you want the ISO format, use the .isoformat() method of the object:
>>> datetime.datetime.now().isoformat()
'2013-11-18T08:18:31.809000'
You can use these in variables for calculations and printing without conversions.
>>> ts = datetime.datetime.now()
>>> tf = datetime.datetime.now()
>>> te = tf - ts
>>> print ts
2015-04-21 12:02:19.209915
>>> print tf
2015-04-21 12:02:30.449895
>>> print te
0:00:11.239980
Based on the answer from #squiguy, to get a true timestamp I would type cast it from float.
>>> import time
>>> ts = int(time.time())
>>> print(ts)
1389177318
At least that's the concept.
The answer could be neither or both.
neither: time.time() returns approximately the number of seconds elapsed since the Epoch. The result doesn't depend on timezone so it is neither UTC nor local time. Here's POSIX defintion for "Seconds Since the Epoch".
both: time.time() doesn't require your system's clock to be synchronized so it reflects its value (though it has nothing to do with local timezone). Different computers may get different results at the same time. On the other hand if your computer time is synchronized then it is easy to get UTC time from the timestamp (if we ignore leap seconds):
from datetime import datetime
utc_dt = datetime.utcfromtimestamp(timestamp)
On how to get timestamps from UTC time in various Python versions, see How can I get a date converted to seconds since epoch according to UTC?
To get a local timestamp using datetime library, Python 3.x
#wanted format: year-month-day hour:minute:seconds
from datetime import datetime
# get time now
dt = datetime.now()
# format it to a string
timeStamp = dt.strftime('%Y-%m-%d %H:%M:%S')
# print it to screen
print(timeStamp)
I eventually settled for:
>>> import time
>>> time.mktime(time.gmtime())
1509467455.0
There is no such thing as an "epoch" in a specific timezone. The epoch is well-defined as a specific moment in time, so if you change the timezone, the time itself changes as well. Specifically, this time is Jan 1 1970 00:00:00 UTC. So time.time() returns the number of seconds since the epoch.
timestamp is always time in utc, but when you call datetime.datetime.fromtimestamp it returns you time in your local timezone corresponding to this timestamp, so result depend of your locale.
>>> import time, datetime
>>> time.time()
1564494136.0434234
>>> datetime.datetime.now()
datetime.datetime(2019, 7, 30, 16, 42, 3, 899179)
>>> datetime.datetime.fromtimestamp(time.time())
datetime.datetime(2019, 7, 30, 16, 43, 12, 4610)
There exist nice library arrow with different behaviour. In same case it returns you time object with UTC timezone.
>>> import arrow
>>> arrow.now()
<Arrow [2019-07-30T16:43:27.868760+03:00]>
>>> arrow.get(time.time())
<Arrow [2019-07-30T13:43:56.565342+00:00]>
time.time() return the unix timestamp.
you could use datetime library to get local time or UTC time.
import datetime
local_time = datetime.datetime.now()
print(local_time.strftime('%Y%m%d %H%M%S'))
utc_time = datetime.datetime.utcnow()
print(utc_time.strftime('%Y%m%d %H%M%S'))

Categories