在Rails中创建随机的DateTime的最佳方法

42

在Ruby/Rails中生成随机DateTime的最佳方法是什么?试图创建一个好的seeds.rb文件。将要像这样使用它:

 Foo.create(name: Faker::Lorem.words, description: Faker::Lorem.sentence, start_date: Random.date)
13个回答

133

以下是如何创建过去10年内的日期:

rand(10.years).seconds.ago

你也可以获取未来的日期:

rand(10.years).seconds.from_now

旧版本的Rails(< 4.1)

在Rails 4.1之前,当您调用.ago时,会将数字转换为秒。关于此问题,请参见Rails PR #12389。 因此,这种方法是可行的:

rand(10.years).ago

rand(10.years).from_now

7
很好。如果你需要过去或未来的时间,可以使用 rand(-5.years..5.years).ago - eprothro
我的答案利用了Rails中从数字转化成秒的隐式转换,当你调用.ago函数时。然而这个特性已经在Rails 4.1版本中被废弃:https://github.com/rails/rails/pull/12389我认为我会把我的答案编辑成:rand(10.years).seconds.ago - Marc O'Morain
为了解决这个弃用问题,你也可以使用 rand(10).years.ago - Michael Saffitz
@MichaelSaffitz,那可能不会按你的预期工作 - 这将给出一个日期,即1年前、2年前、3年前等。 - Marc O'Morain
已更新Rails 4.1信息。 - Marc O'Morain
显示剩余3条评论

36

以下是一组在范围内生成随机整数、数量、时间/日期的方法。

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

现在,您可以进行以下调用。

rand_int(60, 75)
# => 61

rand_price(10, 100)
# => 43.84

rand_time(2.days.ago)
# => Mon Mar 08 21:11:56 -0800 2010

使用Ruby 2.2时出现NoMethodError错误:undefined method `rand_in_range' for main:Object。 - sixty4bit

18

我更喜欢使用 (1..500).to_a.rand.days.ago


这段代码会抛出语法错误(Range类没有rand方法)。 - Harish Shetty
而且,你可以使用 (-200..200).to_a.rand.days.ago 来包括未来的日期。对我的种子数据非常有用。 - Justus Romijn
8
我认为这段没有显式类型转换的代码更漂亮:rand(-200..200).days.ago - loybert
3
Marc的解决方案(https://dev59.com/K3E95IYBdhLWcg3wN7Kv#4886512)更好。这个解决方案每次需要创建随机日期时都会创建一个500项的数组。 - Harish Shetty
1
你可以使用 (1..500).to_a.sample.days.ago。 - msroot

17

你正在使用Faker,为什么不使用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>

当前 Faker 版本:2.11.0


2

这是我使用的内容:

# get random DateTime in last 3 weeks
DateTime.now - (rand * 21)

2

以下是如何在本月创建日期的方法:

day = 1.times.map{ 0+Random.rand(30) }.join.to_i  
rand(day.days).ago

2

另一种使用DateTime的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

1
其他方法:
(10..20).to_a.sample.years.ago

0

没有使用 user faker(因为我正在使用旧版本的 Ruby):

Time.zone.now - rand(16..35.years) - rand(1..31).days

0

我自己没试过,但你可以使用自纪元以来的秒数创建两个日期之间的随机整数。例如,获取上周的随机日期。

end = Time.now
start = (end - 1.week).to_i
random_date = Time.at(rand(end.to_i - start)) + start

当然,最终你会得到一个时间对象而不是日期时间对象,但我相信你可以从这里进行转换。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接