aggInterval.R 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. #' Create Periods for Temporal Composites
  2. #'
  3. #' @description
  4. #' The creation of custom temporal aggregation levels (e.g., half-monthly,
  5. #' monthly) from native 16-day MODIS composites usually requires the definition
  6. #' of date sequences based on which the "composite_day_of_the_year" SDS is
  7. #' further processed. Complementing \code{\link{transDate}}, which returns the
  8. #' respective start and end date only, this function creates full-year
  9. #' (half-)monthly or annual composite periods from a user-defined temporal range.
  10. #'
  11. #' @param x \code{Date} object, see eg default value of 'timeInfo' in
  12. #' \code{\link{temporalComposite}}.
  13. #' @param interval \code{character}. Time period for aggregation. Currently
  14. #' available options are "month" (default), "year" and "fortnight" (i.e., every
  15. #' 1st and 15th day of the month).
  16. #'
  17. #' @return
  18. #' A \code{list} with the following slots:
  19. #'
  20. #' \itemize{
  21. #' \item{\code{$begin}: The start date(s) of each (half-)monthly timestep as
  22. #' \code{Date} object.}
  23. #' \item{\code{$end}: Same for end date(s).}
  24. #' \item{\code{$beginDOY}: Similar to \code{$begin}, but with \code{character}
  25. #' objects in MODIS-style date format (i.e., "\%Y\%j"; see \code{\link{strptime}}).}
  26. #' \item{\code{$endDOY}: Same for end date(s).}
  27. #' }
  28. #'
  29. #' @author
  30. #' Florian Detsch
  31. #'
  32. #' @seealso
  33. #' \code{\link{transDate}}.
  34. #'
  35. #' @examples
  36. #' dates <- do.call("c", lapply(2015:2016, function(i) {
  37. #' start <- as.Date(paste0(i, "-01-01"))
  38. #' end <- as.Date(paste0(i, "-12-31"))
  39. #' seq(start, end, 16)
  40. #' }))
  41. #'
  42. #' intervals <- c("month", "year", "fortnight")
  43. #' lst <- lapply(intervals, function(i) {
  44. #' aggInterval(dates, interval = i)
  45. #' }); names(lst) <- intervals
  46. #'
  47. #' print(lst)
  48. #'
  49. #' @export aggInterval
  50. #' @name aggInterval
  51. aggInterval <- function(x, interval = c("month", "year", "fortnight")) {
  52. ## date range
  53. rng <- c(min(x), max(x))
  54. x <- as.numeric(strftime(x, "%Y"))
  55. ### monthly or fortnightly aggregation -----
  56. if (interval[1] != "year") {
  57. ## create start date sequence
  58. st <- lapply(min(x):max(x), function(i) {
  59. do.call(c, lapply(formatC(1:12, width = 2, flag = "0"), function(j) {
  60. as.Date(paste(i, j, if (interval[1] == "month") "01" else c("01", "15"),
  61. sep = "-"))
  62. }))
  63. })
  64. ## limit start date range to input period
  65. st <- do.call(c, st)
  66. bfr <- st < rng[1]; afr <- st > rng[2]
  67. st <- if (all(any(bfr), any(afr))) {
  68. st[which(bfr)[length(which(bfr))]:(which(afr)[1] - 1)]
  69. } else if (any(bfr) & all(!afr)) {
  70. st[which(bfr)[length(which(bfr))]:length(st)]
  71. } else if (all(!bfr) & any(afr)) {
  72. st[1:(which(afr)[1] - 1)]
  73. } else {
  74. st
  75. }
  76. ## create end date sequence
  77. nd <- lapply(1:length(st), function(i) {
  78. if (i < length(st)) {
  79. st[i + 1] - 1
  80. } else {
  81. if (interval[1] == "fortnight" & substr(st[i], 9, 10) == "01") {
  82. st[i] + 13
  83. } else {
  84. mn <- as.integer(strftime(st[i], "%m"))
  85. dec <- mn + 1 == 13
  86. if (dec) {
  87. yr <- as.integer(substr(st[i], 1, 4))
  88. nx <- paste0(yr + 1, "-01-")
  89. as.Date(gsub(substr(st[i], 1, 8), nx, st[i])) - 1
  90. } else {
  91. nx <- paste0("-", formatC(mn + 1, width = 2L, flag = "0"), "-")
  92. as.Date(gsub(substr(st[i], 5, 8), nx, st[i])) - 1
  93. }
  94. }
  95. }
  96. })
  97. nd <- do.call(c, nd)
  98. ### annual aggregation -----
  99. } else {
  100. st <- as.Date(paste0(min(x):max(x), "-01-01"))
  101. nd <- as.Date(paste0(min(x):max(x), "-12-31"))
  102. }
  103. st_doy <- transDate(st)$beginDOY
  104. nd_doy <- suppressWarnings(transDate(nd)$beginDOY)
  105. ## return named list
  106. list(begin = st, end = nd,
  107. beginDOY = st_doy, endDOY = nd_doy)
  108. }