Exemplo n.º 1
0
caddr_t
bif_week (caddr_t * qst, caddr_t * err_ret, state_slot_t ** args)
{
  caddr_t arg = bif_date_arg (qst, args, 0, "week");
  TIMESTAMP_STRUCT ts;
  uint32 nowadays, new_year;

  dt_to_timestamp_struct (arg, &ts);
  nowadays = date2num (ts.year, ts.month, ts.day);
  new_year = date2num (ts.year, 1, 1);

  return (box_num ((nowadays - new_year) / 7 + 1));
}
Exemplo n.º 2
0
/******************************************************************************
 * @brief   Initialize global time origin
 *****************************************************************************/
void
initialize_time()
{
    extern global_param_struct global_param;

    dmy_struct                 dmy;

    // Origin is 0001-01-01
    dmy.year = 1;
    dmy.month = 1;
    dmy.day = 1;
    dmy.day_in_year = 1;
    dmy.dayseconds = 0;

    // Set origin using date2num with numeric origin of 0.
    // This calculates the julian day (in units of days)
    // for 0001-01-01 for the given calendar
    // This is later used as the reference (origin for advancing numeric dates).
    // See make_dmy.c for more details on how global_param.time_origin_num is used.
    global_param.time_origin_num = date2num(0., &dmy, 0., global_param.calendar,
                                            TIME_UNITS_DAYS);
    // Set the string representation of time_origin_num
    strcpy(global_param.time_origin_str, "0001-01-01 00:00:00");
    return;
}
Exemplo n.º 3
0
static int
dayofweek (caddr_t arg)
{
  TIMESTAMP_STRUCT ts;
  uint32 nowadays, easter_sunday = date2num (2000, 4, 30);

  dt_to_timestamp_struct (arg, &ts);
  nowadays = date2num (ts.year, ts.month, ts.day);

  if (nowadays >= easter_sunday)
    return ((nowadays - easter_sunday) % 7 + 1);
  else
    {
      int wday_to_be = (easter_sunday - nowadays) % 7;
      return (!wday_to_be ? 1 : 8 - wday_to_be);
    }
}
Exemplo n.º 4
0
/******************************************************************************
 * @brief    Determine timestep and start year, month, day, and seconds of forcing files
 *****************************************************************************/
void
get_forcing_file_info(param_set_struct *param_set,
                      size_t            file_num)
{
    extern global_param_struct global_param;
    extern filenames_struct    filenames;

    double                     nc_times[2];
    double                     nc_time_origin;
    size_t                     start = 0;
    size_t                     count = 2;
    char                      *nc_unit_chars = NULL;
    char                      *calendar_char = NULL;
    unsigned short int         time_units;
    unsigned short int         calendar;
    dmy_struct                 nc_origin_dmy;
    dmy_struct                 nc_start_dmy;

    // read time info from netcdf file
    get_nc_field_double(filenames.forcing[0], "time", &start, &count, nc_times);
    get_nc_var_attr(filenames.forcing[0], "time", "units", &nc_unit_chars);
    get_nc_var_attr(filenames.forcing[0], "time", "calendar", &calendar_char);

    // parse the calendar string and check to make sure it matches the global clock
    calendar = str_to_calendar(calendar_char);

    // parse the time units
    parse_nc_time_units(nc_unit_chars, &time_units, &nc_origin_dmy);

    // Get date/time of the first entry in the forcing file.
    nc_time_origin =
        date2num(0., &nc_origin_dmy, 0., calendar, TIME_UNITS_DAYS);
    num2date(nc_time_origin, nc_times[0], 0., calendar, time_units,
             &nc_start_dmy);

    // Assign file start date/time
    global_param.forceyear[file_num] = nc_start_dmy.year;
    global_param.forcemonth[file_num] = nc_start_dmy.month;
    global_param.forceday[file_num] = nc_start_dmy.day;
    global_param.forcesec[file_num] = nc_start_dmy.dayseconds;

    // calculate timestep in forcing file
    if (time_units == TIME_UNITS_DAYS) {
        param_set->force_steps_per_day[file_num] =
            (size_t) nearbyint(1. / (nc_times[1] - nc_times[0]));
    }
    else if (time_units == TIME_UNITS_HOURS) {
        param_set->force_steps_per_day[file_num] =
            (size_t) nearbyint(HOURS_PER_DAY / (nc_times[1] - nc_times[0]));
    }
    else if (time_units == TIME_UNITS_MINUTES) {
        param_set->force_steps_per_day[file_num] =
            (size_t) nearbyint(MIN_PER_DAY / (nc_times[1] - nc_times[0]));
    }
    else if (time_units == TIME_UNITS_SECONDS) {
        param_set->force_steps_per_day[file_num] =
            (size_t) nearbyint(SEC_PER_DAY / (nc_times[1] - nc_times[0]));
    }

    // check that this forcing file will work
    if (param_set->force_steps_per_day[file_num] !=
        global_param.model_steps_per_day) {
        log_err("Forcing file timestep must match the model timestep.  "
                "Model timesteps per day is set to %zu and the forcing file "
                "timestep is set to %zu", global_param.model_steps_per_day,
                param_set->force_steps_per_day[file_num])
    }
    if (calendar != global_param.calendar) {
        log_err("Calendar in forcing file (%s) does not match the calendar of "
                "VIC's clock", calendar_char);
    }

    // Free attribute character arrays
    free(nc_unit_chars);
    free(calendar_char);
}
Exemplo n.º 5
0
/******************************************************************************
 * @brief   This function calculates the time_delta in days from a frequency
            and number of steps.
 *****************************************************************************/
double
time_delta(dmy_struct        *dmy_current,
           unsigned short int freq,
           int                n)
{
    extern global_param_struct global_param;

    double                     td, a, b;
    dmy_struct                 dmy_next;
    unsigned short int         lastday[MONTHS_PER_YEAR];
    int                        i;

    // uniform timedeltas
    if (freq == FREQ_NSECONDS) {
        td = (double) n / (double) SEC_PER_DAY;
    }
    else if (freq == FREQ_NMINUTES) {
        td = (double) n / (double) MIN_PER_DAY;
    }
    else if (freq == FREQ_NHOURS) {
        td = (double) n / (double) HOURS_PER_DAY;
    }
    else if (freq == FREQ_NDAYS) {
        td = (double) n;
    }
    // non-uniform timedeltas
    else {
        if (n < 1) {
            log_err("Negative time delta's are not implemented yet")
        }

        // copy dmy structure
        dmy_next = *dmy_current;

        if (freq == FREQ_NMONTHS) {
            dmy_next.month += n;
            if (dmy_next.month > MONTHS_PER_YEAR) {
                dmy_next.month -= MONTHS_PER_YEAR;
                dmy_next.year += 1;
            }
        }
        else if (freq == FREQ_NYEARS) {
            // advance year
            dmy_next.year += n;
            // re-calculate day_in_year (NOTE: currently will have problem
            // if dmy_next.year is not leap year but date is Feb 29 !)
            make_lastday(global_param.calendar, dmy_next.year, lastday);
            dmy_next.day_in_year = 0;
            for ( i = 0; i < MONTHS_PER_YEAR; i++ ) {
                if ( (i+1) == dmy_next.month ) {
                    dmy_next.day_in_year += dmy_next.day;
                    break;
                }
                else {
                    dmy_next.day_in_year += lastday[i];
                }
            }
            // check if the advanced date is a valid date
            if (invalid_date(global_param.calendar, &dmy_next)) {
                log_err("VIC does not support a simulation starting from "
                        "Feb 29 of a leap year with yearly AGGFREQ or "
                        "HISTFREQ.");
            }
        }
        else {
            log_err("Unknown frequency found during time_delta computation");
        }

        // Check to make sure this is a valid time
        if (invalid_date(global_param.calendar, &dmy_next)) {
            log_err("Invalid date found during time_delta computation");
        }

        // Get ordinal representation of these times
        a = date2num(global_param.time_origin_num, dmy_current, 0,
                     global_param.calendar, TIME_UNITS_DAYS);
        b = date2num(global_param.time_origin_num, &dmy_next, 0,
                     global_param.calendar, TIME_UNITS_DAYS);
        td = b - a;
    }

    return td;
}
Exemplo n.º 6
0
int /* Returns number of chars parsed. */
dt_scan_from_buffer (const char *buf, int mode, caddr_t *dt_ret, const char **err_msg_ret)
{
  const char *tail = buf;
  int fld_len, acc, ymd_found = 0, hms_found = 0, msec_factor;
  TIMESTAMP_STRUCT ts;
  memset (&ts, 0, sizeof (TIMESTAMP_STRUCT));
  dt_ret[0] = NULL;
  err_msg_ret[0] = NULL;
  fld_len = 0; acc = 0; while (isdigit (tail[0]) && (4 > fld_len)) { acc = acc * 10 + (tail++)[0] - '0'; fld_len++; }
  if ('-' == tail[0])
    { /* Date delimiter, let's parse date part */
      if (((DT_PRINT_MODE_YMD | DT_PRINT_MODE_HMS) & mode) && !(DT_PRINT_MODE_YMD & mode))
        {
          err_msg_ret[0] = "Time field is expected but date field delimiter is found";
          return 0;
        }
      if (4 != fld_len)
        {
          err_msg_ret[0] = "Year field should have 4 digits";
          return 0;
        }
      ymd_found = 1;
      ts.year = acc;
      tail++;
      fld_len = 0; acc = 0; while (isdigit (tail[0]) && (2 > fld_len)) { acc = acc * 10 + (tail++)[0] - '0'; fld_len++; }
      if (2 != fld_len)
        {
          err_msg_ret[0] = "Month field should have 2 digits";
          return 0;
        }
      if ('-' != tail[0])
        {
          err_msg_ret[0] = "Minus sign is expected after month";
          return 0;
        }
      ts.month = acc;
      tail++;
      fld_len = 0; acc = 0; while (isdigit (tail[0]) && (2 > fld_len)) { acc = acc * 10 + (tail++)[0] - '0'; fld_len++; }
      if (2 != fld_len)
        {
          err_msg_ret[0] = "Day of month field should have 2 digits";
          return 0;
        }
      ts.day = acc;
      if ('T' != tail[0])
        goto scan_tz; /* see below */
      tail++;
      fld_len = 0; acc = 0; while (isdigit (tail[0]) && (2 > fld_len)) { acc = acc * 10 + (tail++)[0] - '0'; fld_len++; }
    }
  if (':' == tail[0])
    { /* Time delimiter, let's parse time part */
      if (((DT_PRINT_MODE_YMD | DT_PRINT_MODE_HMS) & mode) && !(DT_PRINT_MODE_HMS & mode))
        {
          err_msg_ret[0] = "Date field is expected but time field delimiter is found";
          return 0;
        }
      if (2 != fld_len)
        {
          err_msg_ret[0] = "Hour field should have 2 digits";
          return 0;
        }
      hms_found = 1;
      ts.hour = acc;
      tail++;
      fld_len = 0; acc = 0; while (isdigit (tail[0]) && (2 > fld_len)) { acc = acc * 10 + (tail++)[0] - '0'; fld_len++; }
      if (2 != fld_len)
        {
          err_msg_ret[0] = "Minute field should have 2 digits";
          return 0;
        }
      if (':' != tail[0])
        {
          err_msg_ret[0] = "Colon is expected after minute";
          return 0;
        }
      ts.minute = acc;
      tail++;
      fld_len = 0; acc = 0; while (isdigit (tail[0]) && (2 > fld_len)) { acc = acc * 10 + (tail++)[0] - '0'; fld_len++; }
      if (2 != fld_len)
        {
          err_msg_ret[0] = "Second field should have 2 digits";
          return 0;
        }
      ts.second = acc;
      if ('.' == tail[0])
        {
          tail++;
          msec_factor = 1000000000;
          acc = 0;
          if (!isdigit (tail[0]))
            {
              err_msg_ret[0] = "Fraction of second is expected after decimal dot";
              return 0;
            }
          do
            {
              if (msec_factor)
                acc = acc * 10 + (tail[0] - '0');
              tail++;
              msec_factor /= 10;
            } while (isdigit (tail[0]));
          ts.fraction = acc * (msec_factor ? msec_factor : 1);
        }
      if ('Z' != tail[0] && strncmp (tail, " GMT", 4))
	{
	  err_msg_ret[0] = "Colon or time zone is expected after minute";
	  return 0;
	}
    }
  else
    {
      err_msg_ret[0] = "Generic syntax error in date/time";
      return 0;
    }

scan_tz:
/* Now HMS part is complete (or skipped) */
  if ('Z' == tail[0])
    tail++;
  else if (!strncmp (tail, " GMT", 4))
    tail += 4;
  else
    {
      err_msg_ret[0] = "Generic syntax error in date/time";
      return 0;
    }
  if ((DT_PRINT_MODE_YMD & mode) && !ymd_found)
    {
      err_msg_ret[0] = "Datetime expected but time-only string is found";
      return 0;
    }
  if ((DT_PRINT_MODE_HMS & mode) && !hms_found)
    {
      err_msg_ret[0] = "Datetime expected but date-only string is found";
      return 0;
    }
  dt_ret[0] = dk_alloc_box (DT_LENGTH, DV_DATETIME);
  {
    uint32 day;
    day = date2num (ts.year, ts.month, ts.day);
    DT_SET_DAY (dt_ret[0], day);
    DT_SET_HOUR (dt_ret[0], ts.hour);
    DT_SET_MINUTE (dt_ret[0], ts.minute);
    DT_SET_SECOND (dt_ret[0], ts.second);
    DT_SET_FRACTION (dt_ret[0], ts.fraction);
    DT_SET_TZ (dt_ret[0], dt_local_tz);
  }
  SET_DT_TYPE_BY_DTP (dt_ret[0], (ymd_found ? (hms_found ? DV_DATETIME : DV_DATE) : DV_TIME));
  return (tail - buf);
}