/* format.c ********************************************************************************
* 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);
}
/*******************************************************************************
*/