23

Any easy way to check if a variable / object is of Date / Time / DateTime type? Without naming all the types

Aurimas
  • 2,577
  • 5
  • 26
  • 37
  • Why do you want to check it? Some of them share methods that allows you to use them without knowing what type it is? – Leonel Galán Jun 22 '16 at 19:32
  • I have a Rails active record that has 2 attributes that are Time, I need to do a `.map` to convert each attribute that is Time to datetime. Would be great that in the future the type of time could be changed in the DB, hence the question.. but I guess I'm just kinda curious now... – Aurimas Jun 22 '16 at 19:36
  • Curious why the downvote? .. Is there a way to ask the people who downvoted? I must have made somebody furious in this `forum` – Aurimas Jun 22 '16 at 20:29
  • No you can't ask why someone down voted it... Don't let it get to you, I'm confused a lot of the time people down vote things as well. You asked a simple question and got straight to the point... someone who doesn't like that style ( i.e. they want a draw out reason of why you just asked your question. not necessary IMO) could have down voted it. But as others have noted the `. instance_of?` or `.class` is probably the best solution to finding the class of an object in Ruby. GL with your work! – Tim Mee Jun 22 '16 at 21:46

9 Answers9

33

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 
snorkpete
  • 14,278
  • 3
  • 40
  • 57
zeke
  • 3,603
  • 2
  • 26
  • 41
6

you can inspect the class of a object doing

object.class

It should return Date, String or whatever it is. You can also do the reverse and check if an object is an instance of a class:

object.instance_of?(class)

where class is the one you want to check (String, Date), returning true/false

Ronan Lopes
  • 3,320
  • 4
  • 25
  • 51
5

If you want to verify the object, here you have a couple of examples:

nisevi@nisevi ~:$ irb
irb(main):001:0> require "date"
=> true
irb(main):002:0> require "time"
=> true
irb(main):003:0> d = Date.new
=> #<Date: -4712-01-01 ((0j,0s,0n),+0s,2299161j)>
irb(main):004:0> dt = DateTime.new
=> #<DateTime: -4712-01-01T00:00:00+00:00 ((0j,0s,0n),+0s,2299161j)>  
irb(main):005:0> t = Time.new
=> 2016-06-22 21:33:09 +0200

irb(main):014:0> d.instance_of?(Date)
=> true
irb(main):015:0> d.instance_of?(DateTime)
=> false
irb(main):016:0> d.instance_of?(Time)
=> false
irb(main):017:0> dt.instance_of?(DateTime)
=> true
irb(main):018:0> dt.instance_of?(Time)
=> false
irb(main):019:0> dt.instance_of?(Date)
=> false
irb(main):020:0> t.instance_of?(Time)
=> true
irb(main):021:0> t.instance_of?(DateTime)
=> false
irb(main):022:0> t.instance_of?(Date)
=> false

Also I think that TimeZone is from Rails and not from Ruby.

As per your comment if you want to convert a Time object to DateTime I think that something like this it should work:

def time_to_datetime time
  return time.to_datetime if time.instance_of?(Time)
  false
end

Here you have some code:

irb(main):026:0> t.instance_of?(Time)
=> true
irb(main):027:0> t.methods.sort.to_s
=> "[:!, :!=, :!~, :+, :-, :<, :<=, :<=>, :==, :===, :=~, :>, :>=, :__id__, :__send__, :asctime, :between?, :class, :clone, :ctime, :day, :define_singleton_method, :display, :dst?, :dup, :enum_for, :eql?, :equal?, :extend, :freeze, :friday?, :frozen?, :getgm, :getlocal, :getutc, :gmt?, :gmt_offset, :gmtime, :gmtoff, :hash, :hour, :httpdate, :inspect, :instance_eval, :instance_exec, :instance_of?, :instance_variable_defined?, :instance_variable_get, :instance_variable_set, :instance_variables, :is_a?, :isdst, :iso8601, :itself, :kind_of?, :localtime, :mday, :method, :methods, :min, :mon, :monday?, :month, :nil?, :nsec, :object_id, :private_methods, :protected_methods, :public_method, :public_methods, :public_send, :remove_instance_variable, :respond_to?, :rfc2822, :rfc822, :round, :saturday?, :sec, :send, :singleton_class, :singleton_method, :singleton_methods, :strftime, :subsec, :succ, :sunday?, :taint, :tainted?, :tap, :thursday?, :to_a, :to_date, :to_datetime, :to_enum, :to_f, :to_i, :to_r, :to_s, :to_time, :trust, :tuesday?, :tv_nsec, :tv_sec, :tv_usec, :untaint, :untrust, :untrusted?, :usec, :utc, :utc?, :utc_offset, :wday, :wednesday?, :xmlschema, :yday, :year, :zone]"
irb(main):028:0> t.to_datetime
=> #<DateTime: 2016-06-22T21:33:09+02:00 ((2457562j,70389s,767750206n),+7200s,2299161j)>
irb(main):029:0> t.instance_of?(Time)
=> true
irb(main):030:0> t.instance_of?(DateTime)
=> false
irb(main):031:0> tdt = t.to_datetime
=> #<DateTime: 2016-06-22T21:33:09+02:00 ((2457562j,70389s,767750206n),+7200s,2299161j)>
irb(main):032:0> tdt.instance_of?(Time)
=> false
irb(main):033:0> tdt.instance_of?(DateTime)
=> true

Here you have some interesting info In Ruby on Rails, what's the difference between DateTime, Timestamp, Time and Date?

Community
  • 1
  • 1
nisevi
  • 627
  • 1
  • 10
  • 27
4

In rails 5.2+ you can test if an object is_a?

Date.today.is_a?(Date) # -> true
Date.today.is_a?(DateTime) # -> false
CamiloVA
  • 651
  • 5
  • 11
1

I do not think there is an "easy way" without typing all the type variations of Date / Time / DateTime / Timezone out.

The simplest and fastest way is to do dateTime.is_a?(DateTime) or Time.is_a?(Time), repeat ad nausem - which all will return a boolean.

Conversely you can also use kind_of?.

You might also be able to find a framework that has a function to check all of the variations of date and time.

1

To find what class the module (or method) is located in, you use the .class function, this allows you to inspect Ruby objects to find out what class they are located in. The syntax for this looks like this: object.class. Here's some examples:

irb(main):001:0> require 'date'
=> true
irb(main):002:0> d = Date.today
=> #<Date: 2016-06-22 ((2457562j,0s,0n),+0s,2299161j)>
irb(main):003:0> t = Time.now
=> 2016-06-22 18:52:24 -0500
irb(main):004:0> t.class
=> Time
irb(main):005:0> d.class
=> Date

As you can see this is an easy and simple way to find the class that the object is in.

13aal
  • 1,634
  • 1
  • 21
  • 47
1

The Column objects returned by columns and columns_hash can then be used to get information such as the data type and default values, for example:

User.columns_hash['email'].type
=> :string
User.columns_hash['email'].default
=> nil
User.columns_hash['email'].sql_type
=> "varchar(255)"

(Source)

Stephen Rauch
  • 47,830
  • 31
  • 106
  • 135
wuyuedefeng
  • 61
  • 1
  • 4
1

In Rails you can use the acts_like? method. Time does not act_like_date? so you need to check for date and time.

var.acts_like?(:date) || var.acts_like?(:time)
Lief
  • 535
  • 3
  • 5
  • 14
0

For the sake of completion, another option would be:

def responds_to_datetime?(date)
  true if date.to_datetime rescue false
end