/*
******************************************************************************** * format.c * * This set of routines reformats dates and times into a variety of formats. * * void Jul_FormatDate(dutc, format, string) * prepares a date in general format. * RL_INT4 Jul_FormatTime(secs, isleap, format, string) * prepares a time in general format. * void Jul_FormatPDS(dutc, secs, ndigits, useZ, string) * formats the date and time in PDS format. * void Jul_FormatSQL(dutc, secs, string) * formats the date and time in SQL format. * * Mark Showalter, PDS Ring-Moon Systems Node, November 1995 * Revised by MRS 7/97 with minor updates. * Revised by MRS 6/98 to conform to RingLib naming conventions. *******************************************************************************/ #include <stdio.h> #include <string.h> #include <ctype.h> #include <math.h> #include "julian.h" #include "fortran.h" /*********************************************************** * Definitions ***********************************************************/ #define TEMPSTR_LEN 255 /* temporary string length */ #define ESCAPE '\\' /* escape character */ /*********************************************************** * Static variables ***********************************************************/ static RL_CHAR *(lower_months[12]) = {"january", "february", "march", "april", "may", "june", "july", "august", "september", "october", "november", "december"}; static RL_CHAR *(mixed_months[12]) = {"January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"}; static RL_CHAR *(upper_months[12]) = {"JANUARY", "FEBRUARY", "MARCH", "APRIL", "MAY", "JUNE", "JULY", "AUGUST", "SEPTEMBER", "OCTOBER", "NOVEMBER", "DECEMBER"}; /*********************************************************** * Prototypes of internal functions ***********************************************************/ static RL_INT4 ZJul_RoundSecs RL_PROTO((RL_FLT8 secs, RL_BOOL isleap, RL_INT4 ndigits, RL_INT4 *isecond, RL_INT4 *ifrac)); static RL_BOOL ZJul_ReplaceInt RL_PROTO((RL_CHAR *string, RL_CHAR *match, RL_CHAR *format, RL_INT4 value)); static RL_BOOL ZJul_ReplaceStr RL_PROTO((RL_CHAR *string, RL_CHAR *match, RL_CHAR *format, RL_CHAR *value)); static RL_CHAR *ZJul_FindMatch RL_PROTO((RL_CHAR *string, RL_CHAR *match, RL_CHAR **after)); static void ZJul_RemoveEsc RL_PROTO((RL_CHAR *string)); /* ******************************************************************************** * EXPORTED USER ROUTINES ******************************************************************************** *$ Component_name: * Jul_FormatDate (format.c) *$ Abstract: * Formats a date according to a format string. *$ Keywords: * JULIAN, TIME, FORMATTING * C, PUBLIC *$ Declarations: * void Jul_FormatDate(dutc, format, string) * RL_INT4 dutc; * RL_CHAR *format, *string; *$ Inputs: * dutc day relative to January 1, 2000. * *format null-terminated format string (see detailed * description). *$ Outputs: * *string null-terminated character string containing formatted * date. *$ Returns: * none *$ Side_effects: * none *$ Detailed_description: * This function formats a date according to a format string. The format * string is copied into the output string except for the following * substitutions: * YYYY or yyyy 4-digit year number. * YY or y last two digits of year number. * Y or y year number. * MONTH full month name (all upper-case). * Month full month name (first letter upper-case). * month full month name (all lower-case). * MON 3-letter month name (all upper-case). * Mon 3-letter month name (first letter upper-case). * mon 3-letter month name (all lower-case). * MM or mm 2-digit month number. * M or m month number. * DD or dd 2-digit day number. * D or d day number. * The above substitutions do not take place if the pattern appears as a * part of a longer character string. * * An escape character "\" is removed from the string but prevents the * next character from being either modified or treated as a part of a * neighboring match pattern. Use "\\" to insert the escape character into * the output string. *$ External_references: * Jul_YMDofDUTC() *$ Examples: * Jul_FormatDate(dutc, "yyyy-mm-dd\T", string) * produces a string in PDS date format, including the final "T". * Jul_FormatDate(dutc, "Month d, y", string) * produces a more readable date like "July 4, 1776". *$ Error_handling: * none *$ Limitations: * The dimensioned length of the character string must be long enough to * accomodate the output string plus a final null character. This length * is not checked at runtime. *$ Author_and_institution: * Mark R. Showalter * PDS Ring-Moon Systems Node * NASA/Ames Research Center *$ Version_and_date: * 1.0: November 1995 *$ Change_history: * none *******************************************************************************/ void Jul_FormatDate(dutc, format, string) RL_INT4 dutc; RL_CHAR *format, *string; { RL_INT4 year, month, day; RL_BOOL done; Jul_YMDofDUTC(dutc, &year, &month, &day); strcpy(string, format); /* Replace year field */ done = ZJul_ReplaceInt(string, "YYYY", "%04d", year); if (!done) { done = ZJul_ReplaceInt(string, "yyyy", "%04d", year); if (!done) { done = ZJul_ReplaceInt(string, "YY", "%0d", year%100); if (!done) { done = ZJul_ReplaceInt(string, "yy", "%0d", year%100); if (!done) { done = ZJul_ReplaceInt(string, "Y", "%d", year); if (!done) { done = ZJul_ReplaceInt(string, "y", "%d", year); }}}}} /* Replace month field */ done = ZJul_ReplaceStr(string, "MONTH", "%s", upper_months[month-1]); if (!done) { done = ZJul_ReplaceStr(string, "Month", "%s", mixed_months[month-1]); if (!done) { done = ZJul_ReplaceStr(string, "month", "%s", lower_months[month-1]); if (!done) { done = ZJul_ReplaceStr(string, "MON", "%3.3s", upper_months[month-1]); if (!done) { done = ZJul_ReplaceStr(string, "Mon", "%3.3s", mixed_months[month-1]); if (!done) { done = ZJul_ReplaceStr(string, "mon", "%3.3s", lower_months[month-1]); if (!done) { done = ZJul_ReplaceInt(string, "MM", "%02d", month); if (!done) { done = ZJul_ReplaceInt(string, "mm", "%02d", month); if (!done) { done = ZJul_ReplaceInt(string, "M", "%d", month); if (!done) { done = ZJul_ReplaceInt(string, "m", "%d", month); }}}}}}}}} /* Replace day field */ done = ZJul_ReplaceInt(string, "DD", "%02d", day); if (!done) { done = ZJul_ReplaceInt(string, "dd", "%02d", day); if (!done) { done = ZJul_ReplaceInt(string, "D", "%d", day); if (!done) { done = ZJul_ReplaceInt(string, "d", "%d", day); }}} /* Remove escape characters */ ZJul_RemoveEsc(string); } /* ******************************************************************************** *$ Component_name: * Jul_FormatTime (format.c) *$ Abstract: * Formats a time according to a format string. *$ Keywords: * JULIAN, TIME, FORMATTING * C, PUBLIC *$ Declarations: * RL_INT4 Jul_FormatTime(secs, isleap, format, string) * RL_FLT8 secs; * RL_BOOL isleap; * RL_CHAR *format, *string; *$ Inputs: * secs number of seconds into day. * isleap TRUE if this day has a leap second; FALSE otherwise. * *format null-terminated format string (see detailed * description). *$ Outputs: * *string null-terminated character string containing formatted * time. *$ Returns: * 1 if rounding error shifts the time to the following day; 0 otherwise. *$ Side_effects: * none *$ Detailed_description: * This function formats a date according to a format string. The format * string is copied into the output string except for the following * substitutions: * AM or PM upper-case AM or PM, depending on time. * am or pm lower-case am or pm, depending on time. * HH or hh 2-digit hour. * H or h hour. * MM or mm 2-digit minute. * M or m minute. * SS or ss 2-digit second. * S or s second. * ZZ... or zz... Any sequence is replaced by an equal number of * fractional seconds digits. * The above substitutions do not take place if the pattern appears as a * part of a longer character string. * * An escape character "\" is removed from the string but prevents the * next character from being either modified or treated as a part of a * neighboring match pattern. Use "\\" to insert the escape character into * the output string. *$ External_references: * Jul_HMSofSec() *$ Examples: * This fragment of code formats a date and time. Note that it uses the * returned date offset when formatting the time; the reason is that a time * can round up to midnight, which corresponds to the following day. * * RL_INT4 dutc, delta; * RL_FLT8 secs; * RL_CHAR time_string[80], date_string[80]; * * delta = Jul_FormatTime(secs, Jul_IsLeapDay(dutc), "hh:mm:ss.zzz", * time_string); * Jul_FormatDate(dutc + delta, "yyyy-mm-dd", date_string); * *$ Error_handling: * none *$ Limitations: * The dimensioned length of the character string must be long enough to * accomodate the output string plus a final null character. This length * is not checked at runtime. *$ Author_and_institution: * Mark R. Showalter * PDS Ring-Moon Systems Node * NASA/Ames Research Center *$ Version_and_date: * 1.0: November 1995 *$ Change_history: * none *******************************************************************************/ RL_INT4 Jul_FormatTime(secs, isleap, format, string) RL_FLT8 secs; RL_BOOL isleap; RL_CHAR *format, *string; { RL_INT4 delta, hour, minute, isecond, ifrac, ndigits; RL_CHAR *s, *zptr, tempstr[80]; RL_FLT8 second; RL_BOOL done, ispm; /* Initialize output string */ strcpy(string, format); /* Count 'z's to determine number of fractional digits */ for (s = string; *s != '\0'; s++) { if (*s == 'z' || *s == 'Z') break; } zptr = s; ndigits = 0; for ( ; *s == 'z' || *s == 'Z'; s++) { ndigits++; } /* Replace by a sequence of 'z's by a single 'z' */ if (ndigits > 1) { *zptr = 'z'; zptr++; for ( ; *s != '\0'; zptr++, s++) { *zptr = *s; } *zptr = '\0'; } /* Round seconds */ delta = ZJul_RoundSecs(secs, isleap, ndigits, &isecond, &ifrac); Jul_HMSofSec((RL_INT4) isecond, &hour, &minute, &second); isecond = (RL_INT4) second; /* Replace AM/PM field */ ispm = (hour > 12); if (ispm) { done = ZJul_ReplaceStr(string, "AM", "%s", "PM"); if (!done) { done = ZJul_ReplaceStr(string, "PM", "%s", "PM"); if (!done) { done = ZJul_ReplaceStr(string, "am", "%s", "pm"); if (!done) { done = ZJul_ReplaceStr(string, "pm", "%s", "pm"); }}} } else { done = ZJul_ReplaceStr(string, "AM", "%s", "AM"); if (!done) { done = ZJul_ReplaceStr(string, "PM", "%s", "AM"); if (!done) { done = ZJul_ReplaceStr(string, "am", "%s", "am"); if (!done) { done = ZJul_ReplaceStr(string, "pm", "%s", "am"); }}} } if (done) { if (ispm) hour -= 12; if (hour == 0) hour = 12; } /* Replace hour field */ done = ZJul_ReplaceInt(string, "HH", "%02d", hour); if (!done) { done = ZJul_ReplaceInt(string, "hh", "%02d", hour); if (!done) { done = ZJul_ReplaceInt(string, "H", "%d", hour); if (!done) { done = ZJul_ReplaceInt(string, "h", "%d", hour); }}} /* Replace minute field */ done = ZJul_ReplaceInt(string, "MM", "%02d", minute); if (!done) { done = ZJul_ReplaceInt(string, "mm", "%02d", minute); if (!done) { done = ZJul_ReplaceInt(string, "M", "%d", minute); if (!done) { done = ZJul_ReplaceInt(string, "m", "%d", minute); }}} /* Replace sub-second field */ done = ZJul_ReplaceInt(string, "MM", "%02d", minute); if (!done) { done = ZJul_ReplaceInt(string, "mm", "%02d", minute); if (!done) { done = ZJul_ReplaceInt(string, "M", "%d", minute); if (!done) { done = ZJul_ReplaceInt(string, "m", "%d", minute); }}} /* Replace second field */ done = ZJul_ReplaceInt(string, "SS", "%02d", isecond); if (!done) { done = ZJul_ReplaceInt(string, "ss", "%02d", isecond); if (!done) { done = ZJul_ReplaceInt(string, "S", "%d", isecond); if (!done) { done = ZJul_ReplaceInt(string, "s", "%d", isecond); }}} /* Replace sub-second field */ sprintf( tempstr, "%0*d", ndigits, ifrac); done = ZJul_ReplaceStr(string, "z", "%s", tempstr); /* Remove escape characters */ ZJul_RemoveEsc(string); /* Return change in date */ return delta; } /* ******************************************************************************** *$ Component_name: * Jul_FormatPDS (format.c) *$ Abstract: * This function formats a date and time in PDS format. *$ Keywords: * JULIAN, TIME, FORMATTING * C, PUBLIC *$ Declarations: * void Jul_FormatPDS(dutc, secs, ndigits, useZ, string) * RL_INT4 dutc, nfrac; * RL_FLT8 secs; * RL_BOOL useZ; * RL_CHAR *string; *$ Inputs: * dutc day relative to January 1, 2000. * secs number of seconds into day. * ndigits number of fractional digits to use in second field. * useZ TRUE to append a "Z" character; FALSE to leave it out. *$ Outputs: * *string null-terminated character string containing formatted * date and time. *$ Returns: * none *$ Side_effects: * none *$ Detailed_description: * This function formats a date and time in PDS format. *$ External_references: * Jul_YMDodDUTC(), Jul_HMSofSec() *$ Examples: * none *$ Error_handling: * none *$ Limitations: * The dimensioned length of the character string must be at least * (21+ndigits) characters. This length is not checked at runtime. PDS * format has no representation for years BCE. *$ Author_and_institution: * Mark R. Showalter * PDS Ring-Moon Systems Node * NASA/Ames Research Center *$ Version_and_date: * 1.2: July 1997 *$ Change_history: * 1.0: November 1995 * 1.2: July 1997 -- updated so that is uses the minimum possible * string length when useZ is FALSE. *******************************************************************************/ void Jul_FormatPDS(dutc, secs, ndigits, useZ, string) RL_INT4 dutc, ndigits; RL_FLT8 secs; RL_BOOL useZ; RL_CHAR *string; { RL_FLT8 second; RL_INT4 year, month, day, hour, minute, isecond, ifrac; dutc += ZJul_RoundSecs(secs, Jul_IsLeapDay(dutc), ndigits, &isecond, &ifrac); Jul_YMDofDUTC(dutc, &year, &month, &day); Jul_HMSofSec((RL_FLT8) isecond, &hour, &minute, &second); isecond = (RL_INT4) second; if (ndigits <= 0) { sprintf(string, "%04d-%02d-%02dT%02d:%02d:%02d", year, month, day, hour, minute, isecond); } else { sprintf(string, "%04d-%02d-%02dT%02d:%02d:%02d.%0*d", year, month, day, hour, minute, isecond, ndigits, ifrac); } if (useZ) (void) strcat(string, "Z"); } /* ******************************************************************************** *$ Component_name: * Jul_FormatSQL (format.c) *$ Abstract: * This function formats a date and time in a format compatible with SQL. *$ Keywords: * JULIAN, TIME, FORMATTING * C, PUBLIC *$ Declarations: * void Jul_FormatSQL(dutc, secs, string) * RL_INT4 dutc; * RL_FLT8 secs; * RL_CHAR *string; *$ Inputs: * dutc day relative to January 1, 2000. * secs number of seconds into day. *$ Outputs: * *string null-terminated character string containing formatted * date and time. *$ Returns: * none *$ Side_effects: * none *$ Detailed_description: * This function formats a date and time in a format compatible with SQL. *$ External_references: * Jul_YMDodDUTC(), Jul_HMSofSec() *$ Examples: * none *$ Error_handling: * none *$ Limitations: * The dimensioned length of the character string must be at least 25 * characters. This length is not checked at runtime. SQL has no * representation for years BCE. *$ Author_and_institution: * Mark R. Showalter * PDS Ring-Moon Systems Node * NASA/Ames Research Center *$ Version_and_date: * 1.0: November 1995 *$ Change_history: * none *******************************************************************************/ void Jul_FormatSQL(dutc, secs, string) RL_INT4 dutc; RL_FLT8 secs; RL_CHAR *string; { RL_FLT8 second; RL_INT4 year, month, day, hour, minute, isecond, millisec; dutc += ZJul_RoundSecs(secs, Jul_IsLeapDay(dutc), 3, &isecond, &millisec); Jul_YMDofDUTC(dutc, &year, &month, &day); Jul_HMSofSec((RL_FLT8) isecond, &hour, &minute, &second); isecond = (RL_INT4) second; sprintf(string, "%-3.3s %d, %d %02d:%02d:%02d:%03d", mixed_months[month-1], day, year, hour, minute, isecond, millisec); } /* ******************************************************************************** * INTERNAL FUNCTIONS ******************************************************************************** * RL_INT4 ZJul_RoundSecs(secs, isleap, ndigits, isecs, ifrac) * * This internal function determines the integer and fractional part of a number * of seconds after rounding it to a specified number of fractional digits. * * Input: * secs number of seconds. * isleap TRUE if this day has a leap second; FALSE otherwise. * ndigits number of digits after decimal point. * * Output: * *isecs integer part of number of seconds, after rounding. * *ifrac integer digits of fractional part of number, after * rounding. * * Return: increment to apply to dutc if rounding crosses a day * boundary. *******************************************************************************/ static RL_INT4 ZJul_RoundSecs(secs, isleap, ndigits, isecs, ifrac) RL_FLT8 secs; RL_BOOL isleap; RL_INT4 ndigits, *isecs, *ifrac; { RL_FLT8 scale; RL_INT4 daysecs; /* Round off seconds value */ if (ndigits < 0) ndigits = 0; scale = pow(10., (RL_FLT8) ndigits); secs = floor(secs * scale + 0.5) / scale; /* Save integer and fractional parts */ *isecs = (RL_INT4) floor(secs); *ifrac = (RL_INT4) floor(scale * (secs - *isecs) + 0.5); /* Check for roundoff that crosses a day boundary */ daysecs = (isleap ? 86401:86400); if (*isecs >= daysecs) { *isecs -= daysecs; return 1; } return 0; } /* ******************************************************************************** * RL_BOOL ZJul_ReplaceInt(string, match, format, value) * * This internal function replaces a matched substring in a character string * with an integer. * * Input: * *string string to search. * *match pattern to search string for. * *format format to apply to integer (used in sprintf()). * value integer value to write. * * Output: * *string updated string. * * Return: TRUE if the match string was found; FALSE otherwise. *******************************************************************************/ static RL_BOOL ZJul_ReplaceInt(string, match, format, value) RL_CHAR *string, *match, *format; RL_INT4 value; { RL_CHAR *loc, *after, tempstr1[TEMPSTR_LEN+1], tempstr2[TEMPSTR_LEN+2]; RL_BOOL change; loc = ZJul_FindMatch(string, match, &after); change = (loc != NULL); if (change) { sprintf(tempstr1, format, value); *loc = '\0'; sprintf(tempstr2, "%s%s%s", string, tempstr1, loc + strlen(match)); strcpy(string, tempstr2); } return change; } /* ******************************************************************************** * RL_BOOL ZJul_ReplaceStr(string, match, format, value) * * This internal function replaces a matched substring in a character string * with another string. * * Input: * *string string to search. * *match pattern to search string for. * *format format to apply to character (used in sprintf()). * *value character string to write. * * Output: * *string updated string. * * Return: TRUE if the match string was found; FALSE otherwise. *******************************************************************************/ static RL_BOOL ZJul_ReplaceStr(string, match, format, value) RL_CHAR *string, *match, *format, *value; { RL_CHAR *loc, *after, tempstr1[TEMPSTR_LEN+1], tempstr2[TEMPSTR_LEN+2]; RL_BOOL change; loc = ZJul_FindMatch(string, match, &after); change = (loc != NULL); if (change) { sprintf(tempstr1, format, value); *loc = '\0'; sprintf(tempstr2, "%s%s%s", string, tempstr1, after); strcpy(string, tempstr2); } return change; } /******************************************************************************* * RL_CHAR *ZJul_FindMatch(string, match, after) * * This internal function finds a matching substring within a given string. A * match cannot be delimited by other alphabetic characters. * * Input: * *string string to search. * *match pattern to search string for. * * Output: * after if a match is found, a pointer to the character in the * string following the match. * * Return: a pointer to the first matching character, or NULL if no * match was found. *******************************************************************************/ static RL_CHAR *ZJul_FindMatch(string, match, after) RL_CHAR *string, *match, **after; { RL_CHAR *s; RL_BOOL was_alpha; RL_INT4 i; /* Test each possible starting point in string */ was_alpha = FALSE; for (s = string; *s != '\0'; s++) { /* If this is the escape character, skip it and also the next character */ if (*s == ESCAPE && *(s+1) != '\0') { s++; was_alpha = FALSE; continue; } /* If this character is not alphabetic, no match */ if (!isalpha(*s)) { was_alpha = FALSE; continue; } /* If the previous character was alphabetic, no match */ if (was_alpha) continue; /* Remember that this character is alphabetic */ was_alpha = TRUE; /* If this isn't the first character of the match string, no match */ if (*s != *match) continue; /* OK so far, so test remaining characters */ for (i=1; match[i] != '\0'; i++) { if (s[i] != match[i]) break; } if (match[i] != '\0') continue; /* Make sure the next character is not alphabetic */ if (isalpha(s[i])) continue; /* Otherwise we have a match! */ *after = s + i; return s; } return NULL; } /* ******************************************************************************** * void ZJul_RemoveEsc(string) * * This internal function removes escape characters from a string. * * Input: * *string string to modify. * * Output: * *string modified string. *******************************************************************************/ static void ZJul_RemoveEsc(string) RL_CHAR *string; { RL_CHAR *new, *old; for (new=string, old=string; *old != '\0'; new++, old++) { if (*old == ESCAPE) { old++; if (*old == '\0') break; } *new = *old; } *new = '\0'; } /* ******************************************************************************** * FORTRAN INTERFACE FUNCTIONS ******************************************************************************** *$ Component_name: * FJul_FormatDate (format.c) *$ Abstract: * Formats a date according to a format string. *$ Keywords: * JULIAN, TIME, FORMATTING * FORTRAN, PUBLIC *$ Declarations: * subroutine FJul_FormatDate(dutc, format, string) * integer*4 dutc * character*(*) format, string *$ Inputs: * dutc day relative to January 1, 2000. * format format string (see detailed description). *$ Outputs: * string character string containing formatted date. *$ Returns: * none *$ Side_effects: * none *$ Detailed_description: * This function formats a date according to a format string. The format * string is copied into the output string except for the following * substitutions: * YYYY or yyyy 4-digit year number. * Y or y year number. * MONTH full month name (all upper-case). * Month full month name (first letter upper-case). * month full month name (all lower-case). * MON 3-letter month name (all upper-case). * Mon 3-letter month name (first letter upper-case). * mon 3-letter month name (all lower-case). * MM or mm 2-digit month number. * M or m month number. * DD or dd 2-digit day number. * D or d day number. * The above substitutions do not take place if the pattern appears as a * part of a longer character string. * * An escape character "\" is removed from the string but prevents the * next character from being either modified or treated as a part of a * neighboring match pattern. Use "\\" to insert the escape character into * the output string. *$ External_references: * Jul_FormatDate(), FORT_Cstring(), FORT_Fstring() *$ Examples: * call FJul_FormatDate(dutc, 'yyyy-mm-dd\T', string) * produces a string in PDS date format, including the final "T". * call FJul_FormatDate(dutc, 'Month d, y', string) * produces a more readable date like "July 4, 1776". *$ Error_handling: * none *$ Limitations: * The dimensioned length of the character string must be long enough to * accomodate the output string. This length is not checked at runtime. *$ Author_and_institution: * Mark R. Showalter * PDS Ring-Moon Systems Node * NASA/Ames Research Center *$ Version_and_date: * 1.0: November 1995 *$ Change_history: * none ******************************************************************************** * Note: GJul_FormatDate() defined here is the intermediary routine between * FJul_FormatDate() and Jul_FormatDate(), allowing for the fact that strings * cannot be passed directly between FORTRAN and C. See fjulian.for for the * rest of the code. * * subroutine GJul_FormatDate(dutc, format, string) * integer*4 dutc * byte format, string *******************************************************************************/ void FORTRAN_NAME(gjul_formatdate) (dutc, format, string) RL_INT4 *dutc; RL_CHAR *format, *string; { FORT_Init(); Jul_FormatDate(*dutc, format, string); } /* ******************************************************************************** *$ Component_name: * FJul_FormatTime (format.c) *$ Abstract: * Formats a time according to a format string. *$ Keywords: * JULIAN, TIME, FORMATTING * FORTRAN, PUBLIC *$ Declarations: * integer*4 function FJul_FormatTime(secs, isleap, format, string) * real*8 secs * logical*4 isleap * character*(*) format, string *$ Inputs: * secs number of seconds into day. * isleap .TRUE. if this day has a leap second; .FALSE. otherwise. * format format string (see detailed description). *$ Outputs: * string character string containing formatted time. *$ Returns: * 1 if rounding error shifts the time to the following day; 0 otherwise. *$ Side_effects: * none *$ Detailed_description: * This function formats a date according to a format string. The format * string is copied into the output string except for the following * substitutions: * AM or PM upper-case AM or PM, depending on time. * am or pm lower-case am or pm, depending on time. * HH or hh 2-digit hour. * H or h hour. * MM or mm 2-digit minute. * M or m minute. * SS or ss 2-digit second. * S or s second. * ZZ... or zz... Any sequence is replaced by an equal number of * fractional seconds digits. * The above substitutions do not take place if the pattern appears as a * part of a longer character string. * * An escape character "\" is removed from the string but prevents the * next character from being either modified or treated as a part of a * neighboring match pattern. Use "\\" to insert the escape character into * the output string. *$ External_references: * Jul_FormatTime(), FORT_Cstring(), FORT_Fstring() *$ Examples: * This fragment of code formats a date and time. Note that it uses the * returned date offset when formatting the time; the reason is that a time * can round up to midnight, which corresponds to the following day. * * integer*4 dutc, delta * real*8 secs * character*80 time_string, date_string * * delta = FJul_FormatTime(secs, FJul_IsLeapDay(dutc), 'hh:mm:ss.zzz', * & time_string) * call FJul_FormatDate(dutc + delta, 'yyyy-mm-dd', date_string) * *$ Error_handling: * none *$ Limitations: * The dimensioned length of the character string must be long enough to * accomodate the output string. This length is not checked at runtime. *$ Author_and_institution: * Mark R. Showalter * PDS Ring-Moon Systems Node * NASA/Ames Research Center *$ Version_and_date: * 1.0: November 1995 *$ Change_history: * none ******************************************************************************** * Note: GJul_FormatTime() defined here is the intermediary routine between * FJul_FormatTime() and Jul_FormatTime(), allowing for the fact that strings * cannot be passed directly between FORTRAN and C. See fjulian.for for the * rest of the code. * * subroutine GJul_FormatTime(secs, isleap, format, string) * real*8 secs * logical*4 isleap * byte format, string *******************************************************************************/ RL_INT4 FORTRAN_NAME(gjul_formattime) (secs, isleap, format, string) RL_FLT8 *secs; RL_INT4 *isleap; RL_CHAR *format, *string; { FORT_Init(); return Jul_FormatTime(*secs, (RL_BOOL) *isleap, format, string); } /* ******************************************************************************** *$ Component_name: * FJul_FormatPDS (format.c) *$ Abstract: * This function formats a date and time in PDS format. *$ Keywords: * JULIAN, TIME, FORMATTING * FORTRAN, PUBLIC *$ Declarations: * subroutine FJul_FormatPDS(dutc, secs, ndigits, useZ, string) * integer*4 dutc, nfrac * real*8 secs * logical*4 useZ * character*(*) string *$ Inputs: * dutc day relative to January 1, 2000. * secs number of seconds into day. * ndigits number of fractional digits to use in second field. * useZ .TRUE. to append a "Z" character; .FALSE. to leave it * out. *$ Outputs: * string character string containing formatted date and time. *$ Returns: * none *$ Side_effects: * none *$ Detailed_description: * This function formats a date and time in PDS format. *$ External_references: * Jul_FormatPDS(), FORT_Fstring() *$ Examples: * none *$ Error_handling: * none *$ Limitations: * The dimensioned length of the character string must be at least * (20+ndigits) characters. This length is not checked at runtime. PDS * format has no representation for years BCE. *$ Author_and_institution: * Mark R. Showalter * PDS Ring-Moon Systems Node * NASA/Ames Research Center *$ Version_and_date: * 1.0: November 1995 *$ Change_history: * none ******************************************************************************** * Note: GJul_FormatPDS() defined here is the intermediary routine between * FJul_FormatPDS() and Jul_FormatPDS(), allowing for the fact that strings * cannot be passed directly between FORTRAN and C. See fjulian.for for the * rest of the code. * * subroutine GJul_FormatPDS(dutc, secs, ndigits, useZ, string) * integer*4 dutc, ndigits * real*8 secs * logical*4 useZ * byte string *******************************************************************************/ void FORTRAN_NAME(gjul_formatpds) (dutc, secs, ndigits, useZ, string) RL_INT4 *dutc, *ndigits, *useZ; RL_FLT8 *secs; RL_CHAR *string; { FORT_Init(); Jul_FormatPDS(*dutc, *secs, *ndigits, (RL_BOOL) *useZ, string); } /* ******************************************************************************** *$ Component_name: * FJul_FormatSQL (format.c) *$ Abstract: * This function formats a date and time in a format compatible with SQL. *$ Keywords: * JULIAN, TIME, FORMATTING * FORMAT, PUBLIC *$ Declarations: * subroutine FJul_FormatSQL(dutc, secs, string) * integer*4 dutc * real*8 secs * character*(*) string *$ Inputs: * dutc day relative to January 1, 2000. * secs number of seconds into day. *$ Outputs: * string character string containing formatted date and time. *$ Returns: * none *$ Side_effects: * none *$ Detailed_description: * This function formats a date and time in a format compatible with SQL. *$ External_references: * Jul_FormatSQL(), FORT_Fstring() *$ Examples: * none *$ Error_handling: * none *$ Limitations: * The dimensioned length of the character string must be at least 24 * characters. This length is not checked at runtime. SQL has no * representation for years BCE. *$ Author_and_institution: * Mark R. Showalter * PDS Ring-Moon Systems Node * NASA/Ames Research Center *$ Version_and_date: * 1.0: November 1995 *$ Change_history: * none ******************************************************************************** * Note: GJul_FormatSQL() defined here is the intermediary routine between * FJul_FormatSQL() and Jul_FormatSQL(), allowing for the fact that strings * cannot be passed directly between FORTRAN and C. See fjulian.for for the * rest of the code. * * subroutine GJul_FormatSQL(dutc, secs, string) * integer*4 dutc * real*8 secs * byte string *******************************************************************************/ void FORTRAN_NAME(gjul_formatsql) (dutc, secs, string) RL_INT4 *dutc; RL_FLT8 *secs; RL_CHAR *string; { FORT_Init(); Jul_FormatSQL(*dutc, *secs, string); } /********************************************************************************/