I have validate the start_date and end_date. I need to set null end date field while raising the error. Here is my code:
#api.onchange('end_date')
def onchange_end_date(self, end_date, start_date):
if (start_date and end_date) and (start_date < end_date):
raise exceptions.except_orm(_('Warning!'),_('The start date must be less than to the end date.'))
In Odoo on-change method you no need to pass any parameter, system will directly get it from self object.
#api.onchange('end_date')
def onchange_end_date(self):
if (self.start_date and self.end_date) and (self.start_date < self.end_date):
raise exceptions.except_orm(_('Warning!'),_('The start date must be less than to the end date.'))
This may help you.
Hello you can try this i hope it helps you
import ValidationError
#api.onchange('end_date')
def onchange_end_date(self):
if (self.start_date and self.end_date) and (self.start_date < self.end_date):
raise ValidationError(''The start date must be less than to the end date.'))
Thanks
Other than onchange we can use constraints... It helps to validate something when create and edit and also in change..
Here is my code and it works fine
#api.multi
#api.constrains('start_date', 'start_date')
def _check_date(self):
start_date = self.start_date
end_date = self.end_date
if (start_date and end_date) and (start_date > end_date):
raise ValidationError(_('The start date must be less than to the end date. '))
Thank You
Related
I am creating a class that works with time ranges,
class Time_Range:
"""A class that models time ranges."""
def __init__(self, start:str, end:str, time_format='%m/%d/%Y %H:%M'):
"""Creates a time range.
Parameters:
start : str - start time.
end : str - end time.
"""
start_time = datetime.strptime(start, time_format)
end_time = datetime.strptime(end, time_format)
if start_time > end_time:
raise ValueError("End time is before start time.")
self.start = start_time
self.end = end_time
def __len__(self):
"""Returns the elapsed time in the time range."""
return self.end - self.start
I defined len() to be the time elapsed as a timedelta object, but im getting an error
"TypeError: 'datetime.timedelta' object cannot be interpreted as an integer"
In my opinion, this is a perfectly reasonable way to implement len() in this class, but Python won't allow it. Is there a better way to do this? Do I have to resort to writing my own length method?
It seems you are trying to fit something that isn't into a class.
If your class has only two methods, one of which is __init__, then (in general) it should be a function instead:
def time_range(start:str, end:str, time_format='%m/%d/%Y %H:%M'):
start_time = datetime.strptime(start, time_format)
end_time = datetime.strptime(end, time_format)
if start_time > end_time:
raise ValueError("End time is before start time.")
return end_time - start_time
Especially since you are producing a TimeDelta anyway.
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 have a function that uses a datetime object as default value:
from datetime import datetime, timedelta
from random import randint
def getTime(date = datetime.now()):
i = randint(1,300)
date = date - timedelta(seconds = i)
return date
Now, I need to check if the date variable inside the function was given by another function or was used the default one datetime.now(). If was used the default one, then subtract i seconds, else return the date that was given.
You can do it as follows:
def my_function(date=None):
if date is None:
# The default is used
date = datetime.now()
...
Assuming that you want "now" to be computed every time:
def getTime(date=None):
return date or datetime.now() - timedelta(seconds=randint(1,300))
Otherwise:
Introduce a default arg:
def getTime(date=None, _default=datetime.now()):
return date or _default - timedelta(seconds=randint(1,300))
Or create a decorator:
def just_return_if_provided(f):
def inner(date=None):
return date or f(date)
return inner
#just_return_if_provided
def getTime(date=datetime.now()):
return date - timedelta(seconds=randint(1,300))
I have a model like this;
starttime = models.TimeField('Show Start Time', )
duration = models.DurationField('Duration',)
endtime = models.TimeField('Show End Time (Optional)',blank=True, null=True )
with the starttime and duration I am trying to arrive the endtime while storing the object;
def save(self, *args, **kwargs):
startdelta=timedelta(hours=self.starttime.hour,minutes=self.starttime.minute,seconds=self.starttime.second)
enddelta = startdelta + self.duration
self.endtime = enddelta
super(Showsets, self).save(*args, **kwargs)
Above code throws me error, I want to know how the timefield and duration field works in django also please assist with the ways to query the fields based on starttime or endtime (like objects that starts (starttime) in 30mins from now).
Also curious to know if there are any django-app(add-ons) for time based querying.
Thanks a ton!
Not sure if this will be a good solution for your circumstance but I normally do something like:
start_time = models.TimeField()
end_time = models.TimeField()
def duration(self):
return self.end_time - self.start_time
It seems like a much more concise solution than storing start time with duration and then calculating the end_time on save().
You can combine starttime with today's date and add duration:
from datetime import datetime, date
self.endtime = (datetime.combine(date.today(), self.starttime) + self.duration).time()
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