66char *option[N_OPTIONS] = {
77 " sddstimeconvert [<SDDSinput>] [<SDDSoutput>] \n"
78 " [-pipe=<input>[,<output>]] \n"
79 " [-majorOrder=row|column]\n"
80 " [-breakdown={column|parameter},<timeName>[,year=<newName>]\n"
81 " [,julianDay=<newName>]\n"
82 " [,month=<newName>]\n"
84 " [,hour=<newName>]\n"
85 " [,text=<newName>]]\n"
86 " [-dateToTime={column|parameter},<timeName>,<newName>,<stringName>,format=<formatString>]\n"
87 " [-epoch={column|parameter},<newName>,year=<name>,[julianDay=<name>|month=<name>,day=<name>],hour=<name>]\n"
89 " -pipe Enable standard SDDS Toolkit pipe processing.\n"
90 " -majorOrder Specify output file order: row or column major.\n"
91 " -breakdown Break down epoch time into components.\n"
92 " -epoch Create a new epoch time column or parameter.\n"
93 " -dateToTime Convert date string to epoch time.\n\n"
94 "Program by Michael Borland. (" __DATE__
" " __TIME__
", SVN revision: " SVN_VERSION
")\n";
96#define IS_COLUMN 0x0001U
97#define IS_PARAMETER 0x0002U
98#define EPOCH_GIVEN 0x0004U
99#define YEAR_GIVEN 0x0008U
100#define JDAY_GIVEN 0x0010U
101#define MONTH_GIVEN 0x0020U
102#define DAY_GIVEN 0x0040U
103#define HOUR_GIVEN 0x0080U
104#define DO_BREAKDOWN 0x0100U
105#define DO_EPOCH 0x0200U
106#define TEXT_GIVEN 0x0400U
107#define FORMAT_GIVEN 0x0800U
108#define DO_DATECONVERSION 0x1000U
112 char *epochName, *yearName, *jDayName, *monthName, *dayName, *hourName;
113 char *textName, *format;
114 long epochIndex, yearIndex, jDayIndex, monthIndex, dayIndex, hourIndex;
131int main(
int argc,
char **argv) {
135 char *input, *output;
138 unsigned long pipeFlags, majorOrderFlag;
139 short columnMajorOrder = -1;
142 argc =
scanargs(&s_arg, argc, argv);
144 fprintf(stderr,
"%s", USAGE);
148 input = output = NULL;
153 for (i_arg = 1; i_arg < argc; i_arg++) {
154 if (s_arg[i_arg].arg_type == OPTION) {
155 switch (
match_string(s_arg[i_arg].list[0], option, N_OPTIONS, 0)) {
156 case SET_MAJOR_ORDER:
158 s_arg[i_arg].n_items--;
159 if (s_arg[i_arg].n_items > 0 &&
160 (!
scanItemList(&majorOrderFlag, s_arg[i_arg].list + 1, &s_arg[i_arg].n_items, 0,
161 "row", -1, NULL, 0, SDDS_ROW_MAJOR_ORDER,
162 "column", -1, NULL, 0, SDDS_COLUMN_MAJOR_ORDER, NULL)))
163 SDDS_Bomb(
"invalid -majorOrder syntax/values");
164 if (majorOrderFlag & SDDS_COLUMN_MAJOR_ORDER)
165 columnMajorOrder = 1;
166 else if (majorOrderFlag & SDDS_ROW_MAJOR_ORDER)
167 columnMajorOrder = 0;
170 if (s_arg[i_arg].n_items < 4)
172 if (!(conversion =
SDDS_Realloc(conversion,
sizeof(*conversion) * (conversions + 1))))
174 memset((
char *)(conversion + conversions), 0,
sizeof(*conversion));
175 conversion[conversions].epochName = s_arg[i_arg].list[2];
176 s_arg[i_arg].list[2] = s_arg[i_arg].list[1];
177 s_arg[i_arg].n_items -= 2;
179 s_arg[i_arg].list + 2, &s_arg[i_arg].n_items, 0,
180 "column", -1, NULL, 0, IS_COLUMN,
181 "parameter", -1, NULL, 0, IS_PARAMETER,
182 "year",
SDDS_STRING, &conversion[conversions].yearName, 1, YEAR_GIVEN,
183 "julianday",
SDDS_STRING, &conversion[conversions].jDayName, 1, JDAY_GIVEN,
184 "month",
SDDS_STRING, &conversion[conversions].monthName, 1, MONTH_GIVEN,
185 "day",
SDDS_STRING, &conversion[conversions].dayName, 1, DAY_GIVEN,
186 "hour",
SDDS_STRING, &conversion[conversions].hourName, 1, HOUR_GIVEN, NULL))
188 conversion[conversions].flags |= EPOCH_GIVEN | DO_EPOCH;
189 if (!(conversion[conversions].flags & (IS_COLUMN | IS_PARAMETER)))
190 SDDS_Bomb(
"Specify 'column' or 'parameter' qualifier with -epoch");
191 if (conversion[conversions].flags & IS_COLUMN && conversion[conversions].flags & IS_PARAMETER)
192 SDDS_Bomb(
"Specify only one of 'column' or 'parameter' qualifier with -epoch");
193 if (!(conversion[conversions].flags & YEAR_GIVEN))
194 SDDS_Bomb(
"Specify year name with -epoch");
195 if (!(conversion[conversions].flags & JDAY_GIVEN) &&
196 (conversion[conversions].flags & (MONTH_GIVEN | DAY_GIVEN)) != (MONTH_GIVEN | DAY_GIVEN))
197 SDDS_Bomb(
"Specify either julianDay name, or both month and day names with -epoch");
198 if (conversion[conversions].flags & JDAY_GIVEN && conversion[conversions].flags & (MONTH_GIVEN | DAY_GIVEN))
199 SDDS_Bomb(
"Invalid combination of julianDay name with month or day name for -epoch");
203 if (s_arg[i_arg].n_items < 4)
205 if (!(conversion =
SDDS_Realloc(conversion,
sizeof(*conversion) * (conversions + 1))))
207 memset((
char *)(conversion + conversions), 0,
sizeof(*conversion));
208 conversion[conversions].epochName = s_arg[i_arg].list[2];
209 s_arg[i_arg].list[2] = s_arg[i_arg].list[1];
210 s_arg[i_arg].n_items -= 2;
212 s_arg[i_arg].list + 2, &s_arg[i_arg].n_items, 0,
213 "column", -1, NULL, 0, IS_COLUMN,
214 "parameter", -1, NULL, 0, IS_PARAMETER,
215 "year",
SDDS_STRING, &conversion[conversions].yearName, 1, YEAR_GIVEN,
216 "julianday",
SDDS_STRING, &conversion[conversions].jDayName, 1, JDAY_GIVEN,
217 "month",
SDDS_STRING, &conversion[conversions].monthName, 1, MONTH_GIVEN,
218 "day",
SDDS_STRING, &conversion[conversions].dayName, 1, DAY_GIVEN,
219 "hour",
SDDS_STRING, &conversion[conversions].hourName, 1, HOUR_GIVEN,
220 "text",
SDDS_STRING, &conversion[conversions].textName, 1, TEXT_GIVEN, NULL))
222 conversion[conversions].flags |= EPOCH_GIVEN | DO_BREAKDOWN;
223 if (!(conversion[conversions].flags & (IS_COLUMN | IS_PARAMETER)))
224 SDDS_Bomb(
"Specify 'column' or 'parameter' qualifier with -breakdown");
225 if (conversion[conversions].flags & IS_COLUMN && conversion[conversions].flags & IS_PARAMETER)
226 SDDS_Bomb(
"Specify only one of 'column' or 'parameter' qualifier with -breakdown");
227 if (!(conversion[conversions].flags & (YEAR_GIVEN | JDAY_GIVEN | MONTH_GIVEN | DAY_GIVEN | HOUR_GIVEN | TEXT_GIVEN)))
228 SDDS_Bomb(
"Specify at least one of year, julianDay, month, day, hour, or text qualifiers with -breakdown");
232 if (s_arg[i_arg].n_items < 4)
234 if (!(conversion =
SDDS_Realloc(conversion,
sizeof(*conversion) * (conversions + 1))))
236 memset((
char *)(conversion + conversions), 0,
sizeof(*conversion));
237 conversion[conversions].textName = s_arg[i_arg].list[3];
238 conversion[conversions].epochName = s_arg[i_arg].list[2];
239 s_arg[i_arg].list[3] = s_arg[i_arg].list[1];
240 s_arg[i_arg].n_items -= 3;
242 s_arg[i_arg].list + 3, &s_arg[i_arg].n_items, 0,
243 "column", -1, NULL, 0, IS_COLUMN,
244 "parameter", -1, NULL, 0, IS_PARAMETER,
245 "format",
SDDS_STRING, &conversion[conversions].format, 1, FORMAT_GIVEN, NULL))
247 conversion[conversions].flags |= DO_DATECONVERSION;
248 if (!(conversion[conversions].flags & (IS_COLUMN | IS_PARAMETER)))
249 SDDS_Bomb(
"Specify 'column' or 'parameter' qualifier with -dateToTime");
250 if (conversion[conversions].flags & IS_COLUMN && conversion[conversions].flags & IS_PARAMETER)
251 SDDS_Bomb(
"Specify only one of 'column' or 'parameter' qualifier with -dateToTime");
252 if (!(conversion[conversions].flags & FORMAT_GIVEN))
253 SDDS_Bomb(
"Format string not provided for date to time conversion");
257 if (!
processPipeOption(s_arg[i_arg].list + 1, s_arg[i_arg].n_items - 1, &pipeFlags))
261 fprintf(stderr,
"Error: Unknown option: %s\n", s_arg[i_arg].list[0]);
267 input = s_arg[i_arg].list[0];
269 output = s_arg[i_arg].list[0];
271 fprintf(stderr,
"Error: Argument '%s' is invalid: too many filenames (sddstimeconvert)\n", s_arg[i_arg].list[0]);
284 CheckEpochConversionElements(&SDDSin, conversion, conversions);
285 CheckBreakdownConversionElements(&SDDSin, conversion, conversions);
286 CheckDateConversionElements(&SDDSin, conversion, conversions);
288 InitializeOutput(&SDDSout, output, conversion, conversions, &SDDSin, columnMajorOrder);
295 for (iconv = 0; iconv < conversions; iconv++) {
296 if (conversion[iconv].flags & DO_EPOCH) {
297 if (conversion[iconv].flags & IS_PARAMETER)
298 DoParameterEpochConversion(&SDDSout, &SDDSin, conversion + iconv);
300 DoColumnEpochConversion(&SDDSout, &SDDSin, conversion + iconv);
301 }
else if (conversion[iconv].flags & DO_BREAKDOWN) {
302 if (conversion[iconv].flags & IS_PARAMETER)
303 DoParameterBreakdownConversion(&SDDSout, &SDDSin, conversion + iconv);
305 DoColumnBreakdownConversion(&SDDSout, &SDDSin, conversion + iconv);
308 if (conversion[iconv].flags & IS_PARAMETER)
309 DoParameterDateToTimeConversion(&SDDSout, &SDDSin, conversion + iconv);
311 DoColumnDateToTimeConversion(&SDDSout, &SDDSin, conversion + iconv);
328 while (conversions-- > 0) {
329 if (!(conversion[conversions].flags & DO_EPOCH))
331 if (conversion->flags & IS_PARAMETER) {
333 (conversion->jDayName &&
335 (conversion->dayName &&
337 (conversion->monthName &&
343 conversion->dayIndex = conversion->jDayIndex = conversion->monthIndex = -1;
344 if (conversion->dayName)
346 if (conversion->jDayName)
348 if (conversion->monthName)
352 (conversion->jDayName &&
354 (conversion->dayName &&
356 (conversion->monthName &&
362 conversion->dayIndex = conversion->jDayIndex = conversion->monthIndex = -1;
363 if (conversion->dayName)
365 if (conversion->jDayName)
367 if (conversion->monthName)
375 while (conversions-- > 0) {
376 if (!(conversion[conversions].flags & DO_BREAKDOWN))
378 if (conversion->flags & IS_PARAMETER) {
392 while (conversions-- > 0) {
393 if (!(conversion[conversions].flags & DO_DATECONVERSION))
395 if (conversion->flags & IS_PARAMETER) {
404 if (conversion->textIndex < 0) {
405 fprintf(stderr,
"Error: '%s' does not exist in input file.\n", conversion->textName);
416 if (columnMajorOrder != -1)
417 SDDSout->layout.data_mode.column_major = columnMajorOrder;
419 SDDSout->layout.data_mode.column_major = SDDSin->layout.data_mode.column_major;
420 while (conversions-- > 0) {
421 if (conversion->flags & DO_EPOCH) {
422 if (conversion->flags & IS_PARAMETER) {
424 NULL,
"s",
"Time since start of epoch", NULL,
SDDS_DOUBLE, NULL)) < 0)
428 NULL,
"s",
"Time since start of epoch", NULL,
SDDS_DOUBLE, 0)) < 0)
431 }
else if (conversion->flags & DO_BREAKDOWN) {
432 if (conversion->flags & IS_PARAMETER) {
433 if ((conversion->yearName &&
434 (conversion->yearIndex =
SDDS_DefineParameter(SDDSout, conversion->yearName, NULL, NULL,
"Year", NULL,
436 (conversion->dayName &&
437 (conversion->dayIndex =
SDDS_DefineParameter(SDDSout, conversion->dayName, NULL, NULL,
"Day of month",
439 (conversion->monthName &&
440 (conversion->monthIndex =
SDDS_DefineParameter(SDDSout, conversion->monthName, NULL, NULL,
"Month", NULL,
442 (conversion->jDayName &&
443 (conversion->jDayIndex =
SDDS_DefineParameter(SDDSout, conversion->jDayName, NULL, NULL,
"Julian day",
445 (conversion->hourName &&
446 (conversion->hourIndex =
SDDS_DefineParameter(SDDSout, conversion->hourName, NULL, NULL,
"Hour of day",
448 (conversion->textName &&
449 (conversion->textIndex =
SDDS_DefineParameter(SDDSout, conversion->textName, NULL, NULL,
"Timestamp",
453 if ((conversion->yearName &&
454 (conversion->yearIndex =
SDDS_DefineColumn(SDDSout, conversion->yearName, NULL, NULL,
"Year", NULL,
456 (conversion->dayName &&
457 (conversion->dayIndex =
SDDS_DefineColumn(SDDSout, conversion->dayName, NULL, NULL,
"Day of month",
459 (conversion->monthName &&
460 (conversion->monthIndex =
SDDS_DefineColumn(SDDSout, conversion->monthName, NULL, NULL,
"Month", NULL,
462 (conversion->jDayName &&
463 (conversion->jDayIndex =
SDDS_DefineColumn(SDDSout, conversion->jDayName, NULL, NULL,
"Julian day",
465 (conversion->hourName &&
466 (conversion->hourIndex =
SDDS_DefineColumn(SDDSout, conversion->hourName, NULL, NULL,
"Hour of day",
468 (conversion->textName &&
469 (conversion->textIndex =
SDDS_DefineColumn(SDDSout, conversion->textName, NULL, NULL,
"Timestamp",
475 if (conversion->flags & IS_PARAMETER) {
477 NULL,
"s",
"Time since start of epoch", NULL,
SDDS_DOUBLE, NULL)) < 0)
481 NULL,
"s",
"Time since start of epoch", NULL,
SDDS_DOUBLE, 0)) < 0)
493 double month = 0, day = 0, jDay = 0, year, epochTime;
510 double hour, epochTime;
511 short year, jDay, month, day;
518 if ((conversion->yearName &&
520 conversion->yearIndex, (
double)year, -1)) ||
521 (conversion->dayName &&
523 conversion->dayIndex, (
double)day, -1)) ||
524 (conversion->jDayName &&
526 conversion->jDayIndex, (
double)jDay, -1)) ||
527 (conversion->monthName &&
529 conversion->monthIndex, (
double)month, -1)) ||
530 (conversion->hourName &&
532 conversion->hourIndex, (
double)hour, -1)) ||
533 (conversion->textName &&
534 !
SDDS_SetParameters(SDDSout, SDDS_BY_INDEX | SDDS_PASS_BY_VALUE, conversion->textIndex, text, -1)))
540 fprintf(stderr,
"Error: strptime function needed by DoParameterDateToTimeConversion is not available on Windows\n");
544 double month = 0, day = 0, jDay = 0, year, epochTime;
545 char *timestr = NULL;
556 if (strptime(timestr, conversion->format, &tm) == NULL) {
557 fprintf(stderr,
"Error: Failed to parse date string '%s' with format '%s'\n", timestr, conversion->format);
560 year = tm.tm_year + 1900;
561 month = tm.tm_mon + 1;
563 hour = tm.tm_hour + tm.tm_min / 60.0 + tm.tm_sec / 3600.0;
573 double *month, *day, *jDay, *year, *epochTime;
581 jDay = month = day = NULL;
589 if (!(epochTime = (
double *)malloc(
sizeof(*epochTime) * rows)))
592 for (row = 0; row < rows; row++)
593 TimeBreakdownToEpoch((
short)year[row], jDay ? (
short)jDay[row] : 0, month ? (
short)month[row] : 0, day ? (
short)day[row] : 0, hour[row], epochTime + row);
609 fprintf(stderr,
"Error: strptime function needed by DoColumnDateToTimeConversion is not available on Windows\n");
613 double month = 0, day = 0, year = 0, jDay = 0, *epochTime;
615 char **timestr = NULL;
627 if (!(epochTime = (
double *)malloc(
sizeof(*epochTime) * rows)))
630 for (row = 0; row < rows; row++) {
631 if (strptime(timestr[row], conversion->format, &tm) == NULL) {
632 fprintf(stderr,
"Error: Failed to parse date string '%s' with format '%s'\n", timestr[row], conversion->format);
635 year = tm.tm_year + 1900;
636 month = tm.tm_mon + 1;
638 hour = tm.tm_hour + tm.tm_min / 60.0 + tm.tm_sec / 3600.0;
639 TimeBreakdownToEpoch((
short)year, (
short)jDay, (
short)month, (
short)day, hour, epochTime + row);
649 double *hour, *epochTime;
650 short *month, *day, *jDay, *year;
661 month = day = jDay = year = NULL;
663 if ((conversion->hourName && !(hour = (
double *)malloc(
sizeof(*hour) * rows))) ||
664 (conversion->monthName && !(month = (
short *)malloc(
sizeof(*month) * rows))) ||
665 (conversion->dayName && !(day = (
short *)malloc(
sizeof(*day) * rows))) ||
666 (conversion->jDayName && !(jDay = (
short *)malloc(
sizeof(*jDay) * rows))) ||
667 (conversion->textName && !(text = (
char **)malloc(
sizeof(*text) * rows))) ||
668 (conversion->yearName && !(year = (
short *)malloc(
sizeof(*year) * rows))))
671 for (row = 0; row < rows; row++) {
673 text[row] = malloc(
sizeof(**text) * 30);
674 if (!
TimeEpochToBreakdown(year ? year + row : NULL, jDay ? jDay + row : NULL, month ? month + row : NULL, day ? day + row : NULL, hour ? hour + row : NULL, epochTime[row]) ||
676 SDDS_Bomb(
"Problem performing time breakdown");
679 if ((year && !
SDDS_SetColumn(SDDSout, SDDS_BY_NAME, year, rows, conversion->yearName)) ||
680 (day && !
SDDS_SetColumn(SDDSout, SDDS_BY_NAME, day, rows, conversion->dayName)) ||
681 (month && !
SDDS_SetColumn(SDDSout, SDDS_BY_NAME, month, rows, conversion->monthName)) ||
682 (jDay && !
SDDS_SetColumn(SDDSout, SDDS_BY_NAME, jDay, rows, conversion->jDayName)) ||
683 (hour && !
SDDS_SetColumn(SDDSout, SDDS_BY_NAME, hour, rows, conversion->hourName)) ||
684 (text && !
SDDS_SetColumn(SDDSout, SDDS_BY_NAME, text, rows, conversion->textName)))
699 for (row = 0; row < rows; row++)
SDDS (Self Describing Data Set) Data Types Definitions and Function Prototypes.
int32_t SDDS_InitializeCopy(SDDS_DATASET *SDDS_target, SDDS_DATASET *SDDS_source, char *filename, char *filemode)
int32_t SDDS_CopyPage(SDDS_DATASET *SDDS_target, SDDS_DATASET *SDDS_source)
int32_t SDDS_SetParametersFromDoubles(SDDS_DATASET *SDDS_dataset, int32_t mode,...)
int32_t SDDS_SetParameters(SDDS_DATASET *SDDS_dataset, int32_t mode,...)
int32_t SDDS_SetColumnFromDoubles(SDDS_DATASET *SDDS_dataset, int32_t mode, double *data, int64_t rows,...)
Sets the values for a single data column using double-precision floating-point numbers.
int32_t SDDS_SetColumn(SDDS_DATASET *SDDS_dataset, int32_t mode, void *data, int64_t rows,...)
Sets the values for one data column in the current data table of an SDDS dataset.
int32_t SDDS_WritePage(SDDS_DATASET *SDDS_dataset)
Writes the current data table to the output file.
int32_t SDDS_DefineColumn(SDDS_DATASET *SDDS_dataset, const char *name, const char *symbol, const char *units, const char *description, const char *format_string, int32_t type, int32_t field_length)
Defines a data column within the SDDS dataset.
int32_t SDDS_WriteLayout(SDDS_DATASET *SDDS_dataset)
Writes the SDDS layout header to the output file.
int32_t SDDS_DefineParameter(SDDS_DATASET *SDDS_dataset, const char *name, const char *symbol, const char *units, const char *description, const char *format_string, int32_t type, char *fixed_value)
Defines a data parameter with a fixed string value.
int32_t SDDS_FreeStringArray(char **string, int64_t strings)
Frees an array of strings by deallocating each individual string.
int32_t SDDS_GetParameterIndex(SDDS_DATASET *SDDS_dataset, char *name)
Retrieves the index of a named parameter in the SDDS dataset.
int32_t SDDS_GetColumnIndex(SDDS_DATASET *SDDS_dataset, char *name)
Retrieves the index of a named column in the SDDS dataset.
int32_t SDDS_CheckColumn(SDDS_DATASET *SDDS_dataset, char *name, char *units, int32_t type, FILE *fp_message)
Checks if a column exists in the SDDS dataset with the specified name, units, and type.
void SDDS_PrintErrors(FILE *fp, int32_t mode)
Prints recorded error messages to a specified file stream.
void SDDS_RegisterProgramName(const char *name)
Registers the executable program name for use in error messages.
void SDDS_Bomb(char *message)
Terminates the program after printing an error message and recorded errors.
int32_t SDDS_CheckParameter(SDDS_DATASET *SDDS_dataset, char *name, char *units, int32_t type, FILE *fp_message)
Checks if a parameter exists in the SDDS dataset with the specified name, units, and type.
void * SDDS_Realloc(void *old_ptr, size_t new_size)
Reallocates memory to a new size.
#define SDDS_STRING
Identifier for the string data type.
#define SDDS_SHORT
Identifier for the signed short integer data type.
#define SDDS_ANY_NUMERIC_TYPE
Special identifier used by SDDS_Check*() routines to accept any numeric type.
#define SDDS_DOUBLE
Identifier for the double data type.
long match_string(char *string, char **option, long n_options, long mode)
Matches a given string against an array of option strings based on specified modes.
int scanargs(SCANNED_ARG **scanned, int argc, char **argv)
long processPipeOption(char **item, long items, unsigned long *flags)
void processFilenames(char *programName, char **input, char **output, unsigned long pipeFlags, long noWarnings, long *tmpOutputUsed)
long scanItemList(unsigned long *flags, char **item, long *items, unsigned long mode,...)
Scans a list of items and assigns values based on provided keywords and types.
short TimeEpochToBreakdown(short *year, short *jDay, short *month, short *day, double *hour, double epochTime)
Breaks down epoch time into its constituent components.
short TimeBreakdownToEpoch(short year, short jDay, short month, short day, double hour, double *epochTime)
Converts a broken-down time into epoch time.
short TimeEpochToText(char *text, double epochTime)
Converts epoch time to a formatted text string.