Ruby - 如何查找给定小时的NEXT事件?

时间:2017-03-31 00:48:59

标签: ruby-on-rails ruby date datetime time

我想返回一个Ruby Time对象(毫秒),表示给定DateTime的下一个X小时。

下一个凌晨5点的例子

  • 如果目前是3/28的晚上9点,则NEXT 5am将是3/29 5am
  • 如果目前是3月29日早上6点,那么下午5点将是3/30凌晨5点

代码明智:

# for the below attribute
@object.created_at
=> "2017-03-28 21:00:00"

# given the definition of the next X hour in question
next_hour_to_find = 5 # for 5am

# what's the equation to produce 3/29 5am?

我想要一些灵活的东西,如果next_hour_to_find = 14那么该函数将能够找到下一个下午2点。不用担心时区,这都在@object.created_at的时区范围内。

我目前的想法如下,但我觉得有一种更清洁的方式......

if @object.created_at.hour > next_hour_to_find
  # the next X hour is always going to occur on the next date
  date = (@object.created_at + 1.days).strftime(...) # get the date out
else
  # the next X hour is always going to occur on the same date
  date = (@object.created_at).strftime(...) # get the date out
end

# now that we have a date in a string, we have to append that string with the next_hour_to_find
# not sure if below works for both single and double digit hours
string = date + next_hour_to_find + ":00:00"

# finish by returning Time object, but this seems suuuuper inefficient since we converted to string and then back again
return Time.parse(string)

5 个答案:

答案 0 :(得分:2)

您可能想要查看Chronic,这是一个很棒的库,在Ruby中使用日期时允许使用自然语言。

five_today = Chronic.parse('5am')
five_today < Time.now ? Chronic.parse('tomorrow 5am') : five_today

由于Chronic会返回常规DateTime个对象,因此如果没有它,这也会有效。但是,你的语法不太令人愉快。

答案 1 :(得分:1)

没有理由用字符串格式的时间粉碎。 DateTime对象包含您需要的所有内容:

task ndkBuild(type: Exec,description: 'run ndk-build') {
    if (Os.isFamily(Os.FAMILY_WINDOWS)) {
        workingDir 'jni'
        commandLine 'ndk-build.cmd', '-j' , Runtime.runtime.availableProcessors()
    } else {
        workingDir 'jni'
        commandLine "ndk-build", '-j', Runtime.runtime.availableProcessors()
    }
}
tasks.withType(JavaCompile) {
    compileTask -> compileTask.dependsOn(ndkBuild)
}

答案 2 :(得分:0)

以下情况如何?

def next_hour_from(time, next_hour_to_find)
  hour_on_day_of_time = next_hour_to_find.hours.since( time.beginning_of_day )
  hour_on_day_of_time < time ? 1.day.since(hour_on_day_of_time) : hour_on_day_of_time
end

# e.g.
next_hour_from(@object.created_at, 5) # @object.created_at #=> 2017-03-28 21:00:00
# => 2017-03-29 05:00:00

基本上它的作用是:

  • 它会查看time日开始时的时间,并以小时为单位添加next_hour_to_find。将该值分配给hour_on_day_of_time
  • 然后检查hour_on_day_of_time是否在给定的time之前或之后。如果它在之后,则该方法可以返回hour_on_day_of_time。如果是之前的话,它会在hour_on_day_of_time增加1天并返回。

答案 3 :(得分:0)

这是纯粹的Ruby答案。我假设24小时制。如果需要12小时制,则可以将12小时时间(例如3pm)转换为(15)作为预备步骤。

require 'time'

dt = DateTime.now
  #=> #<DateTime: 2017-03-31T00:18:08-07:00\
  #     ((2457844j,26288s,566004000n),-25200s,2299161j)> 

假设

next_hr = 15

然后

Time.new(dt.year, dt.month, dt.day, dt.hour) +
  3600 * ((dt.hour < next_hr) ? next_hr - dt.hour : 24 + next_hr - dt_hour)
  #> 2017-03-31 15:00:00 -0700

答案 4 :(得分:-1)

为我的用例提供了更复杂的解决方案

def resolve_time str
  time_string, locality_string = str.split(/ +/)
  locality_string ||= ENV['TZ'] # or however you default your TZ, the locality string is ie 'UTC', 'Europe/Stockholm', 'CET', ...
  zone_string = Time.now.in_time_zone(locality_string).zone
  rv = DateTime.strptime("#{time_string} #{zone_string}", '%H:%M %Z')

  if rv < Time.now
    rv = rv.advance(days: 1)
  end

  rv
end

它接受带或不带时区的字符串输入。就我而言,这是必要的。

相关问题