How to display different date formats in Odoo datetime fields? - python

Currently the date format on our Odoo CRM looks like 11/20/2017 13:03:41 but I want to display the format to July 3rd 3:00PM and on another place show as 3 Jul 3:00PM
We show this field in the form
<field name="pickup_time"/>
I have searched a lot to find how to change the format, but It's mainly to change in the local settings and it's permanently one setting for everywhere. Which would not solve of what we want, like having two different format for different places.

Along Odoo the default constant date format used is DEFAULT_SERVER_DATETIME_FORMAT. This is defined in the file misc.py
DEFAULT_SERVER_DATE_FORMAT = "%Y-%m-%d"
DEFAULT_SERVER_TIME_FORMAT = "%H:%M:%S"
DEFAULT_SERVER_DATETIME_FORMAT = "%s %s" % (
DEFAULT_SERVER_DATE_FORMAT,
DEFAULT_SERVER_TIME_FORMAT)
So if you declare the field like the following code then that constant is going to be used:
pickup_time = fields.Datetime(
string="Pickup time",
)
So if you want to use another format you can create a computed field with that custom format. You need to use some date functions: strftime (object to string) and strptime (string to object). The formats codes are explained almost at the bottom of this python documentation page
from datetime import datetime
from odoo.tools import DEFAULT_SERVER_DATETIME_FORMAT
[...]
pickup_time_formated = fields.Char( # it is going to be a readonly field
string='Pickup time formated',
compute='_compute_pickup_time_formated'
)
#api.multi
#api.depends('pickup_time')
def _compute_pickup_time_formated(self):
for record in self:
date = record.pickup_time
date_obj = datetime.strptime(date, DEFAULT_SERVER_DATETIME_FORMAT) # to convert it in a date object
v = date_obj.day % 10 # to get the remainder of the operation
if v == 1:
ordinal_suffix = 'st'
elif v == 2:
ordinal_suffix = 'nd'
elif v == 3:
ordinal_suffix = 'rd'
else:
ordinal_suffix = 'th'
# format 'July 3rd 3:00PM'
record.pickup_time_formated = datetime.strftime(date_obj, '%B %d' + ordinal_suffix + ' %I:%M %p')
# format '3 Jul 3:00PM'
# record.pickup_time_formated = datetime.strftime(date_obj, '%d %b %I:%M %p'),
And then you can show the new fields in the xml form:
<field name="pickup_time_formated"/>

Related

ValueError: time data 'None' does not match format '%Y-%m-%dT%H:%M:%S.%f'

For the node 'TransactionDate' i have a logic before updating it for policy"POL000002NGJ".
The logic i am trying to implement is If existing 'TransactionDate' < than today, then add 5 days with current value and parse it to xml.
Transaction Date Format in XML : 2020-03-23T10:56:15.00
Please Note that, If i parsing the DateTime value like below, It works good But i dont want to hardcode the value... I want to Parse it as a string object to handle for any datetime in format ""%Y-%m-%dT%H:%M:%S.%f""...
# <TransactionDate>
today = datetime.now()
TransactionDate = doc.find('TransactionDate')
Date = '2020-03-24T10:56:15.00'
previous_update = datetime.strptime(Date, "%Y-%m-%dT%H:%M:%S.%f")
if previous_update < today:
today = previous_update - timedelta(days=-5)
TransactionDate = today.strftime("%Y-%m-%dT%H:%M:%S.%f")
Below code while parsing it as a DateTime Object, I have an issue.. I got struck here and referenced other answers in stackoverflow and python forums, But still i got struct up here and unable to resolve the issue...
if any help to fix will be a great helpful. Thanks. Below code using lxml and getting help to support below code will helpful. Because i already completed for other nodes. My understanding is Date variable is calling as None.. But struck here to fix.. Please help..
# <TransactionDate>
today = datetime.now()
TransactionDate = doc.find('TransactionDate')
Date = str(TransactionDate)
previous_update = datetime.strptime(Date, "%Y-%m-%dT%H:%M:%S.%f")
if previous_update < today:
today = previous_update - timedelta(days=-5)
TransactionDate = today.strftime("%Y-%m-%dT%H:%M:%S.%f")
Full Code is Below
from lxml import etree
from datetime import datetime, timedelta
import random, string
doc = etree.parse(r'C:\Users\python.xml')
# <PolicyId> - Random generated policy number
Policy_Random_Choice = 'POL' + ''.join(random.choices(string.digits, k=6)) + 'NGJ'
# <TransactionDate>
today = datetime.now()
TransactionDate = doc.find('TransactionDate')
Date = str(TransactionDate)
previous_update = datetime.strptime(Date, "%Y-%m-%dT%H:%M:%S.%f")
if previous_update < today:
today = previous_update - timedelta(days=-5)
TransactionDate = today.strftime("%Y-%m-%dT%H:%M:%S.%f")
#Parsing the Variables
replacements = [Policy_Random_Choice , TransactionDate ]
targets = doc.xpath('//ROW[PolicyId="POL000002NGJ"]')
for target in targets:
target.xpath('./PolicyId')[0].text = replacements[0]
target.xpath('.//TransactionDate')[0].text = replacements[1]
print(etree.tostring(doc).decode())
Sample XML
<TABLE>
<ROW>
<PolicyId>POL000002NGJ</PolicyId>
<BusinessCoverageCode>COV00002D3X1</BusinessCoverageCode>
<TransactionDate>2020-03-23T10:56:15.00</TransactionDate>
</ROW>
<ROW>
<PolicyId>POL111111NGJ</PolicyId>
<BusinessCoverageCode>COV00002D3X4</BusinessCoverageCode>
<TransactionDate>2020-03-23T10:56:15.00</TransactionDate>
</ROW>
</TABLE>
Maybe the find method is wrong. Try this one
# <TransactionDate>
today = datetime.now()
TransactionDate = doc.xpath('//ROW/TransactionDate') # Change find to xpath
Date = str(TransactionDate[0].text) # Use the first one
previous_update = datetime.strptime(Date, "%Y-%m-%dT%H:%M:%S.%f")

insert conditional for hours

Good evening, could you help me in how I can put a condition so that a message comes out saying that you can not take an hour because it is already busy ?, I currently have this:
class reserva (models.Model):
_name='gimnasio.reserva'
tipo_reserva=fields.Selection([('clase','Clase'),('evaluacion','Evaluacion')])
fecha_reserva=fields.Date()
start_time=fields.Float()
end_time=fields.Float()
def fecha(self):
if self.star_time==self.star_time:
raise validationError('the hour is busy')
I have another question for you. you know how to configure Datetime only for hour and minutes because I only need hour and minutes but not the date.
To configure Datetime only for hour and minutes.
time = fields.Datetime("time")
custom_time = fields.Char('my_custome_time')
#api.onchange('time')
def _get_time(self):
if self.time:
for rec in self:
# datetime value is a string like 'YYYY-mm-dd HH:MM:SS'
# so just extract string from position 11 to 16
_time = self.time[11:16]
self.custom_time = _time
rec.custom_time = self.custom_time
I think you can use strptime method from datetime module.
from datetime import datetime as dt
start_time = fields.Float()
end_time = fields.Float()
#api.onchange('start_time','end_time')
def _check(self):
records = self.env["gimnasio.reserva"].search([("day", '=', the day you want to check eg. "2019-06-13")])
for rec in records:
ref_start = dt.strptime(str(rec.start_time), "%H:%M")
curr_start = dt.strptime(str(self.start_time), "%H:%M")
if ref_start == curr_start:
raise validationError('the hour is busy')
I didn't debug yet, you can try it.
how to eliminate the default date that you added ("2019-06-13") and that any date should not have the same busy schedule?
In this case you don't need datetime module just
#api.constrains("start_time")
def _check(self):
# search db for any record have same start time.
records = self.env["gimnasio.reserva"].search([('start_time ','=', self.start_time)])
if len(records) > 0:
raise validationError('the hour is busy')

Python & Tweepy - How to compare and change times.

I am trying to create a number of constraints for some other code based on twitter handle sets.
I am having issues with the following code because:
TypeError: can't compare datetime.datetime to str
It seems that even though I have changed Last_Post to a datetime object initially, when i compare it to datetime.datetime.today() it is converting to string. Yes, I have checked the to ensure that Last_post is converting properly. Im not really sure what is going on. Help?
for handle in handles:
try:
user = api.get_user(handle)
#print json.dumps(user, indent = 4)
verified = user["verified"]
name = user['name']
language = user['lang']
follower_count = user['followers_count']
try:
last_post = user['status']['created_at']
last_post = datetime.strptime(last_post, '%a %b %d %H:%M:%S +0000 %Y')
except:
last_post = "User has not posted ever"
location = user['location']
location_ch = location_check(location)
if location_ch is not "United States":
location_output.append(False)
else:
location_output.append(True)
new_sum.append(follower_count)
if language is not "en":
lang_output.append(False)
else:
lang_output.append(True)
if datetime.datetime.today() - datetime.timedelta(days=30) > last_post:
recency.append(False)
else:
recency.append(True)
I think you need to convert the twitter date to a timestamp:
import time
ts = time.strftime('%Y-%m-%d %H:%M:%S', time.strptime(tweet['created_at'],'%a %b %d %H:%M:%S +0000 %Y'))

Guessing the date format python

I am writing a method in a Python module which tries to make live easier to the users. This method implements the creation of events in that calendar.
def update_event(start_datetime=None, end_datetime=None, description=None):
'''
Args:
start_date: string datetime in the format YYYY-MM-DD or in RFC 3339
end_date: string datetime in the format YYYY-MM-DD or in RFC 3339
description: string with description (\n are transforrmed into new lines)
'''
If the user specifies the start_date or the end_date a check up should be made in order to determine if the date is in YYYY-MM-DD format or in the datetime RFC 3339 format.
if (start_date is not None):
# Check whether we have an date or datetime value
# Whole day events are represented as YYYY-MM-DD
# Other events are represented as 2014-04-25T10:47:00.000-07:00
whole_day_event = False
try:
new_start_time = datetime.datetime.strptime(start_date,'YYYY-MM-DD')
# Here the event date is updated
try:
new_start_time = datetime.datetime.strptime(start_date,'%Y-%m-%dT%H:%M:%S%z')
#Here the event date is updated
except ValueError:
return (ErrorCodeWhatever)
except ValueError:
return (ErrorCodeWhatever)
Is this a good way of doing this? Can I check what kind of date I am receiving in a nicer way?
Thanks!
dateutil.parser.parse can be used to attempt to parse strings into datetime objects for you.
from dateutil.parser import parse
def update_event(start_datetime=None, end_datetime=None, description=None):
if start_datetime is not None:
new_start_time = parse(start_datetime)
return new_start_time
d = ['23/04/2014', '24-04-2013', '25th April 2014']
new = [update_event(i) for i in d]
for date in new:
print(date)
# 2014-04-23 00:00:00
# 2013-04-24 00:00:00
# 2014-04-25 00:00:00
Extending #Ffisegydd answer you can also specify your target datetime format that you want like this :-
from dateutil.parser import parse
def update_event(start_datetime=None, end_datetime=None, description=None):
if start_datetime is not None:
new_start_time = parse(start_datetime)
return new_start_time
d = ['06/07/2021 06:40:23.277000','06/07/2021 06:40','06/07/2021']
new = [update_event(i) for i in d]
for date in new:
print(date.strftime('%Y/%m/%d %H:%M:%S.%f'))

ToscaWidgets CalendarDatePicker pylons

How does one set the date on the CalendarDatePicker. i.e. it defaults to current date and I want to display it with another date which I will set from my controller.
I am displaying the CalendarDatePicker widget in a TableForm from tw.form. I have looked at this for a few hours and can't work out how to do this so any pointers greatly appreciated.
import tw.forms as twf
form = twf.TableForm('dateSel', action='changeDate', children=[
twf.CalendarDatePicker('StartDate', date_format = "%d/%m/%Y"),
twf.CalendarDatePicker('EndDate', date_format = "%d/%m/%Y" )
])
I don't have a copy of twforms laying around, but based on their sample code, it looks like you might want to do something like:
from datetime import datetime
start = twf.CalendarDatePicker('StartDate', date_format = "%d/%m/%Y")
start.default = datetime.now() # or any valid datetime object
end = twf.CalendarDatePicker('EndDate', date_format = "%d/%m/%Y" )
start.default = datetime.now() # or any valid datetime object
form = twf.TableForm('dateSel', action='changeDate', children=[start, end])

Categories