I am using odoo 12 and want to show Date field record from a model into Reports, how can i do this?
Still facing error
time data 'False' does not match format '%d %B, %Y'
here is my code
#api.multi
def _get_student_dob_in_words(self, student_id):
date_of_birth = fields.Date('BirthDate', default=fields.date.today(),
states={'done': [('readonly', True)]})
student = self.env['student.student'].search([('id','=',student_id)])
date_of_birth = student.date_of_birth
# date_of_birth = date.today()
# %Y-%m-%d %H:%M:%S
strp_date = datetime.strptime(str(date_of_birth),"%d %B, %Y")
# dob_result = datetime.strptime(date_of_birth, DEFAULT_SERVER_DATETIME_FORMAT).date()
# str_dob_result = str(date_of_birth)
strp_dob_result = num2words(strp_date)
strp_dob_result = strp_dob_result.upper()
return [{
'dob_in_words': strp_dob_result}]
You don't need strptime at all, you may use strftime. You still have to test if date is present. And i would make it as computed field as well.
_{name|inherit} = 'student.student'
#date_of_birth = fields.Date(...
date_of_birth_words = fields.Char(compute='_compute_dob_in_words', store=True)
#api.depends('date_of_birth')
def _compute_dob_in_words(self):
for student in self:
if student.date_of_birth:
date_of_birth = student.date_of_birth
month = date_of_birth.strftime('%B') #date_of_birth.month
day = num2words.num2words(date_of_birth.day, to='ordinal')
year = num2words.num2words(date_of_birth.year)
student.date_of_birth_words = "{} {} in year {}".format(day, month, year).upper()
python get the quarterly dates from a date range
example :
start date = 01/04/2020
end date = 01/04/2021
Here I need to get the Quaternary dates from this date range.
Try:
start_date = "01/04/2020"
end_date = "01/04/2021"
pd.date_range(start_date, end_date, freq='Q')
DatetimeIndex(['2020-03-31', '2020-06-30', '2020-09-30', '2020-12-31'], dtype='datetime64[ns]', freq='Q-DEC')
pd.date_range(start date, end date, freq='3m').to_period('Q')
With pure Python:
import datetime
start_date_str = "01/04/2020"
end_date_str = "01/04/2021"
start_date = datetime.datetime.strptime(start_date_str, "%d/%m/%Y").date()
end_date = datetime.datetime.strptime(end_date_str, "%d/%m/%Y").date()
print(f"Quarters within {start_date_str} and {end_date_str}:")
start_of_quarter = start_date
while True:
far_future = start_of_quarter + datetime.timedelta(days=93)
start_of_next_quarter = far_future.replace(day=1)
end_of_quarter = start_of_next_quarter - datetime.timedelta(days=1)
if end_of_quarter > end_date:
break
print(f"\t{start_of_quarter:%d/%m/%Y} - {end_of_quarter:%d/%m/%Y}")
start_of_quarter = start_of_next_quarter
I want to specify the date of the desired format as a file name in this way
;
During [2019-10-01 09:00 ~ 2019-10-02 08:59:59]
Save data to 191001-09.txt
I have no idea about this. I could only follow simple code.
Please let me know how to fix it :
def timeStamped (fname, fmt = '19% m% d-% H {fname} '):
return datetime.datetime.now (). strftime (fmt) .format (fname = fname)
with open (timeStamped ('. txt'), 'a') as f_last:
f_last.write ('data')
Question: Conditional file name from datetime.now()
Import the required objects
datetime
timedelta
from datetime import datetime, timedelta
Define a function that gets the desired file name from a datetime.date object:
def fname_from_date(date):
# Rule 09:00:00 ~ day + 1 08:59:59
midnight = date.replace(hour=0, minute=0, second=0)
begin_of_day = date.replace(hour=9, minute=0, second=0)
end_of_day = date.replace(hour=8, minute=59, second=59)
# Are we between 'midnight' and 'end_of_day'
if date >= midnight and date <= end_of_day:
date = date - timedelta(days=1)
print('\tNext day -1: {}'.format(date))
# 191001-09.txt
fname = date.strftime('%Y%m%d-09')
return fname
Test the function def fname_from_date(... with static dates.
This requires to create a datetime.date object from datestr.
for datestr in ['2019-10-01 09:00:00',
'2019-10-01 11:01:11',
'2019-10-02 07:07:07',
'2019-10-02 08:59:59']:
date = datetime.strptime(datestr, '%Y-%m-%d %H:%M:%S')
print(date)
fname = '{}.txt'.format(fname_from_date(date))
print('\t{}'.format(fname))
Output:
2019-10-01 09:00:00
20191001-09.txt
2019-10-01 11:01:11
20191001-09.txt
2019-10-02 07:07:07
Next day -1: 2019-10-01 07:07:07
20191001-09.txt
2019-10-02 08:59:59
Next day -1: 2019-10-01 08:59:59
20191001-09.txt
Usage:
fname = '{}.txt'.format(fname_from_date(datetime.now()))
startdate = datetime.date(2017,1,13)
expirydate = datetime.date(2017,1,19)
data = dict()
for x in range(0,3):
for y in range(1,8):
if ((startdate.weekday() !=5) or (startdate.weekday() !=6)):
data [(x,y)] = get_history(symbol="BANKNIFTY",
start= startdate,
end= startdate,
index=True,
option_type='CE',
strike_price= int(df['CE Strike'][y]),
expiry_date=expirydate)
startdate += datetime.timedelta(days=1)
expirydate += datetime.timedelta(days=7)
if Day is Saturday or Sunday please don't run. That's what I was expecting from this code. but it is still including sat and sun.
In if ((startdate.weekday() !=5) or (startdate.weekday() !=6)):
change or to and.
Alternative: if startdate.weekday() not in [5, 6]:.
I have an Event model, and each event will have different shows.
class Event(models.Model):
title = models.CharField(max_length=200)
class Show(models.Model):
event = models.ForeignKey(Event, on_delete=models.CASCADE)
date_time = models.DateTimeField(unique=True)
I have another Ticket model. Each ticket should be unique. Meaning each ticket will be unique and relate to a Show and a Seat.
class Ticket(models.Model):
show = models.ForeignKey(Show)
seat = models.ForeignKey(Seat)
class Meta:
unique_together = ('show', 'seat')
I need to create shows based on the start date and end date provide by the user. Suppose this is a JSON post:
{
"event_id": 1,
"start_date": "2018-02-16",
"end_date": "2018-02-20",
"time_list": ["11:00 AM", "8:00 PM"]
}
From the above JSON example, I need to create Show starting like this:
# Start with the start_date as the date, and for each time from the time_list
Show.objects.create(
event = 1,
date_time = datetime.strptime('2018-02-16 11:00 AM', "%Y-%m-%d %I:%M %p")
)
Show.objects.create(
event = 1,
date_time = datetime.strptime('2018-02-16 8:00 PM', "%Y-%m-%d %I:%M %p")
)
# Next date after the start_date, i.e., 16+1 = 17
Show.objects.create(
event = 1,
date_time = datetime.strptime('2018-02-17 8:00 PM', "%Y-%m-%d %I:%M %p")
)
.
.
.
# Create Show objects till the end_date and for each time from the time_list
Show.objects.create(
event = 1,
date_time = datetime.strptime('2018-02-20 8:00 PM', "%Y-%m-%d %I:%M %p")
)
Right now this is how I am creating Show objects:
def create_show_by_datetime(self, request):
event_id = request.data['event_id']
try:
event = Event.objects.get(id=event_id)
except Event.DoesNotExist:
return Response(
{'error': 'event with id: %s does not exist.' % event_id},
status=status.HTTP_400_BAD_REQUEST
)
start_date = request.data['start_date']
end_date = request.data['end_date']
time_list = request.data['time_list']
date_format = '%Y-%m-%d'
time_format = "%I:%M %p"
try:
datetime.strptime(start_date, date_format)
datetime.strptime(end_date, date_format)
for i in range(len(time_list)):
time = datetime.strptime(time_list[i], time_format)
except ValueError as e:
return Response(
{'error': 'Time was not in a supported format. %s' % e},
status=status.HTTP_400_BAD_REQUEST
)
delta_days = datetime.strptime(end_date, date_format).date() - datetime.strptime(start_date, date_format).date()
delta_days = delta_days.days + 1
dt = None
try:
with transaction.atomic():
for i in range(delta_days):
day = datetime.strptime(start_date, date_format) + timedelta(days=i)
for i in range(len(time_list)):
hrs = datetime.strptime(time_list[i], time_format).hour
mins = datetime.strptime(time_list[i], time_format).minute
dt = day + timedelta(hours=hrs, minutes=mins)
show = Show.objects.create(
event=event,
date_time=dt
)
return Response({"data": 'Post succesfull'}, status=status.HTTP_201_CREATED)
except IntegrityError as e:
return Response(
{
'error': "event with date and time already exsits. %s-%s-%s at %s:%s" % (
dt.day, dt.month, dt.year, dt.hour, dt.minute),
'detail': str(e)
}, status=status.HTTP_400_BAD_REQUEST
But I am hoping there's much more elegant way than how I am doing. I am using python 3, django 2 and django rest frameowork. How can I create Shows with the event, and date_time based on the event_id, start_date, end_date and the time_list?
My approach is a little bit different. You said in the question tag that you are using django-rest-framework.. So where are the serializers? :)
Lets create two serializers, one for user data validation (Because we don't trust the USER!) and one for multi data insert.
I haven't checked the code! But you can use it was an example...
class ShowEventSerializer(serializers.Serializer):
event_id = serializers.IntegerField()
start_date = serializers.DateField(required=True)
end_date = serializers.DateField(required=True)
time_list = serializers.ListField(
child=serializers.TimeField()
)
class Meta:
fields = ('event_id', 'start_date', 'end_date', 'time_list')
class ShowSerializer(serializers.Serializer):
date_time = serializers.DateTimeField()
class Meta:
model = Show
fields = ('event', 'date_time')
Now, with the serializers, we are going to validate the user data and then to create a json data object:
def create_show_by_datetime(self, request):
show_event_serializer = ShowEventSerializer(data=request.data)
if not show_event_serializer.is_valid():
return Response({'error': show_event_serializer.errors},status=status.HTTP_400_BAD_REQUEST)
event_id = show_event_serializer.data['event_id']
try:
event = Event.objects.get(id=event_id)
except Event.DoesNotExist:
return Response({'error': 'event with id: %s does not exist.' % event_id},status=status.HTTP_400_BAD_REQUEST)
start_date = show_event_serializer.data['start_date']
end_date = show_event_serializer.data['end_date']
time_list = show_event_serializer.data['time_list']
date_format = '%Y-%m-%d'
time_format = "%I:%M %p"
try:
datetime.strptime(start_date, date_format)
datetime.strptime(end_date, date_format)
for i in range(len(time_list)):
time = datetime.strptime(time_list[i], time_format)
except ValueError as e:
return Response(
{'error': 'Time was not in a supported format. %s' % e},
status=status.HTTP_400_BAD_REQUEST
)
delta_days = datetime.strptime(end_date, date_format).date() - datetime.strptime(start_date, date_format).date()
delta_days = delta_days.days + 1
dt = None
show_data = []
for i in range(delta_days):
day = datetime.strptime(start_date, date_format) + timedelta(days=i)
for i in range(len(time_list)):
hrs = datetime.strptime(time_list[i], time_format).hour
mins = datetime.strptime(time_list[i], time_format).minute
dt = day + timedelta(hours=hrs, minutes=mins)
show_data.append({
"event": event,
"date_time": dt
})
try:
with transaction.atomic():
show_serializer = ShowSerializer(data=show_data, many=True)
if show_serializer.is_valid():
show_serializer.save()
return Response({"data": 'Post succesfull'}, status=status.HTTP_201_CREATED)
except IntegrityError as e:
return Response(
{
'error': "event with date and time already exsits. %s-%s-%s at %s:%s" % (
dt.day, dt.month, dt.year, dt.hour, dt.minute),
'detail': str(e)
}, status=status.HTTP_400_BAD_REQUEST
So this code is basically the same as yours, with the difference of the way the objects are saved using the DRF. Look the show_data variable.
This solution is just a different way of looking at the question.
GOOD LUCK!
http://www.django-rest-framework.org/api-guide/serializers/
http://www.django-rest-framework.org/api-guide/fields/
Then your Show model should look like
from django.contrib.postgres.fields import ArrayField
class Show(models.Model):
event = models.ForeignKey(Event, on_delete=models.CASCADE)
start_date = models.DateField(blank=True, null=True)
end_date = models.DateField(blank=True, null=True)
board = ArrayField(
models.TimeField(blank=True, null=True),
size=10, # specify max array size
)
so you'll have model Show with specified DateFields and array of TimeFields.
django docs: Array Field, Time Field, Date Field
There are some tools in the datetime library that can give you a more streamlined approach to generating your times. You can use toordinal to turn a date into an integer and fromordinal to turn an integer back into a date; this makes a nice way to create a range of dates. And you can use combine to merge a date object and a time object into a datetime. I'd create the following function:
from datetime import datetime, date
def get_showtimes(post):
start = datetime.strptime(post['start_date'], '%Y-%m-%d')
end = datetime.strptime(post['end_date'], '%Y-%m-%d')
times = [datetime.strptime(t, '%I:%M %p').time() for t in post['time_list']]
for ordinal in range(start.toordinal(), end.toordinal() + 1):
date = date.fromordinal(date)
for time in times:
yield datetime.combine(date, time)
then, in your code, replace the second try: except: block and what follows it with:
try:
showtimes = list(get_showtimes(post))
except ValueError as e:
return Response(
{'error': 'Time was not in a supported format. %s' % e},
status=status.HTTP_400_BAD_REQUEST
)
try:
with transaction.atomic():
for showtime in showtimes:
show = Show.objects.create(event=event, date_time=showtime)
except IntegrityError as e:
# etc.
I am leaving the validation part and only focusing on generating Show objects from the given data:
data = request.data
date_format = '%Y-%m-%d'
time_format = "%I:%M %p"
show_time_format = f"{date_format} {time_format}"
# get the total number of days by parsing start and end dates
start_date = datetime.strptime(data['start_date'], date_format)
end_date = datetime.strptime(data['end_date'], date_format)
total_days = (end_date - start_date).days + 1
# Get the timings for the first day.
# We will use this to generate the timings for the rest of the days.
first_day_timings = [
datetime.strptime(f"{data['start_date']} {show_time}", show_time_format)
for show_time in data['time_list']
]
# generate all show objects using list comprehension and bulk create later
show_objects = [
Show(event=event, date_time=first_day_timing + timedelta(days=day_cnt))
for day_cnt in range(total_days)
for first_day_timing in first_day_timings
]
Show.objects.bulk_create(show_objects)
Enhancements made on the existing code:
Reduced the number of instances date/time is getting parsed and hours/minutes are getting computed.
Use list comprehension to generate show objects and bulk create instead of creating one object at a time in a transaction.