Rails: Update only hour and minute of datetime field - ruby-on-rails-4

There is a field start_time of type datetime in processes table. The initial value is set to Time.zone.now. After that the user is not allowed to change the date, only hour and minute of that start_time field is allowed to change.
So, an edit form is provided to the user that shows only hour:minute like "22:43" but when the form is submitted the field value is changed to current date and time. In the controller I've used the standard rails statement to update the values:
#process = Process.find(params[:id])
#process.update(process_params)
In the params I get the start_time as "20:40"
Also tried the change method but it not saving the changes instead it rollbacks.
hour_minute = params[:process][:start_time].split(":")
#process.start_time.change({hour: hour_minute[0], min: hour_minute[1]})
I want to update only hour and minute of the field date should remain the same.

change method return changed time or date but didn't update active record it self.
you can do this for update.
hour_minute = params[:process][:start_time].split(":")
#process.update(start_time: #process.start_time.change(hour: hour_minute[0], min: hour_minute[1]))
Hope, this will help you.

Related

Django query by separate date and time fields (how to perform conditional order_by)

I have a Meeting model. It has a separate date and time field, the reason why it is not a single datetime field is that the time is allowed to be null.
If I used a single datetime field and set the hours/minutes to 00:00 if no time is given, then I can't distinguish that from a meeting set at 00:00. And some unusual sentinel value like 13:37:42 as no meeting is a weird hack.
Here's the model:
class Meeting(models.Model):
meeting_date = models.DateField(db_index=True)
meeting_time = models.TimeField(db_index=True, null=True, blank=True)
Now the problem comes in to filter by a given date/time.
So I think the solution is to filter by date, then order by the time. E.g. to get the latest meeting that is before now:
from datetime import datetime
now = datetime.now()
prev_meeting = (
Meeting.objects.filter(meeting_date__lte=now.date())
.order_by('-meeting_date', f'meeting_time <= {now.time()}', '-meeting_time')
.first()
)
The f'meeting_time <= {now.time()}' is the part I don't know how to do with the django ORM, but I know how to do with SQL. the Django Docs do not mention conditional ordering.
The solution I came up with is to use a single datetime field to store the date/time, and then instead of a sentinel time value, I have an additional boolean value storing whether the time was set or not. If the time was not set, then then datetime time is 00:00 and the time_was_set field is set to False.

Comparing Date to Minimum Future Value in Other Model

I have two django models that define:
Item = A set of items with an expiry date.
Event = A set of events that have a start and end date.
My aim is that when the item is displayed, its expiry date is shown conditionally formatted, based on whether that item expires after the next event's end date but before the following events end date (so warning when it's due to expire.)
The problem becomes, how best to manage this feat?
If I was directly accessing the database, I'd be using subqueries to get the minimum end date still in the future, and then comparing that to the expiry date on an if basis to swap the formatting.
From research, I'm coming to the conclusion that this is best handled in the view logic, rather than trying to set a method in either of the models, but I don't know how best to get this to splice together so I can return the value of my minimum future date and my itemlist object from the Item model.
The current view is pretty simple at this stage (it will have more filtering options later):
def itemlist(request):
item_list = Item.objects.all
return render(request, "itemlist.html", {'item_list': item_list})
but I cant see a way of easily returning a django equivalent of something like what I'd do in straight SQL:
select item from items where status != expired and expiry_date <= (select min(end_date) from events where end_date >= getdate() )
EDIT: Since I've written this, I've realised the comparison for what I want is a little more complex, as it's not the minimum date, it's the next to minimum.
For Item A, expiry_date 01/05/19
Event A: end_date 25/04/19
Event B: end_date 10/05/19
What I need it to do is check the events when reading back the item list, see that Item A's expiry date is after the next event.end_date for event A, but is before the event.end_date for event B, so set a flag for using conditional formatting on the template's expiry date display.
Eventually, I suppose, the wish list is to also be able to say for every item "what's the latest event I can renew this item before it expires if there's an event in the list after its expiry time."
I could not completely understand your requiremets from your description, but you can use subqueries in Django as well. If you filter like this:
now = datetime.datetime.utcnow()
Item.objects.annotate(last_event_time=Subquery(Event.objects.filter(end_date__gt=now).values('end_date').order_by('-end_date')[:1]))
Each item in the resulting queryset will have last_event_time field, which would keep the latest event end_date field.
You can also use this field in further filtering, using F expressions:
Item.objects.annotate(last_event_time=Subquery(Event.objects.filter(end_date__gt=now).values('end_date').order_by('-end_date')[:1])).filter(expiry_date__lte=F('last_event_time'))

how to grab the hour from a timefield - django

I have a model and form with a TimeField and I want to make a change for the hour once the timefield is extracted from the form that was submitted and stored. I want to update the hour in the time. can anyone help me with this...
here is the view
start_time = cd['start_time']
hour = start_time.hour
new_hour = hour - int(alert)
update_time = start_time
update_time.hour = new_hour
update_time.save()
So the start_time is a timefield that submitted.
I want to grab the hour from that start time to change it. how can i do that...
this is the error essage I am getting:
attribute 'hour' of 'datetime.time' objects is not writable
I want to grab the hour from the original time and updated/change it
datetime instances are immutable, but there is a method to get a new instance with one (or serveral) of the fields replaced with a different value. It's documented here: https://docs.python.org/3/library/datetime.html#datetime.datetime.replace
So your example would become something like this:
start_time = cd['start_time']
update_time = start_time.replace(hour=start_time.hour - int(alert))
I'm not sure why you are calling save on update time. I'm assuming that's a mistake in your example.

sitecore 8 item created time is returning different time

In item's statistics section the created time is 15:19 but item.Statistics.created gives 14:19 am. A time difference of 1 hour is there. How can I get time that is shown in Statistics section?
The date which Sitecore saves in the database is always ISO Date. There are many options you can use to get your local time.
E.g. you can use ToLocalTime() method of DateTime, so:
item.Statistics.Created.ToLocalTime()
Or when you get a value from a field:
var dateField = (DateField)item.Fields["Date"];
var itemDate = Sitecore.DateUtil.IsoDateToDateTime(dateField.Value);
You can also look at other methods of DateUtil class, like ToServerTime().

Add an IntegerField to a Datefield in a Django template

I'm trying to display the expiry date of a bonus from within a Django template. At the moment the opening_date is stored as a datefield and we store the bonus term as an integerfield. Unfortunately just trying to add the bonus term to the opening date fails and the furthest I have got so far is:
{{product_form.instance.opening_date|add:product_form.instance.bonus_term}}
I have tried just adding it to the month but unfortunately I need the whole date returned to display.
For a better idea of what I want is say the opening date was 01/01/2012 and the bonus term was 12, I want to display the expiry date of 01/01/2013. I realise this is probably better off being in the database but due to the way it has been previously set up there is a large amount of existing data that wouldn't have it.
Thanks.
I think that, for your scenario, the most elegant solution is to create a model method in your model that calcule expire date, then call the method in template:
In model:
class product(models.Model):
opening_date = ...
bonus_term = ...
def expire_date( self ):
return self.opening_date + timedelta( days = self.bonus_term )
In template:
{{product_form.instance.expire_date}}
I'm sure that you will call this method in more other lines of your code.