I have the following class in a file called 'GPS_Date.py':
import datetime
from math import floor
class GPS_Date(datetime.datetime):
ref_date = datetime.datetime(1980, 1, 6)
def __init__(self, year, month, day, hour=0, minute=0, second=0):
datetime.datetime.__init__(year, month, day, hour, minute, second)
def gps_week(self):
difftime = self-self.ref_date
return floor(difftime.days / 7)
def day_of_week(self):
difftime = self-self.ref_date
return difftime.days % 7
def day_of_year(self):
return self.timetuple().tm_yday
#staticmethod
def to_GPS_date(date):
return GPS_Date(date.year, date.month, date.day, date.hour, date.minute, date.second)
#staticmethod
def now():
return GPS_Date.to_GPS_date(datetime.datetime.utcnow())
When I run the following code in python3.6 I get the correct solution:
import datetime
from GPS_Date import GPS_Date
time_string = '2019-01-01 23:59:30.0'
date_format = '%Y-%m-%d %H:%M:%S.%f'
time_1 = datetime.datetime.strptime(time_string, date_format)
time_2 = GPS_Date.to_GPS_date(time_1)
add_time = time_2 + datetime.timedelta(minutes=30)
But when I run it with python3.9 I get the following error:
add_time = time_2 + datetime.timedelta(minutes=30)
TypeError: __init__() takes from 4 to 7 positional arguments but 9 were given
I assume something has been changed between python3.6 and python3.9. I've looked at documentation but haven't found anything. Can anyone enlighten me?
datetime.datetime does have more arguments that can be passed than GPS_Date accounts for (i.e. tzinfo and fold). Why this doesn't blow up in Python3.6, I am not sure. But you don't need to override __init__ at all, since you aren't doing anything:
class GPS_Date(datetime.datetime):
ref_date = datetime.datetime(1980, 1, 6)
def gps_week(self):
difftime = self - self.ref_date
return floor(difftime.days / 7)
def day_of_week(self):
difftime = self - self.ref_date
return difftime.days % 7
def day_of_year(self):
return self.timetuple().tm_yday
#staticmethod
def to_GPS_date(date):
return GPS_Date(date.year, date.month, date.day, date.hour, date.minute, date.second)
#staticmethod
def now():
return GPS_Date.to_GPS_date(datetime.datetime.utcnow())
is perfectly fine. (Also note: If you were to do something, you need to override __new__ instead of __init__)
Related
Here I am writing property method to display the remaining leave days and total leave days.The total leave days are working fine but def leave_remaining_days(self) this is not working.
I go this error
'datetime.date' object has no attribute 'days'
Here the problem is while returning the no.of days return leave_remaining.days but when i return return leave_remaining just then it works.
How can I calculate the remaining leave days here ?
Only if leave.is_accepted True then i want to calculate remaining days.
I want to decrease days 1 to the end_day by each day until
datetime.date.today() == self.end_day.
EDIT: For this I used celery but this is also not working.Initially to check whether it works or not I set minutes=1 in the periodic task but it doesn't works.
models.py
class Leave(models.Model):
staff = models.ForeignKey(get_user_model(),on_delete=models.CASCADE,related_name='staff')
sub = models.CharField(max_length=300)
msg = models.TextField()
start_day = models.DateField()
end_day = models.DateField()
is_accepted = models.BooleanField(default=False)
is_rejected = models.BooleanField(default=False)
#property
def leave_days(self):
diff = self.end_day - self.start_day
return diff.days
#property
def leave_remaining_days(self):
if self.is_accepted and not datetime.date.today() > self.end_day:
leave_remaining = self.end_day - datetime.timedelta(days=1)
return leave_remaining.days
#changes
from celery.schedules import crontab
from celery.task import periodic_task
#property
#periodic_task(run_every=crontab(minute=1))
def leave_remaining_day(self):
if self.is_accepted and not datetime.date.today() > self.end_day:
leave_remaining = self.leave_days - 1
return leave_remaining
The reason you get this error is because subtracting a timedelta from a date results in a date.
A date has no days attribute (which you can check by creating one and calling dir(...) on it or checking the documentation).
On a sidenote, if you want leave_remaining_days to return how many days are left until the Leave is up, then you should do something like:
#property
def leave_remaining_days(self):
if self.is_accepted and not datetime.date.today() > self.end_day:
delta = self.end_day - datetime.date.today()
return delta.days
Since you are storing the start_day and end_day I'm not sure you need to decrease anything each day. You could perhaps check the property I've written above.
If I understand your question correctly, then in your code:
leave_remaining = self.end_day - datetime.timedelta(days=1)
return leave_remaining.days
leave_remaining is a datetime.date that is 1 day prior to self.end_day, which I think is what you want; just return the date directly like this:
return leave_remaining
I think most obvious answer would be to define your leave_remaining_days prop like this:
#property
def leave_remaining_days(self):
if self.is_accepted:
return self.leave_days - 1
isn't it?
Do you mean this?
#property
def leave_remaining_days(self):
if self.is_accepted and not datetime.date.today() > self.end_day:
leave_remaining = self.end_day - datetime.date.today()
return leave_remaining.days
This shall work:
def leave_remaining_days(self):
if self.is_accepted and not datetime.date.today() > self.end_day:
leave_remaining = self.end_day - datetime.timedelta(days=1)
return leave_remaining.day
leave_remaining.day will give you the remaining leave days
I need help for my python scripts. How to access my clock's function through Date's classes ?
from datetime import date
from datetime import datetime
class Date(object):
def date_today(self):
now = date.today()
print (now)
class Time(Date):
pass
def clock(self):
hr = datetime.now()
hr_now = hr.hour
print (hr_now)
cr_date = Date()
print (cr_date.date_today())
print (cr_date.date_today.clock())
i got an error --> AttributeError: 'function' object has no attribute 'clock'. What is the reason for this error?
you can also add minute, second and other related functions in your time class. I hope it will help.
from datetime import date
from datetime import datetime
class Time():
def clock(self):
hr = datetime.now()
hr_now = hr.hour
return hr_now
class Date():
def __init__(self):
self.time = Time()
def date_today(self):
now = date.today()
return now
def clock(self):
return self.time.clock()
cr_date = Date()
print(cr_date.date_today())
print(cr_date.clock())
For example, I have a file called "gui.py", which uses a module, which is called "pytime.py".
They are in the same directory.
The module (time.py) code has two functions: settime() and readtime()
gui.py code looks like:
import pytime
pytime.settime(16,40) #set hour to 16:40
Now, I want that the other function in the pytime module (readtime()) could access the hour.
I tried "global" but it didn't helped, and also googled a lot.
Thanks!
if you want shared state between the functions, the best way to do this would probably be a class:
# pytime.py
class PyTime(object):
def __init__(self, hour=0, minute=0):
self._hour = hour
self._minute = minute
def set_time(self, hour=None, minute=None):
if hour is not None:
self._hour = hour
if minute is not None:
self._minute = minute
def read_time(self):
return self._hour, self._minute
def __str__(self):
return "{0._hour:02d}:{0._minute:02d}".format(self)
#property
def hour(self):
return self._hour
#property
def minute(self):
return self._minute
In use:
>>> timer = PyTime()
>>> timer.set_time(16, 40)
>>> timer.read_time()
(16, 40)
>>> timer.hour
16
>>> str(timer)
'16.40'
>>> timer.set_time(minute=30)
>>> str(timer)
'16:30'
>>> timer.hour = 15
Traceback (most recent call last):
File "<pyshell#25>", line 1, in <module>
timer.hour = 15
AttributeError: can't set attribute
Note this last result - as I define a property getter for hour but no setter, hour is immutable (although a determined user can access _hour directly).
You could pass in the variable into the function as such:
pytime.py:
def settime(hour, minute):
return str(hour)+':'+str(minute)
def readtime(hour):
print 'This is the hour: {0}'.format(hour)
gui.py:
import pytime
hour = pytime.settime(16, 40)
pytime.readtime(hour)
This runs as:
bash-3.2$ python gui.py
This is the hour: 16:40
bash-3.2$
Extends
Ok, we are not having a good day today.
When you attach the correct tzinfo object to a datetime instance, and then you strftime() it, it STILL comes out in UTC, seemingly ignoring the beautiful tzinfo object I attached to it.
# python 2.5.4
now = datetime.now()
print now.strftime( "%a %b %d %X" ) # %X is "locale's appropriate time rep"
pst = now.replace( tzinfo=Pacific )
print pst.strftime( "%a %b %d %X" )
We get:
Mon Jan 18 17:30:16
Mon Jan 18 17:30:16
I found if I add %z, I can add the difference its supposed to have computed:
Mon Jan 18 17:32:38
Mon Jan 18 17:32:38 -0800
It just tacks on the -8 there, as if to say, "you do it yourself, foo."
But I want strftime() to simply give me a string WITH PRECOMPUTED LOCAL TIME.
How can I get strftime() to do the hour subtraction math for me when I strftime() it?
The full code I'm using is below.
from datetime import tzinfo, timedelta, datetime
ZERO = timedelta(0)
HOUR = timedelta(hours=1)
# A UTC class.
class UTC(tzinfo):
"""UTC"""
def utcoffset(self, dt):
return ZERO
def tzname(self, dt):
return "UTC"
def dst(self, dt):
return ZERO
utc = UTC()
# A class building tzinfo objects for fixed-offset time zones.
# Note that FixedOffset(0, "UTC") is a different way to build a
# UTC tzinfo object.
class FixedOffset(tzinfo):
"""Fixed offset in minutes east from UTC."""
def __init__(self, offset, name):
self.__offset = timedelta(minutes = offset)
self.__name = name
def utcoffset(self, dt):
return self.__offset
def tzname(self, dt):
return self.__name
def dst(self, dt):
return ZERO
# A class capturing the platform's idea of local time.
import time as _time
STDOFFSET = timedelta(seconds = -_time.timezone)
if _time.daylight:
DSTOFFSET = timedelta(seconds = -_time.altzone)
else:
DSTOFFSET = STDOFFSET
DSTDIFF = DSTOFFSET - STDOFFSET
class LocalTimezone(tzinfo):
def utcoffset(self, dt):
if self._isdst(dt):
return DSTOFFSET
else:
return STDOFFSET
def dst(self, dt):
if self._isdst(dt):
return DSTDIFF
else:
return ZERO
def tzname(self, dt):
return _time.tzname[self._isdst(dt)]
def _isdst(self, dt):
tt = (dt.year, dt.month, dt.day,
dt.hour, dt.minute, dt.second,
dt.weekday(), 0, -1)
stamp = _time.mktime(tt)
tt = _time.localtime(stamp)
return tt.tm_isdst > 0
Local = LocalTimezone()
# A complete implementation of current DST rules for major US time zones.
def first_sunday_on_or_after(dt):
days_to_go = 6 - dt.weekday()
if days_to_go:
dt += timedelta(days_to_go)
return dt
# In the US, DST starts at 2am (standard time) on the first Sunday in April.
DSTSTART = datetime(1, 4, 1, 2)
# and ends at 2am (DST time; 1am standard time) on the last Sunday of Oct.
# which is the first Sunday on or after Oct 25.
DSTEND = datetime(1, 10, 25, 1)
class USTimeZone(tzinfo):
def __init__(self, hours, reprname, stdname, dstname):
self.stdoffset = timedelta(hours=hours)
self.reprname = reprname
self.stdname = stdname
self.dstname = dstname
def __repr__(self):
return self.reprname
def tzname(self, dt):
if self.dst(dt):
return self.dstname
else:
return self.stdname
def utcoffset(self, dt):
return self.stdoffset + self.dst(dt)
def dst(self, dt):
if dt is None or dt.tzinfo is None:
# An exception may be sensible here, in one or both cases.
# It depends on how you want to treat them. The default
# fromutc() implementation (called by the default astimezone()
# implementation) passes a datetime with dt.tzinfo is self.
return ZERO
assert dt.tzinfo is self
# Find first Sunday in April & the last in October.
start = first_sunday_on_or_after(DSTSTART.replace(year=dt.year))
end = first_sunday_on_or_after(DSTEND.replace(year=dt.year))
# Can't compare naive to aware objects, so strip the timezone from
# dt first.
if start <= dt.replace(tzinfo=None) < end:
return HOUR
else:
return ZERO
Eastern = USTimeZone(-5, "Eastern", "EST", "EDT")
#Central = USTimeZone(-6, "Central", "CST", "CDT")
#Mountain = USTimeZone(-7, "Mountain", "MST", "MDT")
Pacific = USTimeZone(-8, "Pacific", "PST", "PDT")
now = datetime.now()
print now.strftime( "%a %b %d %X %z" )
pst = now.replace( tzinfo=Pacific )
print pst.strftime( "%a %b %d %X %z" )
.replace does no computation: it simply replaces one or more field in the new returned object, while copying all others from the object it's called on.
If I understand your situation correctly, you start with a datetime object which you know (through other means) is UTC, but doesn't know that itself (is has a tzinfo attribute of None, meaning "I'm totally clueless regarding what timezone I'm in).
So, first, you make a timezone-aware from your input timezone-naive object, in order to inform it that it's in timezone UTC (all other fields just get copied over):
aware = naive.replace(tzinfo=utc)
Then, you can request computations regarding timezones, and printing in consequence:
print aware.astimezone(Pacific).strftime('%a %b %d %X %z')
With dt.replace(tzinfo=tz) you're not really converting the time value, you're just saying 'hey no, wait, this time was actually in PDT, not in UTC'. You'll probably want to use datetime.astimezone(tz) instead.
I think Wim had the right idea, just backwards. If you want to know what your time would be in UTC, use:
print pst.astimezone(UTC).strftime( "%a %b %d %X" )
You'll have to dig up a definition for a UTC timezone class. I understand why Python didn't want to supply a default implementation of every possible tzinfo, but UTC should have been included in the base package.
How do I set the timezone of a datetime instance that just came out of the datastore?
When it first comes out it is in UTC. I want to change it to EST.
I'm trying, for example:
class Book( db.Model ):
creationTime = db.DateTimeProperty()
When a Book is retrieved, I want to set its tzinfo immediately:
book.creationTime.tzinfo = EST
Where I use this example for my EST object
However I get:
attribute 'tzinfo' of 'datetime.datetime' objects is not writable
I've seen a number of answers that recommend pytz and python-dateutil, but I really want an answer to this question.
datetime's objects are immutable, so you never change any of their attributes -- you make a new object with some attributes the same, and some different, and assign it to whatever you need to assign it to.
I.e., in your case, instead of
book.creationTime.tzinfo = EST
you have to code
book.creationTime = book.creationTime.replace(tzinfo=EST)
If you're receiving a datetime that's in EST, but doesn't have its tzinfo field set, use dt.replace(tzinfo=tz) to assign a tzinfo without modifying the time. (Your database should be doing this for you.)
If you're receiving a datetime that's in UDT, and you want it in EST, then you need astimezone. http://docs.python.org/library/datetime.html#datetime.datetime.astimezone
In the vast majority of cases, your database should be storing and returning data in UDT, and you shouldn't need to use replace (except possibly to assign a UDT tzinfo).
What you want is right there in the docs.
from datetime import tzinfo, timedelta, datetime
ZERO = timedelta(0)
HOUR = timedelta(hours=1)
DSTSTART = datetime(1, 4, 1, 2)
DSTEND = datetime(1, 10, 25, 1)
def first_sunday_on_or_after(dt):
days_to_go = 6 - dt.weekday()
if days_to_go:
dt += timedelta(days_to_go)
return dt
class USTimeZone(tzinfo):
def __init__(self, hours, reprname, stdname, dstname):
self.stdoffset = timedelta(hours=hours)
self.reprname = reprname
self.stdname = stdname
self.dstname = dstname
def __repr__(self):
return self.reprname
def tzname(self, dt):
if self.dst(dt):
return self.dstname
else:
return self.stdname
def utcoffset(self, dt):
return self.stdoffset + self.dst(dt)
def dst(self, dt):
if dt is None or dt.tzinfo is None:
# An exception may be sensible here, in one or both cases.
# It depends on how you want to treat them. The default
# fromutc() implementation (called by the default astimezone()
# implementation) passes a datetime with dt.tzinfo is self.
return ZERO
assert dt.tzinfo is self
# Find first Sunday in April & the last in October.
start = first_sunday_on_or_after(DSTSTART.replace(year=dt.year))
end = first_sunday_on_or_after(DSTEND.replace(year=dt.year))
# Can't compare naive to aware objects, so strip the timezone from
# dt first.
if start <= dt.replace(tzinfo=None) < end:
return HOUR
else:
return ZERO
now = datetime.now()
print now
print now.tzinfo
Eastern = USTimeZone(-5, 'Eastern', 'EST', 'EDT')
now_tz_aware = now.replace(tzinfo=Eastern)
print now_tz_aware
output:
2010-01-18 17:08:02.741482
None
2010-01-18 17:08:02.741482-05:00