Datetime format Rails - ruby-on-rails

I am having problem understanding datetime format in rails. I have stored a date which is called 'starts_at' and type is datetime using postman.
{
"reservation": {
"starts_at": "2020-1-7 7:00 pm",
"expires_at": "2020-1-7 9:00 pm"
}
}
I want to enter another date and want to validate the date I enter every time be in an interval of 120 minutes after.
So I tried plucking out 'starts_at' from my model 'reservations' and tried to loop through each 'starts_at' date and comparing their difference with my new entered dates' 'starts_at'.
# I have defined scope to pluck the 'starts_at' in reservation.rb
# scope :starts_at, -> { pluck(:starts_at) }
def create
Reservation.starts_at.each do |starts_at|
time_diffs = time_diff_in_minutes(date_time_conversion(starts_at) - params[:starts_at].to_datetime)
if time_diffs < 120
return
end
#reservation = Reservation.new(processed_params)
reservation.save
end
end
private
def date_time_conversion(starts_at)
starts_at.to_datetime
end
def time_diff_in_minutes(time_calc)
(time_calc * 24 * 60).to_s.to_i.abs
end
I have one value in database which has starts_at datetime = "2020-1-7 7:00 pm".
When I run debugger and checked the plucked value it has a format something like
Tue, 07 Jan 2020 18:00:00 +06 +06:00
And the format of the date I entered was something like
Tue, 07 Jan 2020 19:00:00 +0000
I want to understand what does +06 +6:00 means and how does postgresql database store datetime object and return format. Your help shall be highly appreciated. Thank you!

Related

Rails Dynamically return today's date at runtime

For demonstration purposes: say I am including in the module TodayDynamicDate into the model Foo below:
# app/models/concerns/today_dynamic_date.rb
module TodayDynamicDate
extend ActiveSupport::Concern
def todays_date
Date.today
end
end
#app/models/foo.rb
class Foo < ApplicationRecord
include TodayDynamicDate
end
I am wondering if using that mixed in method of #todays_date will work how I want it to.
I want the method #todays_date to dynamically return the date that the method was run. I do not want it to return the static date that the rails server was booted up.
Example:
Say I boot up the server today, Friday, July 1st, 2016. Here is what I expect the method to return today:
Foo.new.todays_date
=> Fri, 01, Jul 2016
The server continues running and it is now Tuesday, July 5th, 2016. That same method is called in the app and here is what I expect it to return:
# dynamically returning the date that the method was called
Foo.new.todays_date
=> Tues, 05, July 2016
I want to ensure that it will not return this:
# returning a static date
Foo.new.todays_date
=> Fri, 01, Jul 2016
Question: Will my implementation return a dynamic date? If it will not return a dynamic date: how would I do that with that mixed-in method todays_date?
Answer is yes. Each call to Date.today will return current date.
todays_date is not a class (what you are referring as static) variable, its a method.

Convert readable time string to datetime

I have an alarm clock app, I want when the user enter's "5:00 PM", the system store it as datetime.
How do I convert '5:00 pm' to a datetime.
If it is already past 5:00 pm and the user enters '5:00 pm', the system should assume the user means tomorrow's '5:00 pm' and return the appropriate datetime.
Thanks to a previous answer, I figure out.
time_string = '5:00 pm' # mock of user input
date_time = DateTime.parse time_string
date_time += 1.day if Time.now > date_time
return date_time

How do I specify a time given a date object?

I am trying to create an object which has both a date field and a time field. I'd like the time field to be generated based on the date in the date field. For example:
SampleObject.new(
date = Date.today #Sat, 28 Dec 2013
time = Date.today.at(5:00pm EST) #Sat, 28 Dec 2013 2013-12-28 17:00:00 -0500 Not valid ruby syntax)
)
How can I make time = line work as intended?
I'd do something like:
DateTime.parse Date.today.to_s + ' 5pm'
#<DateTime: 2013-12-28T17:00:00+00:00 ((2456655j,61200s,0n),+0s,2299161j)>
I am interpreting this question as "a way to set the time of the day on a given date to a given time".
One way you could do it is as follows:
def set_date_and_time(date = Date.today, time = Time.now)
this_day = [date.year, date.month, date.day]
this_time = [time.hour, time.min, time.sec]
Time.new(*this_day, *this_time)
end
Hope this helps.

Parsing a custom DATE_FORMAT with DateTime in Rails

How do I get DateTime to parse a custom date format(i.e. 'x-%Y')?
I've set the format within an initializer with (as per the RoR API):
Time::DATE_FORMATS[:x_year] = 'x-%Y'
Date::DATE_FORMATS[:x_year] = 'x-%Y'
and when I call:
DateTime.strptime('x-2011', 'x-%Y')
The correct result is returned, but
DateTime.parse('x-2011')
Throws an
ArgumentError: invalid date
never heard of such a possibility. However, you could still do something like:
class DateTime
class << self
alias orig_parse parse
end
def self.parse(string, format = nil)
return DateTime.orig_parse(string) unless format
DateTime.strptime(string, Date::DATE_FORMATS[format])
end
end
in your example it might look like that:
Date::DATE_FORMATS.merge!({:xform => "x-%Y"})
DateTime.parse('x-2011', :xform) #=> Sat, 01 Jan 2011 00:00:00 +0000
You could get rid of 'format' attribute and iterate && validate/rescue through DATE_FORMATS instead

Best way to create random DateTime in Rails

What is the best way to generate a random DateTime in Ruby/Rails? Trying to create a nice seeds.rb file. Going to use it like so:
Foo.create(name: Faker::Lorem.words, description: Faker::Lorem.sentence, start_date: Random.date)
Here is how to create a date in the last 10 years:
rand(10.years).ago
You can also get a date in the future:
rand(10.years).from_now
Update – Rails 4.1+
Rails 4.1 has deprecated the implicit conversion from Numeric => seconds when you call .ago, which the above code depends on. See Rails PR #12389 for more information about this. To avoid a deprecation warning in Rails 4.1 you need to do an explicit conversion to seconds, like so:
rand(10.years).seconds.ago
Here are set of methods for generating a random integer, amount, time/datetime within a range.
def rand_int(from, to)
rand_in_range(from, to).to_i
end
def rand_price(from, to)
rand_in_range(from, to).round(2)
end
def rand_time(from, to=Time.now)
Time.at(rand_in_range(from.to_f, to.to_f))
end
def rand_in_range(from, to)
rand * (to - from) + from
end
Now you can make the following calls.
rand_int(60, 75)
# => 61
rand_price(10, 100)
# => 43.84
rand_time(2.days.ago)
# => Mon Mar 08 21:11:56 -0800 2010
I prefer use (1..500).to_a.rand.days.ago
You are using Faker; why not use one of the methods provided by Faker::Date?
# Random date between dates
# Keyword arguments: from, to
Faker::Date.between(from: 2.days.ago, to: Date.today) #=> "Wed, 24 Sep 2014"
# Random date between dates except for certain date
# Keyword arguments: from, to, excepted
Faker::Date.between_except(from: 1.year.ago, to: 1.year.from_now, excepted: Date.today) #=> "Wed, 24 Sep 2014"
# Random date in the future (up to maximum of N days)
# Keyword arguments: days
Faker::Date.forward(days: 23) # => "Fri, 03 Oct 2014"
# Random date in the past (up to maximum of N days)
# Keyword arguments: days
Faker::Date.backward(days: 14) #=> "Fri, 19 Sep 2014"
# Random birthday date (maximum age between 18 and 65)
# Keyword arguments: min_age, max_age
Faker::Date.birthday(min_age: 18, max_age: 65) #=> "Mar, 28 Mar 1986"
# Random date in current year
Faker::Date.in_date_period #=> #<Date: 2019-09-01>
# Random date for range of year 2018 and month 2
# Keyword arguments: year, month
Faker::Date.in_date_period(year: 2018, month: 2) #=> #<Date: 2018-02-26>
# Random date for range of current year and month 2
# Keyword arguments: month
Faker::Date.in_date_period(month: 2) #=> #<Date: 2019-02-26>
current Faker version: 2.11.0
Here is how to create a date in this month:
day = 1.times.map{ 0+Random.rand(30) }.join.to_i
rand(day.days).ago
Another approach using DateTime's advance
def rand_date
# return a random date within 100 days of today in both past and future directions.
n = rand(-100..100)
Date.today.advance(days: n)
end
This is what I use:
# get random DateTime in last 3 weeks
DateTime.now - (rand * 21)
other way:
(10..20).to_a.sample.years.ago
I haven't tried this myself but you could create a random integer between two dates using the number of seconds since epoch. For example, to get a random date for the last week.
end = Time.now
start = (end - 1.week).to_i
random_date = Time.at(rand(end.to_i - start)) + start
Of course you end up with a Time object instead of a DateTime but I'm sure you can covert from here.
As I already mentioned in another question I think the following code-snippet is more consisent regarding the data-types of the parameters and of the value to be returned. Stackoverflow: How to generate a random date in Ruby?
Anyway this uses the rand() method's internal logic what is the random Date or random Time within a span. Maybe someone has a more efficient way to set the default-parameter to (Time.now.to_date) of the method random_date, so it doesn't need this typecasting.
def random_time from = Time.at(0.0), to = Time.now
rand(from..to)
end
# works quite similar to date :)
def random_date from = Date.new(1970), to = Time.now.to_date
rand(from..to)
end
Edit: this code won't work before ruby v1.9.3
You can pass Time Range to rand
rand(10.weeks.ago..1.day.ago)
Output Example:
=> Fri, 10 Jan 2020 10:28:52 WIB +07:00
Without user faker (cause I'm using an old version of ruby):
Time.zone.now - rand(16..35.years) - rand(1..31).days
My 'ish' gem provides a nice way of handling this:
# plus/minus 5 min of input date
Time.now.ish
# override that time range like this
Time.now.ish(:offset => 1.year)
https://github.com/spilliton/ish

Resources