Get time from DateTime Variable in Ruby
Try DateTime#strftime.
DateTime.now.strftime("%H:%M")
# => "12:17"
Rails: Get the time from a datetime
strftime will do it.
t = Time.now
t.strftime("%I:%M%p")
All other attributes here:
http://www.wetware.co.nz/blog/2009/07/rails-date-formats-strftime/
Ruby parse DateTime with variable
In your third call, you use the literal string "datetime" rather than the value of your datetime
variable. You can use string interpolation to use the variable's value:
DateTime.parse("#{datetime} 9pm")
In this case, the "9pm" is ignored since it doesn't make sense added to the end of an existing date but this is why the initial attempt wasn't working. Interpolation is generally a solution for using a variable's value rather than its name.
If your goal is to change the time of an existing date, use the change method:
datetime.change(hour:21)
Convert to/from DateTime and Time in Ruby
You'll need two slightly different conversions.
To convert from Time
to DateTime
you can amend the Time class as follows:
require 'date'
class Time
def to_datetime
# Convert seconds + microseconds into a fractional number of seconds
seconds = sec + Rational(usec, 10**6)
# Convert a UTC offset measured in minutes to one measured in a
# fraction of a day.
offset = Rational(utc_offset, 60 * 60 * 24)
DateTime.new(year, month, day, hour, min, seconds, offset)
end
end
Similar adjustments to Date will let you convert DateTime
to Time
.
class Date
def to_gm_time
to_time(new_offset, :gm)
end
def to_local_time
to_time(new_offset(DateTime.now.offset-offset), :local)
end
private
def to_time(dest, method)
#Convert a fraction of a day to a number of microseconds
usec = (dest.sec_fraction * 60 * 60 * 24 * (10**6)).to_i
Time.send(method, dest.year, dest.month, dest.day, dest.hour, dest.min,
dest.sec, usec)
end
end
Note that you have to choose between local time and GM/UTC time.
Both the above code snippets are taken from O'Reilly's Ruby Cookbook. Their code reuse policy permits this.
Where Ruby get date, time from?
https://ruby-doc.org/core-2.2.0/Time.html#method-c-new
Unless given a time during initialization of a Time instance, Ruby uses the type from the system it is running on.
If you want the current time on a user's device in a Rails project, you'll need to capture it with Javascript and pass it back to your Rails application.
How to check if variable is Date or Time or DateTime in Ruby?
Another option:
def is_datetime(d)
d.methods.include? :strftime
end
Or alternatively:
if d.respond_to?(:strftime)
# d is a Date or DateTime object
end
How do I get the current Date/time in DD/MM/YYYY HH:MM format?
The formatting can be done like this (I assumed you meant HH:MM instead of HH:SS, but it's easy to change):
Time.now.strftime("%d/%m/%Y %H:%M")
#=> "14/09/2011 14:09"
Updated for the shifting:
d = DateTime.now
d.strftime("%d/%m/%Y %H:%M")
#=> "11/06/2017 18:11"
d.next_month.strftime("%d/%m/%Y %H:%M")
#=> "11/07/2017 18:11"
You need to require 'date'
for this btw.
Ruby on Rails parsing time from datetime, not as string
Is there a specific reason you want a Time object?
Just so we're clear, the Time class in Ruby isn't just "DateTime without the date." As "What's the difference between DateTime and Time in Ruby?" explains, "Time is a wrapper around POSIX-standard time_t, or seconds since January 1, 1970." Like DateTime, a Time object still has year, month, and day, so you don't really gain anything by using Time instead. There's not really a way to represent just hour and minute using either Time or DateTime.
The best you could do with Time, I think, would be this:
date_time = DateTime.now
seconds = date_time.hour * 60 * 60 + date_time.minute * 60
time = Time.at(seconds)
# => 1970-01-01 09:58
...but then you still have to call time.hour
and time.min
to get at the hour and minute.
If you're just looking for a lightweight data structure to represent an hour and minute pair, though, you might as well just roll your own:
HourAndMinute = Struct.new(:hour, :minute) do
def self.from_datetime(date_time)
new(date_time.hour, date_time.minute)
end
end
hm = HourAndMinute.from_datetime(DateTime.now)
# => #<struct HourAndMinute hour=15, minute=58>
hm.to_h
# => { :hour => 15, :minute => 58 }
hm.to_a
# => [ 15, 58 ]
Edit re:
I have a variable that stores an appointment -- this variable is a DateTime object. I have two table fields that store the start and end times of a location. I need to check if the time scheduled for that appointment lies between the start and end times.
Ah, it seems you had a bit of a XY problem. This makes a lot more sense now.
Absent any more information, I'm going to assume your "fields that store the start and end times of a location" are MySQL TIME
columns called start_time
and end_time
. Given MySQL TIME columns, Rails casts the values to Time objects with the date component set to 1/1/2000. So if your database has the values start_time = '09:00'
and end_time = '17:00'
, Rails will give you Time objects like this:
start_time = Time.new(2000, 1, 1, 9, 0) # => 2000-01-01 09:00:00 ...
end_time = Time.new(2000, 1, 1, 17, 0) # => 2000-01-01 17:00:00 ...
Now you say your appointment time is a DateTime, so let's call it appointment_datetime
and suppose it's at 10:30am tomorrow:
appointment_datetime = DateTime.new(2014, 11, 18, 10, 30) # => 2014-11-18 10:30:00 ...
So now to rephrase your question: How do we tell if the time part of appointment_datetime
is between the time part of start_time
and end_time
. The answer is, we need to either change the date part of start_time
and end_time
to match the date part of appointment_datetime
, or the other way around. Since it's easier to change one thing than two, let's do it the other way around and change appointment_datetime
to match start_time
and end_time
(and, since those two are Time objects, we'll create a Time object):
appointment_time = DateTime.new(2000, 1, 1, appointment_datetime.hour, appointment_datetime.minute)
# => 2000-01-01 10:30:00 ...
Now we can compare them directly:
if appointment_time >= start_time && appointment_time <= end_time
puts "Appointment time is good!"
end
# Or, more succinctly:
if (start_time..end_time).cover?(appointment_time)
puts "Appointment time is good!"
end
You would, of course, want to wrap all of this up in a method, perhaps in your Location model (which, again, I'm assuming has start_time
and end_time
attributes):
class Location < ActiveRecord::Base
# ...
def appointment_time_good?(appointment_datetime)
appointment_time = DateTime.new(2000, 1, 1,
appointment_datetime.hour, appointment_datetime.minute)
(start_time..end_time).cover?(appointment_time)
end
end
location = Location.find(12) # => #<Location id: 12, ...>
location.appointment_time_good?(appointment_time) # => true
I hope that's helpful!
P.S. Another way to implement this would be to ditch the date/time objects entirely and do a straight numeric comparison:
def appointment_time_good?(appointment_datetime)
appointment_hour_min = [ appointment_datetime.hour, appointment_datetime.minute ]
appointment_hour_min >= [ start_time.hour, start_time.min ]
&& appointment_hour_min <= [ end_time.hour, end_time.min ]
end
Related Topics
Approach for Installing System Service Implemented as Ruby Gem
How to Get Ruby-Debug-Ide to Work
Should Rbenv Be Installed System-Wide, or at a User Level
Heroku Won't Reset My Database
Capturing Logger Output Inside a Method
Fast Fuzzy/Approximate Search in Dictionary of Strings in Ruby
Gem And/Or Ruby on Rails Broke All of a Sudden, Anyone Know What Happened
What's Gem Can Operate Excel on Linux
How to Remotely Inspect the Data in My Rediscloud Dbs
Generate String for Regex Pattern in Ruby
Ruby on Rails Triggers Update on Serialized Attribute Every Time
How to Find Out Why a Gem Bundle Has Locked a Gem at a Specific Version
Rails 3.1 Rspec Creating Test Case Validate Field for Model
Vim Syntax Highlighting for Ruby 1.9
Carrierwave: Create 1 Uploader for Multiple Types of Files
Lion: Problem with Rvm Installing Rubies - Problem Related to Openssl