【问题标题】:How to Get the Same Weekday Last Year Given any Given Year?给定任何一年,如何获得去年相同的工作日?
【发布时间】:2017-06-06 02:48:21
【问题描述】:

我想在任何一年都得到去年的同一天。我怎样才能最好地在 R 中做到这一点。例如,给定 2010/01/03 星期日,我想获得前一年同一周的星期日。

# "Sunday"
weekdays(as.Date("2010/01/03", format="%Y/%m/%d"))

# "Saturday"
weekdays(as.Date("2009/01/03", format="%Y/%m/%d"))

【问题讨论】:

  • 使用lubridate,您可以执行as.Date(parse_date_time(paste(year(dates) - 1, week(dates), weekdays(dates)), orders = 'YUA')),其中dates 是日期的输入向量,但这在一年中的第一周或最后一周偶尔会失败,其中一周被截断,使得没有对应的日期。

标签: r date dayofweek


【解决方案1】:

要查找一年前的同一工作日,只需从给定日期减去 52 周或 364 天:

d <- as.Date("2010-01-03")
weekdays(d)
#[1] "Sunday"
d - 52L * 7L
#[1] "2009-01-04"
weekdays(d - 52L * 7L)
#[1] "Sunday"

请注意,日历年有 365 天(或闰年为 366 天),比 52 周多一两天。因此,一年前的同一工作日的日历日期会移动一两天。 (或者,它解释了为什么除夕总是在不同的工作日。)

【讨论】:

  • 这是一个很好的简单实用的答案!然而,挑剔这个问题以突出日期的一般痛苦,OPs 对“同一周”的定义尚不清楚。示例:week(as.Date("2017/01/07", format="%Y/%m/%d")) 是 1,但 week(as.Date("2017/01/07", format="%Y/%m/%d") - 364) 是 2(因为 2017 年 1 月 1 日是星期日)。如果您使用在 lubridate isoweek 中实现的 ISO8601 周数定义,那么两者都是 week1
  • @epi99,我同意Q中的短语去年同一天获得前一年同一周的星期日留出解释同一天同一周的含义的空间。所以,我的回答是基于给出的例子的猜测。
  • 这正是我所需要的感谢您的回答,很抱歉与实际问题混淆!
【解决方案2】:

使用 lubridate,以下公式将为您提供上一年同一周的相应工作日:

as.Date(dDate - 364 - ifelse(weekdays( dDate - 363) == weekdays( dDate ), 1, 0))

dDate 是某个日期,即dDate &lt;- as.Date("2016-02-29")ifelse 表示闰年。

【讨论】:

    【解决方案3】:

    这是一个简单的算法。从利息日减去 365 天。使用下面的 Tableau 代码(可轻松翻译成其他语言)将该天调整为一周中最接近的匹配日期。这相当于下表中的规则(1 = 星期一,7 = 星期日)。基本上,如果移动

    [day prior year raw] = [day] - 365
    [matching day prior year] = 
    if abs(datepart('weekday',[day]) - datepart('weekday',[day prior year raw]))<= 3
    then [day prior year raw]+datepart('weekday',[day]) - datepart('weekday',[day prior year raw])
    else [day prior year raw]+(if  datepart('weekday',[day]) > datepart('weekday',[day prior year raw])
            then -7+(datepart('weekday',[day]) - datepart('weekday',[day prior year raw]))
            else 7+(datepart('weekday',[day]) - datepart('weekday',[day prior year raw])) end
          )
    end)
    

    【讨论】:

      【解决方案4】:

      查看 lubridate 包中的 ?years。这将创建一个周期对象,该对象正确跨越闰年。

      > library(lubridate)
      > # set the reference date
      > d1 = as.Date("2017/01/03", format="%Y/%m/%d")
      > 
      > # verify across years and leap years
      > d1 - years(1)
      [1] "2016-01-03"
      > d1 - years(2)
      [1] "2015-01-03"
      > d1 - years(3)
      [1] "2014-01-03"
      > d1 - years(4)
      [1] "2013-01-03"
      > d1 - years(5)
      [1] "2012-01-03"
      > 
      > weekdays(d1 - years(1))
      [1] "Sunday"
      > weekdays(d1 - years(2))
      [1] "Saturday"
      > 
      > # feb 29 on year period in yields NA
      > ymd("2016/02/29") - years(1)
      [1] NA
      > 
      > # feb 29 in a non-leap year fails to convert
      > ymd("2015/02/29") - years(1)
      [1] NA
      Warning message:
      All formats failed to parse. No formats found. 
      > 
      > # feb 29, leap year with 4 year period works.
      > ymd("2016/02/29") - years(4)
      [1] "2012-02-29"
      > 
      

      【讨论】:

      • 你说得对,lubridate 有助于找到一年前的相同日期,但这将是一个不同的工作日。那么,这如何回答 OPgiven Sunday [...] 我想获得前一年同一周的星期日 的问题?顺便说一句,@alistaire 已经在他的评论中提出了 lubridate 解决方案。
      猜你喜欢
      • 1970-01-01
      • 2013-06-17
      • 1970-01-01
      • 2013-01-09
      • 1970-01-01
      • 2015-07-15
      • 2021-10-06
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多