The following APIs impose a period limit in the data retrieved, not allowing querying more than the predetermined period in each API.
AEMET API limit the daily data download to 31 days, and the monthly and yearly data to 3 years:
# aemet api has a limit for 31 days in daily:
get_meteo_from(
'aemet',
aemet_options(
api_key = keyring::key_get('aemet'),
resolution = 'daily',
start_date = as.Date('1990-01-01'),
end_date = as.Date('1990-12-31')
)
)
#> Error in `api_function()`:
#> ✖ 404
#> ℹ AEMET API returned no data: El rango de fechas no puede ser superior a 31
#> dias
# and monthly and yearly data to 3 years
get_meteo_from(
'aemet',
aemet_options(
api_key = keyring::key_get('aemet'),
resolution = 'yearly',
start_date = as.Date('2005-01-01'),
end_date = as.Date('2020-12-31'),
stations = "0149X"
)
)
#> Error in `api_function()`:
#> ✖ 404
#> ℹ AEMET API returned no data: El rango de las fechas no puede ser superior a 36
#> mesess
This means that with one call to get_meteo_from
to the
AEMET service, one can only download 31 days of data, (or 3 years in
monthly and yearly data).
If the period needed is bigger than that, one option is performing all
the calls necessary and join the results:
res_1990_jan <- get_meteo_from(
'aemet',
aemet_options(
api_key = keyring::key_get('aemet'),
resolution = 'daily',
start_date = as.Date('1990-01-01'),
end_date = as.Date('1990-01-31')
)
)
#> ℹ © AEMET. Autorizado el uso de la información y su reproducción citando a
#> AEMET como autora de la misma.
#> https://www.aemet.es/es/nota_legal
res_1990_feb <- get_meteo_from(
'aemet',
aemet_options(
api_key = keyring::key_get('aemet'),
resolution = 'daily',
start_date = as.Date('1990-02-01'),
end_date = as.Date('1990-02-28')
)
)
#> ℹ © AEMET. Autorizado el uso de la información y su reproducción citando a
#> AEMET como autora de la misma.
#> https://www.aemet.es/es/nota_legal
res <- rbind(res_1990_jan, res_1990_feb)
res
#> Simple feature collection with 7015 features and 12 fields
#> Geometry type: POINT
#> Dimension: XY
#> Bounding box: xmin: -17.88889 ymin: 27.81889 xmax: 4.215556 ymax: 43.56694
#> Geodetic CRS: WGS 84
#> # A tibble: 7,015 × 13
#> timestamp service station_id station_name station_province altitude
#> * <dttm> <chr> <chr> <chr> <chr> [m]
#> 1 1990-01-01 00:00:00 aemet 0002I "VANDELLÒS … TARRAGONA 32
#> 2 1990-01-01 00:00:00 aemet 0016A "REUS AEROP… TARRAGONA 71
#> 3 1990-01-01 00:00:00 aemet 0076 "BARCELONA … BARCELONA 4
#> 4 1990-01-01 00:00:00 aemet 0200E "BARCELONA,… BARCELONA 408
#> 5 1990-01-01 00:00:00 aemet 0229I "SABADELL A… BARCELONA 146
#> 6 1990-01-01 00:00:00 aemet 0324A "RIPOLL" GIRONA 675
#> 7 1990-01-01 00:00:00 aemet 0367 "GIRONA AER… GIRONA 143
#> 8 1990-01-01 00:00:00 aemet 1014 "HONDARRIBI… GIPUZKOA 4
#> 9 1990-01-01 00:00:00 aemet 1024E "DONOSTIA /… GIPUZKOA 250
#> 10 1990-01-01 00:00:00 aemet 1082 "BILBAO AER… BIZKAIA 42
#> # ℹ 7,005 more rows
#> # ℹ 7 more variables: mean_temperature [°C], min_temperature [°C],
#> # max_temperature [°C], precipitation [L/m^2], mean_wind_speed [m/s],
#> # insolation [h], geometry <POINT [°]>
While for short periods this can be easily done, when needing long
periods (years, decades), this can be tedious and prone to error (or at
least involves a lot of copy&paste and generate longer
scripts).
To avoid this, we can use loops, both in a tidyverse way
(purrr::map
) or in a more classic approach
(for
). For both ways, the first thing to do is create the
vectors of dates to retrieve:
# First, we prepare the date vectors, with the start and end dates.
start_dates <- seq(as.Date('1990-01-01'), as.Date('1990-06-01'), 'months')
end_dates <- seq(as.Date('1990-02-01'), as.Date('1990-07-01'), 'months') - 1
# Both vectors must have the same length
length(start_dates) == length(end_dates)
#> [1] TRUE
# lets see them
data.frame(start_dates, end_dates)
#> start_dates end_dates
#> 1 1990-01-01 1990-01-31
#> 2 1990-02-01 1990-02-28
#> 3 1990-03-01 1990-03-31
#> 4 1990-04-01 1990-04-30
#> 5 1990-05-01 1990-05-31
#> 6 1990-06-01 1990-06-30
We are gonna use purrr::map2_dfr
, to iterate both date
vectors at the same time and return a data frame with all the results
directly:
# tidyverse map
res_tidyverse <-
purrr::map2(
.x = start_dates, .y = end_dates,
.f = function(start_date, end_date) {
res <- get_meteo_from(
'aemet',
aemet_options(
api_key = keyring::key_get('aemet'),
resolution = 'daily',
start_date = start_date,
end_date = end_date
)
)
return(res)
}
) |>
purrr::list_rbind()
#> ℹ © AEMET. Autorizado el uso de la información y su reproducción citando a
#> AEMET como autora de la misma.
#> https://www.aemet.es/es/nota_legal
#> ℹ © AEMET. Autorizado el uso de la información y su reproducción citando a
#> AEMET como autora de la misma.
#> https://www.aemet.es/es/nota_legal
#> ℹ © AEMET. Autorizado el uso de la información y su reproducción citando a
#> AEMET como autora de la misma.
#> https://www.aemet.es/es/nota_legal
#> ℹ © AEMET. Autorizado el uso de la información y su reproducción citando a
#> AEMET como autora de la misma.
#> https://www.aemet.es/es/nota_legal
head(res_tidyverse)
#> timestamp service station_id station_name station_province altitude
#> 1 1990-01-01 aemet 0002I VANDELLÒS TARRAGONA 32 [m]
#> 2 1990-01-01 aemet 0016A REUS AEROPUERTO TARRAGONA 71 [m]
#> 3 1990-01-01 aemet 0076 BARCELONA AEROPUERTO BARCELONA 4 [m]
#> 4 1990-01-01 aemet 0200E BARCELONA, FABRA BARCELONA 408 [m]
#> 5 1990-01-01 aemet 0229I SABADELL AEROPUERTO BARCELONA 146 [m]
#> 6 1990-01-01 aemet 0324A RIPOLL GIRONA 675 [m]
#> mean_temperature min_temperature max_temperature precipitation
#> 1 11.2 [°C] 8.8 [°C] 13.7 [°C] 0 [L/m^2]
#> 2 9.0 [°C] 5.4 [°C] 12.6 [°C] 0 [L/m^2]
#> 3 9.2 [°C] 4.0 [°C] 14.4 [°C] 0 [L/m^2]
#> 4 9.2 [°C] 6.4 [°C] 12.0 [°C] 0 [L/m^2]
#> 5 7.0 [°C] 2.0 [°C] 12.0 [°C] 0 [L/m^2]
#> 6 4.5 [°C] -2.5 [°C] 11.5 [°C] 0 [L/m^2]
#> mean_wind_speed insolation geometry
#> 1 1.7 [m/s] 0.1 [h] POINT (0.8713889 40.95806)
#> 2 0.6 [m/s] 0.1 [h] POINT (1.163611 41.145)
#> 3 3.6 [m/s] 6.7 [h] POINT (2.07 41.29278)
#> 4 5.6 [m/s] 8.3 [h] POINT (2.124167 41.41833)
#> 5 NA [m/s] NA [h] POINT (2.103056 41.52361)
#> 6 NA [m/s] NA [h] POINT (2.196111 42.19139)
We use base::for
, iterating by the index of the dates
vectors:
# base for loop
res_for <- data.frame()
for (index in seq_along(start_dates)) {
temp_res <- get_meteo_from(
'aemet',
aemet_options(
api_key = keyring::key_get('aemet'),
resolution = 'daily',
start_date = start_dates[index],
end_date = end_dates[index]
)
)
res_for <- rbind(res_for, temp_res)
}
head(res_for)
#> Simple feature collection with 6 features and 12 fields
#> Geometry type: POINT
#> Dimension: XY
#> Bounding box: xmin: 0.8713889 ymin: 40.95806 xmax: 2.196111 ymax: 42.19139
#> Geodetic CRS: WGS 84
#> # A tibble: 6 × 13
#> timestamp service station_id station_name station_province altitude
#> <dttm> <chr> <chr> <chr> <chr> [m]
#> 1 1990-01-01 00:00:00 aemet 0002I "VANDELLÒS " TARRAGONA 32
#> 2 1990-01-01 00:00:00 aemet 0016A "REUS AEROPU… TARRAGONA 71
#> 3 1990-01-01 00:00:00 aemet 0076 "BARCELONA A… BARCELONA 4
#> 4 1990-01-01 00:00:00 aemet 0200E "BARCELONA, … BARCELONA 408
#> 5 1990-01-01 00:00:00 aemet 0229I "SABADELL AE… BARCELONA 146
#> 6 1990-01-01 00:00:00 aemet 0324A "RIPOLL" GIRONA 675
#> # ℹ 7 more variables: mean_temperature [°C], min_temperature [°C],
#> # max_temperature [°C], precipitation [L/m^2], mean_wind_speed [m/s],
#> # insolation [h], geometry <POINT [°]>
Both methods return identical results:
In a loop, no matter if a
purrr::map
or afor
loop, each iteration will connect with the API, consuming connections from the user quota. Take this into consideration when creating loops for longer periods, as you can reach your API request limits for the day/month… (it depends on the service API).
When using MeteoCat in daily
, monthly
and
yearly
there are restrictions on the period that can be
accessed.
daily
daily
always returns the whole month the date selected
is in, i.e. for start_date = as.Date('2020-04-10')
it will
return all days in April, 2020:
api_options <- meteocat_options(
'daily', start_date = as.Date('2020-04-10'),
api_key = keyring::key_get('meteocat')
)
april_2020 <- get_meteo_from('meteocat', api_options)
#> ℹ Data provided by meteo.cat © Servei Meteorològic de Catalunya
#> https://www.meteo.cat/wpweb/avis-legal/#info
unique(april_2020$timestamp)
#> [1] "2020-04-01 UTC" "2020-04-02 UTC" "2020-04-03 UTC" "2020-04-04 UTC"
#> [5] "2020-04-05 UTC" "2020-04-06 UTC" "2020-04-07 UTC" "2020-04-08 UTC"
#> [9] "2020-04-09 UTC" "2020-04-10 UTC" "2020-04-11 UTC" "2020-04-12 UTC"
#> [13] "2020-04-13 UTC" "2020-04-14 UTC" "2020-04-15 UTC" "2020-04-16 UTC"
#> [17] "2020-04-17 UTC" "2020-04-18 UTC" "2020-04-19 UTC" "2020-04-20 UTC"
#> [21] "2020-04-21 UTC" "2020-04-22 UTC" "2020-04-23 UTC" "2020-04-24 UTC"
#> [25] "2020-04-25 UTC" "2020-04-26 UTC" "2020-04-27 UTC" "2020-04-28 UTC"
#> [29] "2020-04-29 UTC" "2020-04-30 UTC"
This means that if we want more than one month, we need to use loops in a similar way as described previously for AEMET:
start_dates <- seq(as.Date('2020-01-01'), as.Date('2020-04-01'), 'months')
# tidyverse map
meteocat_2020q1_tidyverse <-
purrr::map(
.x = start_dates,
.f = function(start_date) {
res <- get_meteo_from(
'meteocat',
meteocat_options(
api_key = keyring::key_get('meteocat'),
resolution = 'daily',
start_date = start_date
)
)
return(res)
}
) |>
purrr::list_rbind()
#> ℹ Data provided by meteo.cat © Servei Meteorològic de Catalunya
#> https://www.meteo.cat/wpweb/avis-legal/#info
#> ℹ Data provided by meteo.cat © Servei Meteorològic de Catalunya
#> https://www.meteo.cat/wpweb/avis-legal/#info
#> ℹ Data provided by meteo.cat © Servei Meteorològic de Catalunya
#> https://www.meteo.cat/wpweb/avis-legal/#info
#> ℹ Data provided by meteo.cat © Servei Meteorològic de Catalunya
#> https://www.meteo.cat/wpweb/avis-legal/#info
head(meteocat_2020q1_tidyverse)
#> timestamp service station_id station_name station_province
#> 1 2020-01-01 meteocat C6 Castellnou de Seana Lleida
#> 2 2020-01-01 meteocat C7 Tàrrega Lleida
#> 3 2020-01-01 meteocat C8 Cervera Lleida
#> 4 2020-01-01 meteocat C9 Mas de Barberans Tarragona
#> 5 2020-01-01 meteocat CC Orís Barcelona
#> 6 2020-01-01 meteocat CD la Seu d'Urgell - Bellestar Lleida
#> altitude mean_temperature min_temperature max_temperature
#> 1 264 [m] 3.9 [°C] 3.2 [°C] 4.5 [°C]
#> 2 427 [m] 2.5 [°C] 1.9 [°C] 3.3 [°C]
#> 3 554 [m] 1.6 [°C] 0.6 [°C] 2.3 [°C]
#> 4 240 [m] 3.4 [°C] 1.7 [°C] 6.5 [°C]
#> 5 626 [m] 2.2 [°C] -2.5 [°C] 11.1 [°C]
#> 6 849 [m] 2.5 [°C] -3.2 [°C] 11.9 [°C]
#> mean_relative_humidity min_relative_humidity max_relative_humidity
#> 1 93 [%] 87 [%] 97 [%]
#> 2 97 [%] 93 [%] 100 [%]
#> 3 100 [%] 100 [%] 100 [%]
#> 4 87 [%] 72 [%] 97 [%]
#> 5 85 [%] 53 [%] 96 [%]
#> 6 82 [%] 45 [%] 98 [%]
#> precipitation mean_wind_direction mean_wind_speed global_solar_radiation
#> 1 0.0 [L/m^2] NA [°] NA [m/s] 1.6 [MJ/m^2]
#> 2 0.0 [L/m^2] NA [°] NA [m/s] 1.4 [MJ/m^2]
#> 3 0.1 [L/m^2] NA [°] NA [m/s] 1.6 [MJ/m^2]
#> 4 0.0 [L/m^2] NA [°] NA [m/s] 4.1 [MJ/m^2]
#> 5 0.0 [L/m^2] NA [°] NA [m/s] 8.1 [MJ/m^2]
#> 6 0.0 [L/m^2] NA [°] NA [m/s] 8.2 [MJ/m^2]
#> geometry
#> 1 POINT (0.95172 41.6566)
#> 2 POINT (1.16234 41.66695)
#> 3 POINT (1.29609 41.67555)
#> 4 POINT (0.39988 40.71825)
#> 5 POINT (2.20862 42.07398)
#> 6 POINT (1.43277 42.37083)
# base for loop
meteocat_2020q1_for <- data.frame()
for (index in seq_along(start_dates)) {
temp_res <- get_meteo_from(
'meteocat',
meteocat_options(
api_key = keyring::key_get('meteocat'),
resolution = 'daily',
start_date = start_dates[index]
)
)
meteocat_2020q1_for <- rbind(meteocat_2020q1_for, temp_res)
}
head(meteocat_2020q1_for)
#> Simple feature collection with 6 features and 16 fields
#> Geometry type: POINT
#> Dimension: XY
#> Bounding box: xmin: 0.39988 ymin: 40.71825 xmax: 2.20862 ymax: 42.37083
#> Geodetic CRS: WGS 84
#> # A tibble: 6 × 17
#> timestamp service station_id station_name station_province altitude
#> <dttm> <chr> <chr> <chr> <chr> [m]
#> 1 2020-01-01 00:00:00 meteocat C6 Castellnou … Lleida 264
#> 2 2020-01-01 00:00:00 meteocat C7 Tàrrega Lleida 427
#> 3 2020-01-01 00:00:00 meteocat C8 Cervera Lleida 554
#> 4 2020-01-01 00:00:00 meteocat C9 Mas de Barb… Tarragona 240
#> 5 2020-01-01 00:00:00 meteocat CC Orís Barcelona 626
#> 6 2020-01-01 00:00:00 meteocat CD la Seu d'Ur… Lleida 849
#> # ℹ 11 more variables: mean_temperature [°C], min_temperature [°C],
#> # max_temperature [°C], mean_relative_humidity [%],
#> # min_relative_humidity [%], max_relative_humidity [%],
#> # precipitation [L/m^2], mean_wind_direction [°], mean_wind_speed [m/s],
#> # global_solar_radiation [MJ/m^2], geometry <POINT [°]>
# both are identical
identical(meteocat_2020q1_tidyverse, meteocat_2020q1_for)
#> [1] FALSE
monthly
monthly
always returns the whole year the date selected
is in, i.e. for start_date = as.Date('2020-04-10')
it will
return all months in 2020:
api_options <- meteocat_options(
'monthly', start_date = as.Date('2020-04-10'),
api_key = keyring::key_get('meteocat')
)
year_2020 <- get_meteo_from('meteocat', api_options)
#> ℹ Data provided by meteo.cat © Servei Meteorològic de Catalunya
#> https://www.meteo.cat/wpweb/avis-legal/#info
unique(year_2020$timestamp)
#> [1] "2020-01-01 UTC" "2020-02-01 UTC" "2020-03-01 UTC" "2020-04-01 UTC"
#> [5] "2020-05-01 UTC" "2020-06-01 UTC" "2020-07-01 UTC" "2020-08-01 UTC"
#> [9] "2020-09-01 UTC" "2020-10-01 UTC" "2020-11-01 UTC" "2020-12-01 UTC"
Which means that if we need more than one year of monthly data, we need to use loops again:
start_dates <- seq(as.Date('2019-01-01'), as.Date('2020-01-01'), 'years')
# tidyverse map
meteocat_2019_20_tidyverse <-
purrr::map(
.x = start_dates,
.f = function(start_date) {
res <- get_meteo_from(
'meteocat',
meteocat_options(
api_key = keyring::key_get('meteocat'),
resolution = 'monthly',
start_date = start_date
)
)
return(res)
}
) |>
purrr::list_rbind()
#> ℹ Data provided by meteo.cat © Servei Meteorològic de Catalunya
#> https://www.meteo.cat/wpweb/avis-legal/#info
#> ℹ Data provided by meteo.cat © Servei Meteorològic de Catalunya
#> https://www.meteo.cat/wpweb/avis-legal/#info
head(meteocat_2019_20_tidyverse)
#> timestamp service station_id station_name station_province
#> 1 2019-01-01 meteocat C6 Castellnou de Seana Lleida
#> 2 2019-01-01 meteocat C7 Tàrrega Lleida
#> 3 2019-01-01 meteocat C8 Cervera Lleida
#> 4 2019-01-01 meteocat C9 Mas de Barberans Tarragona
#> 5 2019-01-01 meteocat CC Orís Barcelona
#> 6 2019-01-01 meteocat CD la Seu d'Urgell - Bellestar Lleida
#> altitude mean_temperature min_temperature_absolute min_temperature_mean
#> 1 264 [m] 2.9 [°C] -7.0 [°C] -1.8 [°C]
#> 2 427 [m] 2.9 [°C] -5.0 [°C] -0.5 [°C]
#> 3 554 [m] 2.5 [°C] -5.6 [°C] -0.7 [°C]
#> 4 240 [m] 9.4 [°C] 0.2 [°C] 5.1 [°C]
#> 5 626 [m] 2.3 [°C] -8.3 [°C] -2.7 [°C]
#> 6 849 [m] 2.9 [°C] -7.1 [°C] -3.0 [°C]
#> max_temperature_absolute max_temperature_mean mean_relative_humidity
#> 1 17.9 [°C] 8.5 [°C] 84 [%]
#> 2 15.9 [°C] 7.4 [°C] 85 [%]
#> 3 14.0 [°C] 6.5 [°C] 85 [%]
#> 4 18.0 [°C] 14.0 [°C] 55 [%]
#> 5 15.7 [°C] 9.9 [°C] 73 [%]
#> 6 17.9 [°C] 10.7 [°C] 56 [%]
#> min_relative_humidity_absolute min_relative_humidity_mean
#> 1 23 [%] 64 [%]
#> 2 28 [%] 68 [%]
#> 3 27 [%] 70 [%]
#> 4 17 [%] 38 [%]
#> 5 8 [%] 43 [%]
#> 6 4 [%] 28 [%]
#> max_relative_humidity_absolute max_relative_humidity_mean precipitation
#> 1 100 [%] 97 [%] 8.4 [L/m^2]
#> 2 100 [%] 96 [%] 14.1 [L/m^2]
#> 3 100 [%] 95 [%] 10.4 [L/m^2]
#> 4 97 [%] 76 [%] 4.0 [L/m^2]
#> 5 96 [%] 90 [%] 8.0 [L/m^2]
#> 6 98 [%] 78 [%] 34.9 [L/m^2]
#> mean_wind_direction mean_wind_speed global_solar_radiation
#> 1 NA [°] NA [m/s] 6.4 [MJ/m^2]
#> 2 NA [°] NA [m/s] 6.4 [MJ/m^2]
#> 3 NA [°] NA [m/s] 6.7 [MJ/m^2]
#> 4 NA [°] NA [m/s] 9.3 [MJ/m^2]
#> 5 NA [°] NA [m/s] 8.0 [MJ/m^2]
#> 6 NA [°] NA [m/s] 8.4 [MJ/m^2]
#> geometry
#> 1 POINT (0.95172 41.6566)
#> 2 POINT (1.16234 41.66695)
#> 3 POINT (1.29609 41.67555)
#> 4 POINT (0.39988 40.71825)
#> 5 POINT (2.20862 42.07398)
#> 6 POINT (1.43277 42.37083)
# base for loop
meteocat_2019_20_for <- data.frame()
for (index in seq_along(start_dates)) {
temp_res <- get_meteo_from(
'meteocat',
meteocat_options(
api_key = keyring::key_get('meteocat'),
resolution = 'monthly',
start_date = start_dates[index]
)
)
meteocat_2019_20_for <- rbind(meteocat_2019_20_for, temp_res)
}
head(meteocat_2019_20_for)
#> Simple feature collection with 6 features and 20 fields
#> Geometry type: POINT
#> Dimension: XY
#> Bounding box: xmin: 0.39988 ymin: 40.71825 xmax: 2.20862 ymax: 42.37083
#> Geodetic CRS: WGS 84
#> # A tibble: 6 × 21
#> timestamp service station_id station_name station_province altitude
#> <dttm> <chr> <chr> <chr> <chr> [m]
#> 1 2019-01-01 00:00:00 meteocat C6 Castellnou … Lleida 264
#> 2 2019-01-01 00:00:00 meteocat C7 Tàrrega Lleida 427
#> 3 2019-01-01 00:00:00 meteocat C8 Cervera Lleida 554
#> 4 2019-01-01 00:00:00 meteocat C9 Mas de Barb… Tarragona 240
#> 5 2019-01-01 00:00:00 meteocat CC Orís Barcelona 626
#> 6 2019-01-01 00:00:00 meteocat CD la Seu d'Ur… Lleida 849
#> # ℹ 15 more variables: mean_temperature [°C], min_temperature_absolute [°C],
#> # min_temperature_mean [°C], max_temperature_absolute [°C],
#> # max_temperature_mean [°C], mean_relative_humidity [%],
#> # min_relative_humidity_absolute [%], min_relative_humidity_mean [%],
#> # max_relative_humidity_absolute [%], max_relative_humidity_mean [%],
#> # precipitation [L/m^2], mean_wind_direction [°], mean_wind_speed [m/s],
#> # global_solar_radiation [MJ/m^2], geometry <POINT [°]>
# both are identical
identical(meteocat_2019_20_tidyverse, meteocat_2019_20_for)
#> [1] FALSE
yearly
yearly
always returns all available years and
start_date
argument is ignored, i.e. using
start_date = as.Date('2020-04-10')
will return all years,
independently of the date supplied:
api_options <- meteocat_options(
'yearly', start_date = as.Date('2020-04-10'),
api_key = keyring::key_get('meteocat')
)
all_years <- get_meteo_from('meteocat', api_options)
#> ℹ Data provided by meteo.cat © Servei Meteorològic de Catalunya
#> https://www.meteo.cat/wpweb/avis-legal/#info
unique(all_years$timestamp)
#> [1] "1989-12-19 UTC" "1990-12-19 UTC" "1991-12-19 UTC" "1992-12-19 UTC"
#> [5] "1993-12-19 UTC" "1994-12-19 UTC" "1995-12-19 UTC" "1996-12-19 UTC"
#> [9] "1997-12-19 UTC" "1998-12-19 UTC" "1999-12-19 UTC" "2000-12-19 UTC"
#> [13] "2001-12-19 UTC" "2002-12-19 UTC" "2003-12-19 UTC" "2004-12-19 UTC"
#> [17] "2005-12-19 UTC" "2006-12-19 UTC" "2007-12-19 UTC" "2008-12-19 UTC"
#> [21] "2009-12-19 UTC" "2010-12-19 UTC" "2011-12-19 UTC" "2012-12-19 UTC"
#> [25] "2013-12-19 UTC" "2014-12-19 UTC" "2015-12-19 UTC" "2016-12-19 UTC"
#> [29] "2017-12-19 UTC" "2018-12-19 UTC" "2019-12-19 UTC" "2020-12-19 UTC"
#> [33] "2021-12-19 UTC" "2022-12-19 UTC"
This means that with yearly we always get all the data available, so there is no need of loops.