How do I specify a time given a date object? - ruby-on-rails

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.

Related

Datetime format 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!

Calculate closing date with openedon date

I'm doing reccuring deposit calculations, When open reccuring deposit account on that time itself i have set opening date as today's date using before_save. I dono how to calculate account maturity date. Because, in my reccuring deposit i have many fields in my dropdown like 6months, 1year, 2years ... upto 5 years. According to that openedon date i have to close that account or renew it on that maturity date itself.
i have use the below code for openedon date
before_save :set_openedon
def set_openedon
self.openedon = Date.today
end
for example:
for first rd account openedon date is 13/05/2013 and maturity date must be 13/05/2014 for one year.
for second rd account openedon date is 15/09/2012 and maturity date must be 15/09/2014 for two years.
like that i have to calculate maturity date for all the accounts. But i dono how to do.
Kindly help me.
-Thanks in advance.
Rails has quite easy-to-use date operators:
Date.parse('13/05/2013') + 1.year
# => Tue, 13 May 2014
Date.parse('15/09/2012') + 2.years
# => Mon, 15 Sep 2014
Same for 6.months, etc.
Something alike:
def calculate_dates
self.openedon = Date.today
case self.noy
when '1'
self.md = self.openedon+1.year
when '2'
self.md = self.openedon+2.years
when '3'
self.md = self.openedon+3.years
when '4'
self.md = self.openedon+4.years
when '5'
self.md = self.openedon+5.years
else
self.md = self.openedon+6.months
end
end

Rails - How to change created_at time?

In my controller I have:
#konkurrencer = Rating.new(params[:kon])
#konkurrencer.save
#konkurrencer.konkurrencer.rating_score += params[:kon][:ratings].to_i
#konkurrencer.konkurrencer.ratings += 1
#konkurrencer.created_at = Time.now.strftime("%Y-%m-%d 00:00:00")
#konkurrencer.save
When I create a new item it the created_at column is:
2012-02-27 16:35:18
I would expect it to be:
2012-02-27 00:00:00
Your problem is that strftime only formats the time, it doesn't actually change the time.
So when you do Time.now, that returns the time. Strftime only changes the way that its represented.
If you wanted to change the created_at date to "2012-02-27 00:00:00", just pass that in to #koncurrencer.created_at
#koncurrencer.created_at = "2012-02-27 00:00:00"
That should do it.
In response to your question:
What you were doing should work just fine then. In fact you can just say:
#koncurrencer.created_at = Time.now
#koncurrencer.save
and that should work just fine.
If you wanted to always have the time be at the beginning of the day you could use Date.today instead of Time.now since that always returns the time component of the Date as "00:00:00"
Here is what you want:
#koncurrencer.created_at = Date.today
#koncurrencer.save
That should be more clear.
If you want to set the time always to "00:00:00", you can go by this:
t = Time.now
=> 2012-02-27 17:46:38 +0100
t2 = Time.parse("00:00:00", t)
=> 2012-02-27 00:00:00 +0100

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

Converting twitter post dates to datetime in rails

I am trying to convert the twitter post dates into datetime objects but for some reason they are not converting correctly. If I do this:
d = '12:06 AM Oct 15th'
and
d = DateTime.parse(d)
or
Tweet.new :body => "test", :created_at => d
then the date ends up Sun Nov 15 00:06:00 -0500 2009. All dates are converting and containing the month of November. Am I totally missing something?
DateTime.parse expects the passed in string to be in a standard format. Since that is not the case with your strings, you'll have to use DateTime.strptime and pass it your string representation of date/time, along with the corresponding format string. In your case something like this should work:
d = DateTime.strptime '12:06 AM Oct 15th', '%H:%M %p %b %d'
d.to_s # => "2009-10-15T00:06:00+00:00"
You can check the documentation to see what each of the formatting directions means.
Always always always use the Chronic gem. Will solve all your problems when it comes to date/time parsing: http://github.com/mojombo/chronic
You might be able to get away with mangling it slightly and then using the parser:
s = '12:06 AM Oct 15th'
d = DateTime.parse(s.sub(/(\w\w\w) /, '\1'))
puts d.to_s
# => 2009-10-15T00:06:00+00:00

Resources