一个会输出直到公元3000年的季度的函数。

huangapple go评论60阅读模式
英文:

A Function that will spit out the quarters to the year 3000 etc

问题

我需要创建一些代码,让我的团队能够持续获取每年的季度信息。我需要一个能够输出例如2020年第一季度或2500年第四季度的函数。

到目前为止我想出来的代码和经理的评论如下:

一个会输出直到公元3000年的季度的函数。

英文:

I need to create some code that will allow my team to have a never ending supply of the yearly quarters. i need a function that will spit out for example q1 2020 or q4 in the year 2500.

the code i have come up with so far and comments made by manager

一个会输出直到公元3000年的季度的函数。

答案1

得分: 1

这会生成一个包含yearqtr、开始日期和结束日期列的三列数据框。输入可以是Date、yearqtr或字符对象。在最后一种情况下,它应该采用类似于示例中的yyyy-q的形式。

yearqtr对象直接表示年份和季度,没有包含日期,并在内部表示为year + fraction,其中fraction为0、1/42/43/4,对应一年的4个季度,因此添加1/4会得到下一个季度,添加1会得到下一年的同一个季度。

    library(zoo)
    
    gen_qtrs <- function(from = Sys.Date(), to) {
      qtrs <- seq(as.yearqtr(from), as.yearqtr(to), by = 1/4)
      data.frame(qtrs, from = as.Date(qtrs), to = as.Date(qtrs, frac = 1))
    }
    gen_qtrs(to = "2024-4")
    ##      qtrs       from         to
    ## 1 2023 Q1 2023-01-01 2023-03-31
    ## 2 2023 Q2 2023-04-01 2023-06-30
    ## 3 2023 Q3 2023-07-01 2023-09-30
    ## 4 2023 Q4 2023-10-01 2023-12-31
    ## 5 2024 Q1 2024-01-01 2024-03-31
    ## 6 2024 Q2 2024-04-01 2024-06-30
    ## 7 2024 Q3 2024-07-01 2024-09-30
    ## 8 2024 Q4 2024-10-01 2024-12-31

这些也可以工作,并且会给出相同的输出:

    gen_qtrs(to = as.Date("2024-12-31"))
    gen_qtrs(to = as.yearqtr("2024-4"))
英文:

This generates a 3 column data frame with yearqtr, from date and to date columns. The inputs can be Date, yearqtr or character objects. In the last case it should be in the form yyyy-q as in the example.

yearqtr objects directly represent year and quarter without day and are represented internally as year + fraction where fraction is 0, 1/4, 2/4, 3/4 for the 4 quarters of a year so that adding 1/4 gives the next quarter and adding 1 gives the same quarter in the next year.

library(zoo)

gen_qtrs &lt;- function(from = Sys.Date(), to) {
  qtrs &lt;- seq(as.yearqtr(from), as.yearqtr(to), by = 1/4)
  data.frame(qtrs, from = as.Date(qtrs), to = as.Date(qtrs, frac = 1))
}
gen_qtrs(to = &quot;2024-4&quot;)
##      qtrs       from         to
## 1 2023 Q1 2023-01-01 2023-03-31
## 2 2023 Q2 2023-04-01 2023-06-30
## 3 2023 Q3 2023-07-01 2023-09-30
## 4 2023 Q4 2023-10-01 2023-12-31
## 5 2024 Q1 2024-01-01 2024-03-31
## 6 2024 Q2 2024-04-01 2024-06-30
## 7 2024 Q3 2024-07-01 2024-09-30
## 8 2024 Q4 2024-10-01 2024-12-31

These would also work and give the same output:

gen_qtrs(to = as.Date(&quot;2024-12-31&quot;))
gen_qtrs(to = as.yearqtr(&quot;2024-4&quot;))

答案2

得分: 0

这段代码是一个用于获取指定季度起止日期的R语言函数。它可以容忍输入的格式不同,比如季度和年份的顺序、大小写、以及额外的空格。以下是一些测试示例:

对于简单的情况,比如输入 'q3 2020',将返回起止日期:

```r
getStartEndDate('q3 2020')
#>        start        end
#> 1 2020-07-01 2020-09-30

这个函数也可以处理未来几个世纪的日期:

getStartEndDate('q4 2500')
#>        start        end
#> 1 2500-10-01 2500-12-31

它支持处理多个输入,可以将输入以向量形式传递:

getStartEndDate(c('q1 2023', 'q3 2024 ', 'q2 2025'))
#>        start        end
#> 1 2023-01-01 2023-03-31
#> 2 2024-07-01 2024-09-30
#> 3 2025-04-01 2025-06-30

另外,它对输入的顺序、大小写和额外的空格都具有容忍性:

getStartEndDate(c('2023 q1', 'Q3 2024 ', ' q2 2025 '))
#>        start        end
#> 1 2023-01-01 2023-03-31
#> 2 2024-07-01 2024-09-30
#> 3 2025-04-01 2025-06-30

如果输入不符合要求,它会给出有用的错误信息:

getStartEndDate('Q3')
#> Error in FUN(X[[i]], ...) : 
#>   "quarter" must be a string in format "q1 2020"

<details>
<summary>英文:</summary>

It&#39;s not clear what format you want the input to be, but I assume you want it to be a string in the format &quot;q3 2020&quot;. We can write a function that will be tolerant of whether the quarter comes before or after the year, and whether the &quot;q&quot; is uppercase or lowercase, and also allow vectorized input:
``` r
getStartEndDate &lt;- function(quarter) {
  # Convert input to lowercase letters and remove any whitespace around text
  quarter &lt;- trimws(tolower(quarter))

  # Split the input strings by the whitespace in the middle to get
  # a list of length-2 strings, (the year and the quarter)
  quarter &lt;- strsplit(quarter, &#39;\\s+&#39;)

  # Only the year portion will convert from string to numeric without NAs
  # so we find this part for each pair of strings and get a vector of all 
  # the years. We throw an error if there are not two strings for each
  # item on our list, and if we fail to extract a year, sapply will return
  # a list instead of a vector so we also throw an error at this stage:
  years &lt;- sapply(quarter, function(x) {
    if(length(x) != 2) stop(&#39;&quot;quarter&quot; must be a string in format &quot;q1 2020&quot;&#39;)
    x &lt;- suppressWarnings(as.numeric(x))
    x[!is.na(x)]})
  if(is.list(years)) stop(&#39;&quot;quarter&quot; must be a string in format &quot;q1 2020&quot;&#39;)
  
  # Go through our list and pick out the q1, q2, q3, or q4, converting it to
  # the number 1:4 by removing the q and calling as.numeric
  quarters &lt;- sapply(quarter, function(x) {
    x &lt;- grep(&#39;q(1|2|3|4)&#39;, x, value = TRUE)
    if(length(x) != 1) stop(&#39;&quot;quarter&quot; must be a string in format &quot;q1 2020&quot;&#39;)
    as.numeric(sub(&#39;q&#39;, &#39;&#39;, x))})
  
  # Now we use Map to get a vector of quarters starting from each year, and 
  # subset the correct one using our quarters. These are made into a one-row
  # data frame for each year-quarter then all bound into a single data frame.
  do.call(rbind, Map(function(y, q) {
    dates &lt;- seq(as.Date(paste0(y, &#39;-01-01&#39;)), by = &#39;quarter&#39;, length = 5)
    data.frame(start = dates[q], end = dates[q + 1] - 1)}, y = years, q = quarters))
}

Testing on a simple case, we have:

getStartEndDate(&#39;q3 2020&#39;)
#&gt;        start        end
#&gt; 1 2020-07-01 2020-09-30

This will work for many centuries to come:

getStartEndDate(&#39;q4 2500&#39;)
#&gt;        start        end
#&gt; 1 2500-10-01 2500-12-31

It can take multiple inputs in vetorised form:

getStartEndDate(c(&#39;q1 2023&#39;, &#39;q3 2024 &#39;, &#39;q2 2025&#39;))
#&gt;        start        end
#&gt; 1 2023-01-01 2023-03-31
#&gt; 2 2024-07-01 2024-09-30
#&gt; 3 2025-04-01 2025-06-30

It is tolerant of ordering, capitalization and accidental whitespaces:

getStartEndDate(c(&#39;2023 q1&#39;, &#39;Q3 2024 &#39;, &#39; q2 2025 &#39;))
#&gt;        start        end
#&gt; 1 2023-01-01 2023-03-31
#&gt; 2 2024-07-01 2024-09-30
#&gt; 3 2025-04-01 2025-06-30

And throws a helpful error message if the wrong input is received:

getStartEndDate(&#39;Q3&#39;)
#&gt; Error in FUN(X[[i]], ...) : 
#&gt;   &quot;quarter&quot; must be a string in format &quot;q1 2020&quot; 

<sup>Created on 2023-02-16 with reprex v2.0.2</sup>

huangapple
  • 本文由 发表于 2023年2月16日 18:47:04
  • 转载请务必保留本文链接:https://go.coder-hub.com/75471148.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定