【问题标题】:Get the last Sunday of the Month获取本月的最后一个星期日
【发布时间】:2013-07-31 14:31:14
【问题描述】:

我正在使用 Chronic 来获取任何给定年份每月的最后一个星期日。它会很高兴地给我第 n 个星期天,但不是最后一个。

这可行,但不是我需要的:

Chronic.parse('4th sunday in march', :now => Time.local(2015,1,1))

这是我需要的,但不起作用:

Chronic.parse('last sunday in march', :now => Time.local(2015,1,1))

有什么办法可以绕过这个明显的限制吗?

更新:我赞成以下两个答案,因为它们都很好,但我已经在“纯 Ruby”中实现了这一点(2 行代码,除了require 'date' 行),但我试图向管理层证明 Ruby 是用于替换即将消失的 Java 代码库的正确语言(并且有数十行代码来计算它) ,我告诉一位经理,我可能用一行 Ruby 就可以做到,而且它可读且易于维护。

【问题讨论】:

  • 一个相当俗气的想法,但你可以从四月的第一天开始,然后在“昨天”的循环中继续向后走,当你到达第一个星期日时爆发......跨度>
  • @aardvarkk 刚刚在你写评论时实现了这个想法 :)
  • @aardvarkk:那你可以写Chronic.parse('1 week before 1st sunday in april')
  • @iconoclast:糟糕,抱歉。文档给出了7 hours before tomorrow at noon 的例子,所以我假设[interval] before [...] 表示法更普遍。我的错。
  • 关于您的更新:您可以(或可能)在一行中使用Chronic 编写此内容,因为您只需调用一个函数。然而,使用这个参数,你基本上是在说你可以用一行代码调用一个 ruby​​ 函数。 Chronic 可能需要不止一行来实现这一点;)

标签: ruby chronic


【解决方案1】:

我不确定Chronic(我以前没听说过),但我们可以用纯 ruby​​ 实现它:)

##
# returns a Date object being the last sunday of the given month/year
# month: integer between 1 and 12
def last_sunday(month,year)
  # get the last day of the month
  date = Date.new year, month, -1
  #subtract number of days we are ahead of sunday
  date -= date.wday
end

last_sunday 方法可以这样使用:

last_sunday 07, 2013
#=> #<Date: 2013-07-28 ((2456502j,0s,0n),+0s,2299161j)>

【讨论】:

  • 而不是while date.wday != 0 date -= 1 end,为什么不只是date -= date.wday
  • (d = Date.new(2013, 7, -1)) - d.wday 将是单行版本
  • 感谢@steenslag - 我不确定这是否更具可读性(=可维护),但 OP 希望使用单线解决方案 - 所以这很棒 :)
  • 嗯...我更喜欢 2 行版本。
【解决方案2】:

阅读您问题中的更新后,我尝试仅使用一行 ruby​​ 代码(不使用 gems)提出另一个答案。这个怎么样?

##
# returns a Date object being the last sunday of the given month/year
# month: integer between 1 and 12
def last_sunday(month,year)
  # get the last day of the month, go back until we have a sunday
  Date.new(year, month, -1).downto(0).find(&:sunday?)
end

last_sunday 07, 2013
#=> #<Date: 2013-07-28 ((2456502j,0s,0n),+0s,2299161j)>

【讨论】:

【解决方案3】:

怎么样

Chronic.parse('last sunday', now: Chronic.parse('last day of march'))

【讨论】:

  • 使用 Chronic 获取 :now 的好主意,但这不起作用。首先,Chronic 将last day of march 解析为2013-03-01 12:00:00 -0500,其次,我仍然需要指定任意年份。第二个问题通过将 :now 值传递给嵌入的 Chronic 表达式来解决。
  • 您也可以使用 Chronic 来设置年份。我刚刚发送了一个拉取请求,以便能够为 :now 选项github.com/mojombo/chronic/pull/199 传递一个字符串
  • 所以可以Chronic.parse('last sunday', now: '31 march, 2015')
  • 是的,当他们接受您的拉取请求时,这将是一个很大的改进。具有讽刺意味的是,一个旨在解析字符串以解释日期的库不会在其自己的参数之一上执行此操作。
  • 嗯,也许是因为没有其他人需要它。我猜你现在已经提前知道了日期。我想这是一个特例,但我认为传递一个字符串看起来很棒。
【解决方案4】:

这行得通,并且可读性强:

Chronic.parse('last sunday', now: Date.new(year,3,31))

感谢 Ismael Abreu 提出的仅解析“上周日”并通过 :now 选项控制其余部分的想法。

更新:也请支持 Ismael 的回答。

【讨论】:

  • 我知道这是一篇旧帖子,但如果一个月的最后一天是星期天,它就会失败。 Chronic.parse('last sunday', now: Date.new(2017,12,31))
  • 从我之前的评论,如果你知道月底,就加1天:Chronic.parse('last sunday', now: Date.new(2017,12,31)+1)
【解决方案5】:

这有点难看,但你可以简单地按顺序尝试第 5 个或第 4 个:

d = [5,4].each do |i| 
  try = Chronic.parse("#{i}th sunday in march", :now => Time.local(2015,1,1))
  break try unless try.nil?
end
 => Sun Mar 29 12:30:00 +0100 2015

d = [5,4].each do |i| 
  try = Chronic.parse("#{i}th sunday in april", :now => Time.local(2015,1,1))
  break try unless try.nil?
end
 => Sun Apr 26 12:00:00 +0100 2015

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-29
    • 2014-06-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多