/* copy&pasted from .../src/backend/utils/adt/datetime.c */ static void AppendSeconds(char *cp, int sec, fsec_t fsec, int precision, bool fillzeros) { if (fsec == 0) { if (fillzeros) sprintf(cp, "%02d", abs(sec)); else sprintf(cp, "%d", abs(sec)); } else { #ifdef HAVE_INT64_TIMESTAMP if (fillzeros) sprintf(cp, "%02d.%0*d", abs(sec), precision, (int) Abs(fsec)); else sprintf(cp, "%d.%0*d", abs(sec), precision, (int) Abs(fsec)); #else if (fillzeros) sprintf(cp, "%0*.*f", precision + 3, precision, fabs(sec + fsec)); else sprintf(cp, "%.*f", precision, fabs(sec + fsec)); #endif TrimTrailingZeros(cp); } }
/* copy&pasted from .../src/backend/utils/adt/datetime.c */ static void AppendSeconds(char *cp, int sec, fsec_t fsec, int precision, bool fillzeros) { if (fsec == 0) { if (fillzeros) sprintf(cp, "%02d", abs(sec)); else sprintf(cp, "%d", abs(sec)); } else { if (fillzeros) sprintf(cp, "%02d.%0*d", abs(sec), precision, (int) Abs(fsec)); else sprintf(cp, "%d.%0*d", abs(sec), precision, (int) Abs(fsec)); TrimTrailingZeros(cp); } }
/* 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 */ int EncodeInterval(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", Abs(fsec)); #else fsec += tm->tm_sec; sprintf(cp, ":%012.9f", 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_ISO_DATES)) { strcat(cp, " ago"); cp += strlen(cp); } return 0; } /* EncodeInterval() */