Change datetime to current user UTC - ruby-on-rails

I am trying to change datetime to users UTC.
e.g
date = anydate (2017-11-03)
time = currenttime (Time.now)
Time.zone = current_user.time_zone
Required = date + time (to current_user.timezone)

You can parse date & time in the user's time zone:
date = '2017-11-03'
time = Time.now
Time.zone = current_user.time_zone
required = Time.zone.parse(date + ' ' + time.strftime('%H:%M:%S'))

date = "2017-11-03"
user_date = date.to_datetime
zone = current_user.time_zone
user_date.in_time_zone(zone)
for example: -
"2017-11-03".to_datetime.in_time_zone("Chennai")
=> Fri, 03 Nov 2017 05:30:00 IST +05:30

Related

Ruby difference between two dates

I need to check the difference between two date and check if there is 24 hours or more. I am having trouble in calling the to_time method of the date object. This to_time method is turning the minutes and seconds if the current date to 00:00:00.
Example:
date = Date.rfc3339('2017-08-16T17:55:49.000-03:00')
=> #<Date: 2017-08-16 ((2457982j,0s,0n),+0s,2299161j)>
date.to_time
2017-08-16 00:00:00 -0300
(( Date.today.to_time - date.to_time)/3600).round
=> 24
Date does not include Time. Use DateTime instead.
require 'date'
dt = DateTime.rfc3339('2017-08-16T17:55:49.000-03:00')
puts (Time.now - dt.to_time)/(60*60) > 24
You can do:
datetime_1 = DateTime.parse("2017-08-17T13:36:03-04:00")
datetime_2 = DateTime.parse("2017-08-16T13:33:03-04:00")
greatest_datetime = [datetime_1, datetime_2].max
smallest_datetime = [datetime_1, datetime_2].min
(greatest_datetime - 1.day) > smallest_datetime

Ruby DateTime: Get next 5:15pm (or similar)

So, given a DateTime object, and a fixed time, I want to get the next occurrence of the fixed time after the given DateTime object.
For example, given the date of 14th March, 2016, 4:00pm, and the time of 5:15pm, I want to return 14th March, 2016 5:15pm.
However, given the date of 14th March, 2016, 6:00pm, and the time of 5:15pm, I want to return 15th March, 2016, 5:15pm, since that's the next occurrence.
So far, I've written this code:
# Given fixed_time and date_time
new_time = date_time
if fixed_time.utc.strftime("%H%M%S%N") >= date_time.utc.strftime("%H%M%S%N")
new_time = DateTime.new(
date_time.year,
date_time.month,
date_time.day,
fixed_time.hour,
fixed_time.min,
fixed_time.sec
)
else
next_day = date_time.beginning_of_day + 1.day
new_time = DateTime.new(
next_day.year,
next_day.month,
next_day.day,
fixed_time.hour,
fixed_time.min,
fixed_time.sec
)
end
# Return new_time
It works, but is there a better way?
I would construct the new date time just once and add 1 day if needed:
# Given fixed_time and date_time
new_date_time = DateTime.new(
date_time.year,
date_time.month,
date_time.day,
fixed_time.hour,
fixed_time.min,
fixed_time.sec
)
# add 1 day if new date prior to the given date
new_date_time += 1.day if new_date_time < date_time
Here's a little stab at refactoring it to remove some of the redundancy:
# Given fixed_time and date_time
base_date = date_time.to_date
if fixed_time.to_time.utc.strftime("%T%N") <= date_time.to_time.utc.strftime("%T%N")
base_date = base_date.next_day
end
new_time = DateTime.new(
base_date.year,
base_date.month,
base_date.day,
fixed_time.hour,
fixed_time.min,
fixed_time.sec
)
# Return new_time
The biggest changes are that the base_date is determined before the new_time is created, so that it can be used there.
I also used the next_day method on DateTime to get the next day, and used the "%T" format specifier as a shortcut for "%H:%M:%S"
Here's a little test program that to show that it works:
require "date"
def next_schedule(fixed_time, date_time)
# Given fixed_time and date_time
base_date = date_time.to_date
if fixed_time.to_time.utc.strftime("%T%N") <= date_time.to_time.utc.strftime("%T%N")
base_date = base_date.next_day
end
new_time = DateTime.new(
base_date.year,
base_date.month,
base_date.day,
fixed_time.hour,
fixed_time.min,
fixed_time.sec
)
# Return new_time
end
StartTime = DateTime.strptime("2016-02-14 17:15:00", "%F %T")
Dates = [
"2016-03-14 16:00:00",
"2016-03-14 18:00:00"
]
Dates.each do |current_date|
scheduled = next_schedule(StartTime, DateTime.strptime(current_date, "%F %T"))
puts "Scheduled: #{scheduled.strftime('%F %T')}"
end
The output of this is:
Scheduled: 2016-03-14 17:15:00
Scheduled: 2016-03-15 17:15:00
It's using the test cases described in the question, and it gets the expected answers.

Ruby how can i get date of Monday after a given date

Given A Day i-e Monday and a Date e.g: Sat, 09 Aug 2014
how can i get the date of Monday coming immediately after given Date
Update:
def get_date_after(date, day)
return date if date.wday == day.to_date.wday
days_difference = (date - day.to_date).to_i
result = day.to_date + days_difference + (day.to_date.wday - date.wday)
result = result + 1.week if result.to_date < date
end
I was looking for something like above method, calling it would return the date of the day passed coming immediately after the date passed
get_date_after(DateTime.parse("15/09/2014").to_date, "Wednesday") #=> 17/09/2014
The chronic gem allows you to parse date expressions, e.g. Chronic.parse("next Monday"). You can add a reference date with the now option. Here's how it could be used for your method:
def get_date_after(date, day)
Chronic.parse("next #{day}", now: date)
end
In rails you can do it this way
Date.today.next_week(day = :monday)

How do I create a date object from a URL?

I have a date paramater in my URL:
http://localhost:3000/restaurants/1/restaurant_stats.pdf?date=2013-05-02
I want to use this date if the parameter exists otherwise use today's date.
if params[:date]
date = Date.new(params[:date].to_i)
else
date = Date.today
end
The above code doesnt work. It sets the date to Jan 01 of the year specified.
if params[:date]
date = Date.parse(params[:date])
else
date = Date.today
end

How can I find records from today, yesterday and so on with Ruby on Rails?

I want to find all records, say Posts, created today with Ruby on Rails, then all Posts created yesterday, and so on… how should I do?
Thank you,
Kevin
Try this:
#Today
Posts.find(:all, conditions: { :created_at => Date.today...Date.today + 1 })
#Yesterday
Posts.find(:all, conditions: { :created_at => Date.today - 1...Date.today })
Or this (preferable, in my opinion):
#Today
Posts.find(:all, conditions: ["DATE(created_at) = ?", Date.today] )
#Yesterday
Posts.find(:all, conditions: ["DATE(created_at) = ?", Date.today - 1] )
As a rule I store all dates on my server in UTC timezone and let the UI handle any timezone conversion.
To get the sort of query you are after to work correctly I had to massage the incoming date into a
UTC specific time range first.
require 'date'
class Post < ActiveRecord::Base
def self.created(a_date)
return Post.where(created_at: to_timerange(a_date))
end
private
def self.to_timerange(a_date)
raise ArgumentError, "expected 'a_date' to be a Date" unless a_date.is_a? Date
dts = Time.new(a_date.year, a_date.month, a_date.day, 0, 0, 0).utc
dte = dts + (24 * 60 * 60) - 1
return (dts...dte)
end
end
This then allows you to call
# today
posts = Post.created(Date.today)
# yesterday
posts = Post.created(Date.today - 1)
To query using a range I prefer the following:
yesterday = Date.yesterday
start = yesterday.beginning_of_day
#Fri, 27 Nov 2020 00:00:00 UTC +00:00
end = yesterday.end_of_day
# Fri, 27 Nov 2020 23:59:59 UTC +00:00 - the value here is one second before midnight
# meaning we should use an inclusive range using two dots:
range = start..end
Post.where(created_at: range)

Resources