Compare dates in openerp 7 - odoo

I have a custom module in openerp 7 with fields check-in time(date-time) and check-out time(date-time). When I click on save, i want to perform a validation on both fields to ensure check-out time is not less than check-in time. Thanks for any ideas.

As above, use datetime.
In Odoo your dates, times and datetimes are handed to use as strings formatted using
openerp.tools.DEFAULT_SERVER_DATE_FORMAT, DEFAULT_SERVER_TIME_FORMAT and DEFAULT_SERVER_DATETIME_FORMAT.
from datetime import datetime
from openerp.tools import DEFAULT_SERVER_DATETIME_FORMAT
check_in = datetime.strptime(my_object.check_in, DEFAULT_SERVER_DATETIME_FORMAT)
check_out = datetime.strptime(my_object.check_out, DEFAULT_SERVER_DATETIME_FORMAT)
Go nuts with comparisons etc.
A couple of notes:
I highly recommend reading up on the datetime module in the standard library, particularly strftime, strptime and timedelta
Remember you will be getting the dates and datetimes in UTC. The classes that represent the date and datetime fields have methods to return dates and timestamps in the users' timezone but you will not usually need these. Have a look at fields.date.context_today and fields.datetime.context_timestamp

I would try to use the datetime class from the datetime module.
Import relevant python module
from datetime import datetime
Retrieve your record via the appropriate method i.e.
your_record = self.pool.get('your_custom_module').search(cr, uid, domain, offset=0, limit=None, order=None, context=None, count=False)
note: you need to provide proper domain and modify/remove arguments to suit you needs
Create datetime objects from relevant fields (use the strptime method of datetime class : create a date object from a string). Something like :
check_in = datetime.strptime(your_record[0]['check-in time'], '%Y-%m-%d')
check_out = datetime.strptime(your_record[0]['check-out time'], '%Y-%m-%d')
note: you need to adapt the format('%Y-%m-%d') to whatever format your DB returns
Compare both object with a simple expression :
if check_in < check_out:
...
else:
...
Do whatever other operations need to be done.
It's kinda hard to provide more info without additional details about your flow.
Hope this helps,
Cheers

Related

Is there an easy way to implement DateTimePicker in Django Crispy forms?

I have a DeliveryNote model which contains datetime field.
class DeliveryNote(models.Model):
date_completed = models.DateTimeField("Date Completed")
But on ModelForms, there is only DateField available:
date_completed = forms.DateField(initial=datetime.date.today,
widget=forms.widgets.DateInput(attrs={'type': 'date'}))
As it can be seen that there is not time selection:
I have looked to this answer, but can not able to implement it. Any idea how to implement datetime field easily.
You can use DateTimeInput widget and datetime-local as input type:
date_completed = forms.DateField(initial=datetime.date.today,
widget=forms.widgets.DateTimeInput(attrs={'type': 'datetime-local'}))

I want to create U.S. Date Format to Indian Date Format Using Asp MVC Core 2.0

I am trying to Create Date Format the US to Indian Date Format like(dd/mm/yyyy hh:mm tt).
When I run the code on my local machine it works.
When we publish and fetch values from the server at that time it shows "US" Date Format(mm/dd/yyyy)
How τo do the internal conversion, in Appsettings.json what strings i need to mention.
public static DateTime ConvertIndianDateFormat(DateTime usTime)
{
DateTime dateTime = DateTime.Now;
TimeZoneInfo usEasternZone = TimeZoneInfo.FindSystemTimeZoneById("US Eastern Standard Time");
TimeZoneInfo indianZone = TimeZoneInfo.FindSystemTimeZoneById("India Standard Time");
DateTime usEasternTime = TimeZoneInfo.ConvertTimeFromUtc(usTime, usEasternZone);
DateTime indianTime = TimeZoneInfo.ConvertTimeFromUtc(usTime, indianZone);
return indianTime;
}
This is because you are probably using something like DateTime.Now for C# and if you have an SQL Server you are using GETDATE(). It's not like an issue with application.json or something. The above functions return the machine datetime, thus why locally on your pc the time is correct and incorrect if you upload it to a server.
So make sure that the time is correct. If you are uploading to servers in another country then you will probably have a different time and/or format.
How you proceed depends on your needs:
Is the time correct?
Then simply reformated it or store it specifically using
DateTime.Now.ToString("dd/mm/yyyy hh:mm tt") // this is not the correct format.
Do you want to serve multiple clients in multiple regions/countries?
Then you should store the time as UTC and cast it based on clients date format. For example the server could be in USA and someone from UK would view a different time than his own which would be weird.
DateTime.UtcNow
Generally your problem could be large or small depending on your needs

Send UTC timestamps with moment.js to ASP.NET Core controller

I have a database with measured values from devices that I want to display in a web frontend. First I send the list of devices to the frontend together with the IANA timezone specifier for each device.
I would like all timestamps to be exchanged as UTC. The user selects a time range in the frontend in device-local time. I use moment.js to convert these timestamps to UTC with the known timezone of the device like this:
var startTimestamp = new Date(2017, 7, 1); //some local timestamp (zero-based month!)
var m = moment.tz(startTimestamp, "Europe/Berlin");
var utc = moment.utc(m).format();
utc is now "2017-07-31T22:00:00Z" which seems to be correct given the 2 hours offset for Berlin in DST.
I send this utc timestamp to my ASP.NET Core backend. The controller looks like this:
[HttpGet]
public IEnumerable<TimestampedValue> GetValues(int id, DateTime startTimestamp)
{
...
}
The problem is that startTimestamp is 2017-08-01 00:00:00 when the controller is called and its Kind property is set to Local. I would have expected it to be the same UTC timestamp.
Any idea what I'm doing wrong? I think moment.js is doing its job correctly so this must be a problem on the server side. If I recall correctly, the deserialization is done by JSON.net but I don't understand why it does not respect the Z at the end of the time string.
After #dbc pointed me to the different behavior between GET and POST requests I come to this conclusion:
Since my request uses the GET method and query strings are not JSON, there is no JSON.net involved in the problem, it is the default .NET Core DateTimeConverter that does the conversion. Moment.js correctly converts the timestamp to a UTC string, I checked that using the browser developer tools.
The code for DateTimeConverter can be found here:
https://github.com/dotnet/corefx/blob/312736914d4e98c2948778bacac029aa831dd6b5/src/System.ComponentModel.TypeConverter/src/System/ComponentModel/DateTimeConverter.cs
As can be seen there, the converter uses DateTime.Parse. It can be tested in a simple test project that DateTime.Parse does not respect the Z-suffix. This is also discussed here DateTimeConverter converting from UTC string.
I think there would be at least four solutions
1) write a custom model binder. These SOs each show a part of it Custom DateTime model binder in ASP.NET Core 1 (RTM)
https://dotnetcoretutorials.com/2016/12/28/custom-model-binders-asp-net-core/
2) write a custom type converter that overrides the default DateTime converter and checks whether there is a trailing Z. If so, use DateTime.Parse with the DateTimeStyles.AdjustToUniversal. Else fall back to the default implementation. I like this solution but I currently don't know how to replace the default DateTimeConverter.
3) replace all relevant DateTime parameters in the controllers with DateTimeOffset. DateTimeOffset seems to correctly convert the UTC string.
4) use a POST instead of a GET request with JSON in the request body. JSON.net seems to correctly convert the UTC string.
My preferred solution is currently a mixture of 3 and 4, depending on the context.

Rails business hours query for active record

I have two models
OfficeTimeing < ActiveRecord::Base
belongs_to :office
end
Office < ActiveRecord::Base
has_many :office_timings
end
with two fields opening_time and closing_time these fields have string values like "09:00 AM" I want a query how can I find currently open offices I want something like this.
Office.joins(:office_timings).where("Datetime.now > office_timings.opening_time AND office_timings.closing_time > DateTime.now")
I don't know how to compare two times represented as a string without being able to parse them in rails first, however, have you considered storing your opening and closing times in seconds (counting from midnight) rather than strings? That way you would easily be able to write this query.
UPDATE: A few useful methods to achieve this.
To get the current seconds since midnight for a specific time:
seconds = specific_time.seconds_since_midnight
To convert the seconds since midnight into a Time object:
time_instance = Time.at(seconds)
To produce a string in the form of 09:00 AM
time_instance.strftime("%I:%M %p")
Details about Time class.
Details about strftime.
You need to inject Datetime.now into your query using ?:
Office.joins(:office_timings)
.where(
"? > office_timings.opening_time AND office_timings.closing_time > ?",
Datetime.now, Datetime.now
)
Each ? will be safely replaced by the arguments following the query string.
You could also do this directly in Postgres using now(), and make the condition a bit easier to read using BETWEEN:
.where("now() BETWEEN office_timings.opening_time AND office_timings.closing_time")

How do I change the format ActiveRecord expects when parsing dates from a text field in a form?

The problem
I have a Ruby on Rails model with a Date attribute.
In the form for this model, I am using a single text field with a JQuery datepicker to represent this attribute (not a drop down for each of year, month, and day, as is the Rails custom).
The datepicker inserts dates with a mm/dd/yyyy format.
Rails is expecting dates with a dd/mm/yyyy format.
Examples
If a user selects March 12th, 2012, the datepicker puts 03/12/2012, which is interpreted by Rails as December 3rd, 2012.
If a user selects March 20th, 2012, the datepicker puts 03/20/2012, which is interpreted by Rails as the 3rd day of the 20th month of 2012. Since this date doesn't exist, Rails casts this to a nil value (I think).
Question
How do I change the date format Rails uses when parsing this date text field?
Notes:
1) I do not want to change the format of the date the datepicker inserts into the text field,
2) I am not asking about displaying my date attribute in a view.
I initially thought this could be solved through the Rails internationalization features, but it turns out I was wrong.
Ever since Ruby 1.9, the standard format for date parsing is dd/mm/yyyy, so as to better accomodate international users. More details can be found in this SO answer.
That standard is maintained in Rails, as Date.parse is now used to process data from form inputs. Using a before_validation callback won't work because the field is going to be received as nil by the callback method.
Right now there are two gems dealing with this specific issue, namely that date parsing in Rails does not follow the locale settings from I18n.locale. Both seem to work well.
delocalize, by clemens - Seems to have been applied successfully in a decent number or projects and has the highest number of stars at the moment.
i18n_alchemy by carlosantoniodasilva - This one has been released more recently. The author is a Rails core team member, and a very active one at that. Definitely deserves a look.
Since you don't want to change the picker's format, I would suggest you use a hidden field for the actual model property.
For example, add a hidden field for the model's date property, assuming you use a form builder as usual:
f.hidden_field :date
Then for the picker text input, don't bind it to the model's date property. Let's say the hidden field has ID 'modelname_date' and the picker text input has ID 'date_picker', use the following to make it work:
$(function(){
$("#date_picker").datepicker({altField: '#nodelname_date', altFormat: 'dd/mm/yyyy'});
});
In this way the date picker shows the date as 'mm/dd/yyyy' but Rails will see the date as 'dd/mm/yyyy'.
Update:
If you want to work this out on the Rails side, here's another solution I'd suggest:
Add a virtual property to your model: attr_accessor :bad_format_date
Add a before_validation callback in which you parse the input date and assign it to the real field:
before_validation do
self.date = Date.strptime(bad_format_date, "%m/%d/%Y")
end
Then for the form on the view use bad_format_date but initialize it with the date field value (if it's an edit form).
The timeliness gem makes ruby date/time parsing much more customizeable and integrates well with Rails.
Since you're working with Rails, be sure to check out the validates_timeliness project as well by the same guy. It includes all of timeliness plus sophisticated date/time validation methods for ActiveModel.
You could try do something like this.
$(function(){
$('#date_picker').datepicker( {
beforeShowDay: $.datepicker.noWeekends,
showOtherMonths: true,
selectOtherMonths: true,
dateFormat: 'dd-mm-yy',
defaultDate: date,
gotoCurrent: true
});
I just add the following monkey patch to config/time_formats.rb
class Date
class << self
alias :euro_parse :_parse
def _parse(str,comp=false)
str = str.to_s.strip
if str == ''
{}
elsif str =~ /^(\d{1,2})[-\/](\d{1,2})[-\/](\d{2,4})/
year,month,day = $3.to_i,$1,$2
date,*rest = str.split(' ')
year += (year < 35 ? 2000 : 1900) if year < 100
euro_parse("#{year}-#{month}-#{day} #{rest.join(' ')}",comp)
else
euro_parse(str,comp)
end
end
end
end