interval.c
来自「PostgreSQL7.4.6 for Linux」· C语言 代码 · 共 831 行 · 第 1/2 页
C
831 行
if (*fsec != 0) { int sec;#ifdef HAVE_INT64_TIMESTAMP sec = (*fsec / INT64CONST(1000000)); *fsec -= (sec * INT64CONST(1000000));#else TMODULO(*fsec, sec, 1e0);#endif tm->tm_sec += sec; } if (is_before) { *fsec = -(*fsec); tm->tm_sec = -(tm->tm_sec); tm->tm_min = -(tm->tm_min); tm->tm_hour = -(tm->tm_hour); tm->tm_mday = -(tm->tm_mday); tm->tm_mon = -(tm->tm_mon); tm->tm_year = -(tm->tm_year); } /* ensure that at least one time field has been found */ return (fmask != 0) ? 0 : -1;} /* DecodeInterval() *//* EncodeInterval() * Interpret time structure as a delta time and convert to string. * * Support "traditional Postgres" and ISO-8601 styles. * Actually, afaik ISO does not address time interval formatting, * but this looks similar to the spec for absolute date/time. * - thomas 1998-04-30 */intEncodeInterval(struct tm * tm, fsec_t fsec, int style, char *str){ int is_before = FALSE; int is_nonzero = FALSE; char *cp = str; /* * The sign of year and month are guaranteed to match, since they are * stored internally as "month". But we'll need to check for is_before * and is_nonzero when determining the signs of hour/minute/seconds * fields. */ switch (style) { /* compatible with ISO date formats */ case USE_ISO_DATES: if (tm->tm_year != 0) { sprintf(cp, "%d year%s", tm->tm_year, ((tm->tm_year != 1) ? "s" : "")); cp += strlen(cp); is_before = (tm->tm_year < 0); is_nonzero = TRUE; } if (tm->tm_mon != 0) { sprintf(cp, "%s%s%d mon%s", (is_nonzero ? " " : ""), ((is_before && (tm->tm_mon > 0)) ? "+" : ""), tm->tm_mon, ((tm->tm_mon != 1) ? "s" : "")); cp += strlen(cp); is_before = (tm->tm_mon < 0); is_nonzero = TRUE; } if (tm->tm_mday != 0) { sprintf(cp, "%s%s%d day%s", (is_nonzero ? " " : ""), ((is_before && (tm->tm_mday > 0)) ? "+" : ""), tm->tm_mday, ((tm->tm_mday != 1) ? "s" : "")); cp += strlen(cp); is_before = (tm->tm_mday < 0); is_nonzero = TRUE; } if ((!is_nonzero) || (tm->tm_hour != 0) || (tm->tm_min != 0) || (tm->tm_sec != 0) || (fsec != 0)) { int minus = ((tm->tm_hour < 0) || (tm->tm_min < 0) || (tm->tm_sec < 0) || (fsec < 0)); sprintf(cp, "%s%s%02d:%02d", (is_nonzero ? " " : ""), (minus ? "-" : (is_before ? "+" : "")), abs(tm->tm_hour), abs(tm->tm_min)); cp += strlen(cp); /* Mark as "non-zero" since the fields are now filled in */ is_nonzero = TRUE; /* fractional seconds? */ if (fsec != 0) {#ifdef HAVE_INT64_TIMESTAMP sprintf(cp, ":%02d", abs(tm->tm_sec)); cp += strlen(cp); sprintf(cp, ".%06d", ((fsec >= 0) ? fsec : -(fsec)));#else fsec += tm->tm_sec; sprintf(cp, ":%013.10f", fabs(fsec));#endif TrimTrailingZeros(cp); cp += strlen(cp); is_nonzero = TRUE; } /* otherwise, integer seconds only? */ else if (tm->tm_sec != 0) { sprintf(cp, ":%02d", abs(tm->tm_sec)); cp += strlen(cp); is_nonzero = TRUE; } } break; case USE_POSTGRES_DATES: default: strcpy(cp, "@ "); cp += strlen(cp); if (tm->tm_year != 0) { int year = tm->tm_year; if (tm->tm_year < 0) year = -year; sprintf(cp, "%d year%s", year, ((year != 1) ? "s" : "")); cp += strlen(cp); is_before = (tm->tm_year < 0); is_nonzero = TRUE; } if (tm->tm_mon != 0) { int mon = tm->tm_mon; if (is_before || ((!is_nonzero) && (tm->tm_mon < 0))) mon = -mon; sprintf(cp, "%s%d mon%s", (is_nonzero ? " " : ""), mon, ((mon != 1) ? "s" : "")); cp += strlen(cp); if (!is_nonzero) is_before = (tm->tm_mon < 0); is_nonzero = TRUE; } if (tm->tm_mday != 0) { int day = tm->tm_mday; if (is_before || ((!is_nonzero) && (tm->tm_mday < 0))) day = -day; sprintf(cp, "%s%d day%s", (is_nonzero ? " " : ""), day, ((day != 1) ? "s" : "")); cp += strlen(cp); if (!is_nonzero) is_before = (tm->tm_mday < 0); is_nonzero = TRUE; } if (tm->tm_hour != 0) { int hour = tm->tm_hour; if (is_before || ((!is_nonzero) && (tm->tm_hour < 0))) hour = -hour; sprintf(cp, "%s%d hour%s", (is_nonzero ? " " : ""), hour, ((hour != 1) ? "s" : "")); cp += strlen(cp); if (!is_nonzero) is_before = (tm->tm_hour < 0); is_nonzero = TRUE; } if (tm->tm_min != 0) { int min = tm->tm_min; if (is_before || ((!is_nonzero) && (tm->tm_min < 0))) min = -min; sprintf(cp, "%s%d min%s", (is_nonzero ? " " : ""), min, ((min != 1) ? "s" : "")); cp += strlen(cp); if (!is_nonzero) is_before = (tm->tm_min < 0); is_nonzero = TRUE; } /* fractional seconds? */ if (fsec != 0) {#ifdef HAVE_INT64_TIMESTAMP if (is_before || ((!is_nonzero) && (tm->tm_sec < 0))) tm->tm_sec = -tm->tm_sec; sprintf(cp, "%s%d.%02d secs", (is_nonzero ? " " : ""), tm->tm_sec, (((int) fsec) / 10000)); cp += strlen(cp); if (!is_nonzero) is_before = (fsec < 0);#else fsec_t sec; fsec += tm->tm_sec; sec = fsec; if (is_before || ((!is_nonzero) && (fsec < 0))) sec = -sec; sprintf(cp, "%s%.2f secs", (is_nonzero ? " " : ""), sec); cp += strlen(cp); if (!is_nonzero) is_before = (fsec < 0);#endif is_nonzero = TRUE; /* otherwise, integer seconds only? */ } else if (tm->tm_sec != 0) { int sec = tm->tm_sec; if (is_before || ((!is_nonzero) && (tm->tm_sec < 0))) sec = -sec; sprintf(cp, "%s%d sec%s", (is_nonzero ? " " : ""), sec, ((sec != 1) ? "s" : "")); cp += strlen(cp); if (!is_nonzero) is_before = (tm->tm_sec < 0); is_nonzero = TRUE; } break; } /* identically zero? then put in a unitless zero... */ if (!is_nonzero) { strcat(cp, "0"); cp += strlen(cp); } if (is_before && (style == USE_POSTGRES_DATES)) { strcat(cp, " ago"); cp += strlen(cp); } return 0;} /* EncodeInterval() *//* interval2tm() * Convert a interval data type to a tm structure. */static intinterval2tm(interval span, struct tm * tm, fsec_t *fsec){#ifdef HAVE_INT64_TIMESTAMP int64 time;#else double time;#endif if (span.month != 0) { tm->tm_year = span.month / 12; tm->tm_mon = span.month % 12; } else { tm->tm_year = 0; tm->tm_mon = 0; } time = span.time;#ifdef HAVE_INT64_TIMESTAMP tm->tm_mday = (time / INT64CONST(86400000000)); time -= (tm->tm_mday * INT64CONST(86400000000)); tm->tm_hour = (time / INT64CONST(3600000000)); time -= (tm->tm_hour * INT64CONST(3600000000)); tm->tm_min = (time / INT64CONST(60000000)); time -= (tm->tm_min * INT64CONST(60000000)); tm->tm_sec = (time / INT64CONST(1000000)); *fsec = (time - (tm->tm_sec * INT64CONST(1000000)));#else TMODULO(time, tm->tm_mday, 86400e0); TMODULO(time, tm->tm_hour, 3600e0); TMODULO(time, tm->tm_min, 60e0); TMODULO(time, tm->tm_sec, 1e0); *fsec = time;#endif return 0;} /* interval2tm() */static inttm2interval(struct tm * tm, fsec_t fsec, interval *span){ span->month = ((tm->tm_year * 12) + tm->tm_mon);#ifdef HAVE_INT64_TIMESTAMP span->time = ((((((((tm->tm_mday * INT64CONST(24)) + tm->tm_hour) * INT64CONST(60)) + tm->tm_min) * INT64CONST(60)) + tm->tm_sec) * INT64CONST(1000000)) + fsec);#else span->time = ((((((tm->tm_mday * 24.0) + tm->tm_hour) * 60.0) + tm->tm_min) * 60.0) + tm->tm_sec); span->time = JROUND(span->time + fsec);#endif return 0;} /* tm2interval() */interval *PGTYPESinterval_from_asc(char *str, char **endptr){ interval *result = NULL; fsec_t fsec; struct tm tt, *tm = &tt; int dtype; int nf; char *field[MAXDATEFIELDS]; int ftype[MAXDATEFIELDS]; char lowstr[MAXDATELEN + MAXDATEFIELDS]; char *realptr; char **ptr = (endptr != NULL) ? endptr : &realptr; tm->tm_year = 0; tm->tm_mon = 0; tm->tm_mday = 0; tm->tm_hour = 0; tm->tm_min = 0; tm->tm_sec = 0; fsec = 0; if (strlen(str) >= sizeof(lowstr)) { errno = PGTYPES_INTVL_BAD_INTERVAL; return NULL; } if ((ParseDateTime(str, lowstr, field, ftype, MAXDATEFIELDS, &nf, ptr) != 0) || (DecodeInterval(field, ftype, nf, &dtype, tm, &fsec) != 0)) { errno = PGTYPES_INTVL_BAD_INTERVAL; return NULL; } result = (interval *) pgtypes_alloc(sizeof(interval)); if (!result) return NULL; if (dtype != DTK_DELTA) { errno = PGTYPES_INTVL_BAD_INTERVAL; free(result); return NULL; } if (tm2interval(tm, fsec, result) != 0) { errno = PGTYPES_INTVL_BAD_INTERVAL; free(result); return NULL; } return result;}char *PGTYPESinterval_to_asc(interval *span){ struct tm tt, *tm = &tt; fsec_t fsec; char buf[MAXDATELEN + 1]; int DateStyle = 0; if (interval2tm(*span, tm, &fsec) != 0) { errno = PGTYPES_INTVL_BAD_INTERVAL; return NULL; } if (EncodeInterval(tm, fsec, DateStyle, buf) != 0) { errno = PGTYPES_INTVL_BAD_INTERVAL; return NULL; } return pgtypes_strdup(buf);}intPGTYPESinterval_copy(interval *intvlsrc, interval *intrcldest){ intrcldest->time = intvlsrc->time; intrcldest->month = intvlsrc->month; return 0;}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?