Datum add_months(PG_FUNCTION_ARGS) { DateADT day = PG_GETARG_DATEADT(0); int n = PG_GETARG_INT32(1); int y, m, d; int days; DateADT result; div_t v; bool last_day; j2date(day + POSTGRES_EPOCH_JDATE, &y, &m, &d); last_day = (d == days_of_month(y, m)); v = div(y * 12 + m - 1 + n, 12); y = v.quot; if (y < 0) y += 1; /* offset because of year 0 */ m = v.rem + 1; days = days_of_month(y, m); if (last_day || d > days) d = days; result = date2j(y, m, d) - POSTGRES_EPOCH_JDATE; PG_RETURN_DATEADT (result); }
Datum plvdate_prev_bizday (PG_FUNCTION_ARGS) { DateADT day = PG_GETARG_DATEADT(0); PG_RETURN_DATEADT(ora_add_bizdays(day,-1)); }
Datum linterp_DateADT(PG_FUNCTION_ARGS) { DateADT y0; DateADT y1; int32 dy; float8 p; DateADT result; bool eq_bounds = false; bool eq_abscissas = false; /* Common */ p = linterp_abscissa(fcinfo, &eq_bounds, &eq_abscissas); /* Ordinate type specific code*/ y0 = PG_GETARG_DATEADT(2); y1 = PG_GETARG_DATEADT(4); dy = date_diff(y1, y0); if ( eq_bounds ) { if ( eq_abscissas && dy == 0 ) result = y0; else PG_RETURN_NULL(); } else { result = date_pl_days(y0, (int32) (p * (float8) dy)); } PG_RETURN_DATEADT(result); }
Datum plvdate_add_bizdays (PG_FUNCTION_ARGS) { DateADT day = PG_GETARG_DATEADT(0); int days = PG_GETARG_INT32(1); PG_RETURN_DATEADT(ora_add_bizdays(day,days)); }
Datum next_day(PG_FUNCTION_ARGS) { DateADT day = PG_GETARG_DATEADT(0); text *day_txt = PG_GETARG_TEXT_PP(1); const char *str = VARDATA_ANY(day_txt); int len = VARSIZE_ANY_EXHDR(day_txt); int off; int d = -1; #ifdef ENABLE_INTERNATIONALIZED_WEEKDAY /* Check mru_weekdays first for performance. */ if (mru_weekdays) { if ((d = weekday_search(mru_weekdays, str, len)) >= 0) goto found; else mru_weekdays = NULL; } #endif /* * Oracle uses only 3 heading characters of the input. * Ignore all trailing characters. */ if (len >= 3 && (d = ora_seq_prefix_search(str, ora_days, 3)) >= 0) goto found; #ifdef ENABLE_INTERNATIONALIZED_WEEKDAY do { int i; int encoding = GetDatabaseEncoding(); for (i = 0; i < lengthof(WEEKDAYS); i++) { if (encoding == WEEKDAYS[i].encoding) { if ((d = weekday_search(&WEEKDAYS[i], str, len)) >= 0) { mru_weekdays = &WEEKDAYS[i]; goto found; } } } } while(0); #endif CHECK_SEQ_SEARCH(-1, "DAY/Day/day"); found: off = d - j2day(day+POSTGRES_EPOCH_JDATE); PG_RETURN_DATEADT((off <= 0) ? day+off+7 : day + off); }
Datum last_day(PG_FUNCTION_ARGS) { DateADT day = PG_GETARG_DATEADT(0); DateADT result; int y, m, d; j2date(day + POSTGRES_EPOCH_JDATE, &y, &m, &d); result = date2j(y, m+1, 1) - POSTGRES_EPOCH_JDATE; PG_RETURN_DATEADT(result - 1); }
Datum ora_date_round(PG_FUNCTION_ARGS) { DateADT day = PG_GETARG_DATEADT(0); text *fmt = PG_GETARG_TEXT_PP(1); DateADT result; int f = ora_seq_search(VARDATA_ANY(fmt), date_fmt, VARSIZE_ANY_EXHDR(fmt)); CHECK_SEQ_SEARCH(f, "round/trunc format string"); result = _ora_date_round(day, f); PG_RETURN_DATEADT(result); }
Datum plvdate_nearest_bizday (PG_FUNCTION_ARGS) { DateADT dt = PG_GETARG_DATEADT(0); DateADT d1, d2, res; d1 = ora_add_bizdays(dt, -1); d2 = ora_add_bizdays(dt, 1); if ((dt - d1) > (d2 - dt)) res = d2; else res = d1; PG_RETURN_DATEADT(res); }
/* next_day(date, integer) is not documented in Oracle manual, but ... */ Datum next_day_by_index(PG_FUNCTION_ARGS) { DateADT day = PG_GETARG_DATEADT(0); int idx = PG_GETARG_INT32(1); int off; /* * off is 1..7 (Sun..Sat). * * TODO: It should be affected by NLS_TERRITORY. For example, * 1..7 should be interpreted as Mon..Sun in GERMAN. */ CHECK_SEQ_SEARCH((idx < 1 || 7 < idx) ? -1 : 0, "DAY/Day/day"); /* j2day returns 0..6 as Sun..Sat */ off = (idx - 1) - j2day(day+POSTGRES_EPOCH_JDATE); PG_RETURN_DATEADT((off <= 0) ? day+off+7 : day + off); }