You have two options; your code doesn't work because you are trying to reset the clock but instead you reset elapsed, which does nothing.
Using modulo division.
start = time.clock()
while True:
elapsed = (time.clock() - start)
if int(elapsed) % 10:
print("MOTION")
Resetting the clock.
start = time.clock()
while True:
elapsed = (time.clock() - start)
if elapsed >= 10:
print("MOTION")
start = time.clock()
Answer from Evan Weissburg on Stack OverflowYou have two options; your code doesn't work because you are trying to reset the clock but instead you reset elapsed, which does nothing.
Using modulo division.
start = time.clock()
while True:
elapsed = (time.clock() - start)
if int(elapsed) % 10:
print("MOTION")
Resetting the clock.
start = time.clock()
while True:
elapsed = (time.clock() - start)
if elapsed >= 10:
print("MOTION")
start = time.clock()
You neglected to reset your reference time: change the basis, not the interval. On each iteration, you reset elapsed to 0, but then immediately go back to the original start time. Change the last line of you loop:
start = time.clock()
while True:
elapsed = (time.clock() - start)
if elapsed > 10:
print("MOTION")
start = time.clock()
How to reset pygames time.
Python time.clock() - reset clock value with threads - Stack Overflow
python - Resetting time.clock() - Stack Overflow
Python module to change system date and time - Stack Overflow
I'm using pygame.time.get_ticks but I can't figure out a way to reset the time back to zero which i need for my game. I was thinking about trying to take the pygames objects time attribute and setting it back to one but idk what the attribute is even called or anything like that.
A thread is not a process, so, no. (As a minor point, you can't kill a thread in Python, you can only ask it to exit. Killing threads through other means, where such means even exist, is likely to leave Python in a bad state.)
The question is why you want to reset the timer, and also why you are using time.clock(). If you care about the elapsed time between two points at such a high granularity that time.time() is not suitable, you'll just have to subtract the first point from the second point. No resetting required. I would recommend just using time.time() unless you really care about that tiny bit of difference in granularity, as time.time() works the same way on all platforms, contrary to time.clock().
Leaving threads apart if you want a clock you can reset with the precision of time.clock() which is higer than the one of time.time() just because the float of the second one is bigger (almost imperceptible difference), for measuring the lapse of time past while running some code you can try this:
t0 = time.clock()
... do something
print('Running time:', time.clock()-t0)
Yo can also try a function decoration for this:
def duration(code):
def f(*args):
t0 = time.clock()
bar = code(*args)
print('Running time:', time.clock()-t0)
return bar
return f
After this you can define your function with the decorator:
@duration
def myFun(*args):
... do something
Or just call the function with the decorator:
duration(myFun)(*args)
import sys
import datetime
time_tuple = ( 2012, # Year
9, # Month
6, # Day
0, # Hour
38, # Minute
0, # Second
0, # Millisecond
)
def _win_set_time(time_tuple):
import pywin32
# http://timgolden.me.uk/pywin32-docs/win32api__SetSystemTime_meth.html
# pywin32.SetSystemTime(year, month , dayOfWeek , day , hour , minute , second , millseconds )
dayOfWeek = datetime.datetime(time_tuple).isocalendar()[2]
pywin32.SetSystemTime( time_tuple[:2] + (dayOfWeek,) + time_tuple[2:])
def _linux_set_time(time_tuple):
import ctypes
import ctypes.util
import time
# /usr/include/linux/time.h:
#
# define CLOCK_REALTIME 0
CLOCK_REALTIME = 0
# /usr/include/time.h
#
# struct timespec
# {
# __time_t tv_sec; /* Seconds. */
# long int tv_nsec; /* Nanoseconds. */
# };
class timespec(ctypes.Structure):
_fields_ = [("tv_sec", ctypes.c_long),
("tv_nsec", ctypes.c_long)]
librt = ctypes.CDLL(ctypes.util.find_library("rt"))
ts = timespec()
ts.tv_sec = int( time.mktime( datetime.datetime( *time_tuple[:6]).timetuple() ) )
ts.tv_nsec = time_tuple[6] * 1000000 # Millisecond to nanosecond
# http://linux.die.net/man/3/clock_settime
librt.clock_settime(CLOCK_REALTIME, ctypes.byref(ts))
if sys.platform=='linux2':
_linux_set_time(time_tuple)
elif sys.platform=='win32':
_win_set_time(time_tuple)
I don't have a windows machine so I didn't test it on windows... But you get the idea.
The tMC's answer seems great. However, it was not working for me properly. I figured out it needed some updates, for both Linux and Windows + python 3. Here is my updated module:
import sys
from _datetime import datetime
time_tuple = (2012, # Year
9, # Month
6, # Day
0, # Hour
38, # Minute
0, # Second
0, # Millisecond
)
def _win_set_time(time_tuple):
import win32api
dayOfWeek = datetime(*time_tuple).isocalendar()[2]
t = time_tuple[:2] + (dayOfWeek,) + time_tuple[2:]
win32api.SetSystemTime(*t)
def _linux_set_time(time_tuple):
import subprocess
import shlex
time_string = datetime(*time_tuple).isoformat()
subprocess.call(shlex.split("timedatectl set-ntp false")) # May be necessary
subprocess.call(shlex.split("sudo date -s '%s'" % time_string))
subprocess.call(shlex.split("sudo hwclock -w"))
if sys.platform == 'linux2' or sys.platform == 'linux':
_linux_set_time(time_tuple)
elif sys.platform == 'win32':
_win_set_time(time_tuple)
For Linux read the following answer: Set the hardware clock in Python?
Based on my testing, this is because threads can only be started once, and as the timer relies on a thread, the timer can only be started once. This means that the only way to re-start the timer would be to do:
def newTimer():
global t
t = Timer(10.0,api_call)
newTimer()
instead of the t = Timer part, and do
t.cancel()
newTimer()
t.start()
instead of the current re-start code.
This makes your full code:
from threading import Timer
def api_call():
print("Call that there api")
def newTimer():
global t
t = Timer(10.0,api_call)
newTimer()
def my_callback(channel):
if something_true:
print('reset timer and start again')
t.cancel()
newTimer()
t.start()
print("\n timer started")
elif something_else_true:
t.cancel()
print("timer canceled")
else:
t.cancel()
print('cancel timer for sure')
try:
if outside_input_that_can_happen_a_lot:
my_callback()
finally:
#cleanup objects
Hope this helps.
Here is a small class which does exactly that from CrazySqueak's answer. So please upvote his answer not mine!
import threading
class AdvTimer():
def __init__(self, interval, callback):
self.interval = interval
self.callback = callback
def restart(self):
self.timer.cancel()
self.start()
def start(self):
self.timer = threading.Timer(self.interval, self.callback)
self.timer.start()
Thanks a lot to the info by @Greg Hewgill. I was able to solve my problem above using the following, if anyone was interested. I got the API information from http://worldtimeapi.org/. The tuple code I built was;
import requests
timeapi = requests.get("http://worldtimeapi.org/api/timezone/Etc/GMT")
tuple_info = timeapi.json()['datetime']
year = int(tuple_info[0:4])
month = int(tuple_info[5:7])
day = int(tuple_info[8:10])
hour = int(tuple_info[11:13])
minute = int(tuple_info[14:16])
second= int(tuple_info[17:19])
millisecond = 0
api_tuple = (year,month,day,hour,minute,second,millisecond)
After changing your system time, your computer only knows the new time. It does not "remember" the original time, so that's why time.gmtime() also returned the new time.
To have your computer learn what the real world time is again, the input has to come from somewhere outside your computer. You can either type in the current time manually, or you could write a script to call some time API service. I found several freely available ones by searching for "time api".
First, change datetime.date.today() to datetime.datetime.today() so that you can manipulate the time of the day.
Then call replace before turning the time into a string.
So instead of:
PERIOD=yesterday.strftime ('%Y-%m-%d')
new_period=PERIOD.replace(hour=23, minute=30)
Do this:
new_period=yesterday.replace(hour=23, minute=30).strftime('%Y-%m-%d')
print new_period
Also keep in mind that the string you're converting it to displays no information about the hour or minute. If you're interested in that, add %H for hour and %M for the minute information to your format string.
You can use datetime.combine(date, time, tzinfo=self.tzinfo)
import datetime
yesterday = datetime.date.today () - datetime.timedelta (days=1)
t = datetime.time(hour=23, minute=30)
print(datetime.datetime.combine(yesterday, t))
Use datetime.replace:
from datetime import datetime
dt = datetime.strptime('26 Sep 2012', '%d %b %Y')
newdatetime = dt.replace(hour=11, minute=59)
Also worth noting: datetime.replace returns a new copy of the datetime (since datetime is immutable): it is like str.replace in that regard.
datetime.replace() will provide the best options. Also, it provides facility for replacing day, year, and month.
Suppose we have a datetime object and date is represented as:
"2017-05-04"
>>> from datetime import datetime
>>> date = datetime.strptime('2017-05-04',"%Y-%m-%d")
>>> print(date)
2017-05-04 00:00:00
>>> date = date.replace(minute=59, hour=23, second=59, year=2018, month=6, day=1)
>>> print(date)
2018-06-01 23:59:59
The freezegun package was made specifically for this purpose. It allows you to change the date for code under test. It can be used directly or via a decorator or context manager. One example:
from freezegun import freeze_time
import datetime
@freeze_time("2012-01-14")
def test():
assert datetime.datetime.now() == datetime.datetime(2012, 1, 14)
For more examples see the project: https://github.com/spulec/freezegun
Monkey-patching time.time is probably sufficient, actually, as it provides the basis for almost all the other time-based routines in Python. This appears to handle your use case pretty well, without resorting to more complex tricks, and it doesn't matter when you do it (aside from the few stdlib packages like Queue.py and threading.py that do from time import time in which case you must patch before they get imported):
>>> import datetime
>>> datetime.datetime.now()
datetime.datetime(2010, 4, 17, 14, 5, 35, 642000)
>>> import time
>>> def mytime(): return 120000000.0
...
>>> time.time = mytime
>>> datetime.datetime.now()
datetime.datetime(1973, 10, 20, 17, 20)
That said, in years of mocking objects for various types of automated testing, I've needed this approach only very rarely, as most of the time it's my own application code that needs the mocking, and not the stdlib routines. After all, you know they work already. If you are encountering situations where your own code has to handle values returned by library routines, you may want to mock the library routines themselves, at least when checking how your own app will handle the timestamps.
The best approach by far is to build your own date/time service routine(s) which you use exclusively in your application code, and build into that the ability for tests to supply fake results as required. For example, I do a more complex equivalent of this sometimes:
# in file apptime.py (for example)
import time as _time
class MyTimeService(object):
def __init__(self, get_time=None):
self.get_time = get_time or _time.time
def __call__(self):
return self.get_time()
time = MyTimeService()
Now in my app code I just do import apptime as time; time.time() to get the current time value, whereas in test code I can first do apptime.time = MyTimeService(mock_time_func) in my setUp() code to supply fake time results.
Update: Years later there's an alternative, as noted in Dave Forgac's answer.