2017-05-26 13 views
0

Ich arbeite mit einer Reihe von Klimamodell Ausgabe (CMIP5 models, speziell). Dies sind netcdfs von Zeitstempel Temperatur, Wind, etc.Konvertieren von Epochen mit nicht-Gregorianischen Kalender

Sie alle verwenden eine days since YYYY-mm-dd 00:00:00 Konvention in UTC. Ich habe zu erleichtern Datum Umwandlung (nicht Datum-Zeit) Objekte mit lubridate:

library(tidyverse) 
input$date.utc = 
    ymd_hms('0001-01-01 00:00:00', tz = 'UTC') + 
    days(floor(input$time)) 

Ich habe zwei Probleme getroffen. Einer davon ist, dass jedes Modell eine andere Epoche hat. Das ist ziemlich einfach zu beheben. Das andere, härtere Problem ist, dass nicht alle Modelle einen Gregorianischen Kalender verwenden. Einige verwenden eine 365-Tage-Variante, bei der es keine Schaltjahre gibt.

Ich sehe keine Möglichkeit, einen nicht-Gregorianischen Kalender in den lubridate Funktionen anzugeben. Ist das möglich?

Antwort

0

Ich konnte nicht diese Funktionalität in lubridate finden, so schrieb ich eine Funktion zumindest berechnen die Anzahl der Schalttage zwischen den einzelnen Elementen eines Vektors von Daten und einer bestimmten Epoche: diese

# count_leap_days: returns an integer for the number of leap days between a 
# supplied vector of dates and a fixed epoch 
count_leap_days <- function(dates, epoch = ymd('1850-01-01'), proleptic = FALSE) 
{ 
    require(lubridate) 

    # check input 
    if (!is(epoch, 'Date') | !is(dates, 'Date')) 
    { 
    stop('count_leap_days: both arguments must be Date objects.') 
    } 
    if (any(dates <= epoch)) 
    { 
    stop('count_leap_days: dates should all be later than epoch.') 
    } 
    if (proleptic = FALSE & epoch < ymd('1582-10-15')) 
    { 
    message('count_leap_days: ', 
     'no leap days before 1582-10-15 unless proleptic = TRUE.') 
    epoch = ymd('1582-10-15') 
    } 

    # get the year range 
    # exclude start (end) years if they begin after (start before) feb 29 
    y.epoch = year(epoch) + 
    ifelse(epoch >= ymd(paste0(year(epoch), '-03-01')), 1, 0) 
    y.dates = year(dates) - 
    ifelse(dates <= ymd(paste0(year(dates), '-02-28')), 1, 0) 
    span = y.dates - y.epoch + 1 

    # a year is a leap year if it's: 
    # - divisble by 4. but 
    # - NOT if it's also divisible by 100, unless 
    # - it's also divisible by 400. 
    # all years div. by 4 are also div. by 100, and 
    # all years div. by 100 are also div. by 400. 
    # hence, total days = (div. by 4) - (div. by 100) + (div. by 400) 
    div4 = span %/% 4 + 
    ifelse(
     (y.epoch %% 4) %in% c(0, (4 - (span %% 4) - 1):(4 - 1)) & 
     (y.dates %% 4) %in% 0:(span %% 4 - 1), 
    1, 0) 
    div100 = span %/% 100 + 
    ifelse(
     (y.epoch %% 100) %in% c(0, (100 - (span %% 100) - 1):(100 - 1)) & 
     (y.dates %% 100) %in% 0:(span %% 100 - 1), 
    1, 0) 
    div400 = span %/% 400 + 
    ifelse(
     (y.epoch %% 400) %in% c(0, (400 - (span %% 400) - 1):(400 - 1)) & 
     (y.dates %% 400) %in% 0:(span %% 400 - 1), 
    1, 0) 
    return(div4 - div100 + div400) 
} 

Mit Kann ich von einem 365-Tage-Kalender in Gregorianisch umwandeln, indem ich einfach die Anzahl der fehlenden Schalttage hinzufüge:

input$date.utc = input$date.utc + 
    count_leap_days(input$date.utc, epoch = epoch) 
Verwandte Themen