Skip to content

Instantly share code, notes, and snippets.

@d11wtq
Created March 20, 2013 03:18
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save d11wtq/5202045 to your computer and use it in GitHub Desktop.
Save d11wtq/5202045 to your computer and use it in GitHub Desktop.
Like Timecop, but simpler.
class Time
class << self
attr_accessor :mock_time
def now_with_mock_time
@mock_time || now_without_mock_time
end
alias_method_chain :now, :mock_time
# Freeze Time.now, DateTime.now and Date.today to the given Time
# This method operates only in the context of a provided block.
#
# Example Usage:
#
# Time.be(:utc, 2007, 5, 2) do
# puts Time.now
# end
# # => 2007-05-02 00:00:00 UTC
#
# Time.be(:local, 2007, 5, 2, 17, 31, 2) do
# puts Time.now
# end
# # => 2007-05-02 17:31:02 +1000
#
# It works with DateTime.now too:
#
# Time.be(Time.utc(2012, 1, 1)) do
# puts DateTime.now
# end
# # => 2012-01-01T00:00:00+00:00
#
# And also with Date.today:
#
# Time.be(:utc, 2000, 2, 14) do
# puts Date.today
# end
# # => 2000-02-14
#
# Blocks can be nested together:
#
# Time.be(:utc, 2007, 5, 2) do
# Time.be(:local, 2007, 5, 2, 17, 31, 2) do
# puts Time.now
# end
# puts Time.now
# end
# # => 2007-05-02 17:31:02 +1000
# # => 2007-05-02 00:00:00 UTC
#
# And lastly, you can take advantage of ActiveSupport's Numeric helpers:
#
# Time.be(:utc, 2000, 1, 1) do
# Time.be(4.days.from_now.utc) do
# puts Time.now
# Time.be(3.minutes.ago.utc) do
# puts Time.now
# end
# end
# end
# # => 2000-01-05 00:00:00 UTC
# # => 2000-01-04 23:57:00 UTC
#
def be(a_time_or_type, *args)
raise ArgumentError, "Time.be requires a block, but none was given" unless block_given?
a_time = if a_time_or_type.kind_of?(Time)
a_time_or_type
else
unless [:utc, :local].include?(a_time_or_type)
raise ArgumentError, "First argument must either by a Time, :utc or :local"
end
Time.send(a_time_or_type, *args)
end
original_mock_time = @mock_time
@mock_time = a_time
yield
ensure
@mock_time = original_mock_time
end
# Simply freeze the time at whatever time it is now
def freeze(&block)
be(Time.now, &block)
end
end
end
class DateTime
class << self
def now(*)
Time.now.to_datetime
end
end
end
class Date
class << self
def today(*)
Time.now.to_date
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment