52char *option[N_OPTIONS] = {
63 " sddstimeconvert [<SDDSinput>] [<SDDSoutput>] \n"
64 " [-pipe=<input>[,<output>]] \n"
65 " [-majorOrder=row|column]\n"
66 " [-breakdown={column|parameter},<timeName>[,year=<newName>]"
67 "[,julianDay=<newName>][,month=<newName>][,day=<newName>][,hour=<newName>]"
68 "[,text=<newName>]]\n"
69 " [-dateToTime={column|parameter},<timeName>,<newName>,"
70 "<stringName>,format=<formatString>]\n"
71 " [-epoch={column|parameter},<newName>,year=<name>,"
72 "[julianDay=<name>|month=<name>,day=<name>],hour=<name>]\n\n"
74 " -pipe Enable standard SDDS Toolkit pipe processing.\n"
75 " -majorOrder Specify output file order: row or column major.\n"
76 " -breakdown Break down epoch time into components.\n"
77 " -epoch Create a new epoch time column or parameter.\n"
78 " -dateToTime Convert date string to epoch time.\n\n"
79 "Program by Michael Borland. (" __DATE__
" " __TIME__
", SVN revision: " SVN_VERSION
")\n";
81#define IS_COLUMN 0x0001U
82#define IS_PARAMETER 0x0002U
83#define EPOCH_GIVEN 0x0004U
84#define YEAR_GIVEN 0x0008U
85#define JDAY_GIVEN 0x0010U
86#define MONTH_GIVEN 0x0020U
87#define DAY_GIVEN 0x0040U
88#define HOUR_GIVEN 0x0080U
89#define DO_BREAKDOWN 0x0100U
90#define DO_EPOCH 0x0200U
91#define TEXT_GIVEN 0x0400U
92#define FORMAT_GIVEN 0x0800U
93#define DO_DATECONVERSION 0x1000U
97 char *epochName, *yearName, *jDayName, *monthName, *dayName, *hourName;
98 char *textName, *format;
99 long epochIndex, yearIndex, jDayIndex, monthIndex, dayIndex, hourIndex;
116int main(
int argc,
char **argv) {
120 char *input, *output;
123 unsigned long pipeFlags, majorOrderFlag;
124 short columnMajorOrder = -1;
127 argc =
scanargs(&s_arg, argc, argv);
129 fprintf(stderr,
"%s", USAGE);
133 input = output = NULL;
138 for (i_arg = 1; i_arg < argc; i_arg++) {
139 if (s_arg[i_arg].arg_type == OPTION) {
140 switch (
match_string(s_arg[i_arg].list[0], option, N_OPTIONS, 0)) {
141 case SET_MAJOR_ORDER:
143 s_arg[i_arg].n_items--;
144 if (s_arg[i_arg].n_items > 0 &&
145 (!
scanItemList(&majorOrderFlag, s_arg[i_arg].list + 1, &s_arg[i_arg].n_items, 0,
146 "row", -1, NULL, 0, SDDS_ROW_MAJOR_ORDER,
147 "column", -1, NULL, 0, SDDS_COLUMN_MAJOR_ORDER, NULL)))
148 SDDS_Bomb(
"invalid -majorOrder syntax/values");
149 if (majorOrderFlag & SDDS_COLUMN_MAJOR_ORDER)
150 columnMajorOrder = 1;
151 else if (majorOrderFlag & SDDS_ROW_MAJOR_ORDER)
152 columnMajorOrder = 0;
155 if (s_arg[i_arg].n_items < 4)
157 if (!(conversion =
SDDS_Realloc(conversion,
sizeof(*conversion) * (conversions + 1))))
159 memset((
char *)(conversion + conversions), 0,
sizeof(*conversion));
160 conversion[conversions].epochName = s_arg[i_arg].list[2];
161 s_arg[i_arg].list[2] = s_arg[i_arg].list[1];
162 s_arg[i_arg].n_items -= 2;
164 s_arg[i_arg].list + 2, &s_arg[i_arg].n_items, 0,
165 "column", -1, NULL, 0, IS_COLUMN,
166 "parameter", -1, NULL, 0, IS_PARAMETER,
167 "year",
SDDS_STRING, &conversion[conversions].yearName, 1, YEAR_GIVEN,
168 "julianday",
SDDS_STRING, &conversion[conversions].jDayName, 1, JDAY_GIVEN,
169 "month",
SDDS_STRING, &conversion[conversions].monthName, 1, MONTH_GIVEN,
170 "day",
SDDS_STRING, &conversion[conversions].dayName, 1, DAY_GIVEN,
171 "hour",
SDDS_STRING, &conversion[conversions].hourName, 1, HOUR_GIVEN, NULL))
173 conversion[conversions].flags |= EPOCH_GIVEN | DO_EPOCH;
174 if (!(conversion[conversions].flags & (IS_COLUMN | IS_PARAMETER)))
175 SDDS_Bomb(
"Specify 'column' or 'parameter' qualifier with -epoch");
176 if (conversion[conversions].flags & IS_COLUMN && conversion[conversions].flags & IS_PARAMETER)
177 SDDS_Bomb(
"Specify only one of 'column' or 'parameter' qualifier with -epoch");
178 if (!(conversion[conversions].flags & YEAR_GIVEN))
179 SDDS_Bomb(
"Specify year name with -epoch");
180 if (!(conversion[conversions].flags & JDAY_GIVEN) &&
181 (conversion[conversions].flags & (MONTH_GIVEN | DAY_GIVEN)) != (MONTH_GIVEN | DAY_GIVEN))
182 SDDS_Bomb(
"Specify either julianDay name, or both month and day names with -epoch");
183 if (conversion[conversions].flags & JDAY_GIVEN && conversion[conversions].flags & (MONTH_GIVEN | DAY_GIVEN))
184 SDDS_Bomb(
"Invalid combination of julianDay name with month or day name for -epoch");
188 if (s_arg[i_arg].n_items < 4)
190 if (!(conversion =
SDDS_Realloc(conversion,
sizeof(*conversion) * (conversions + 1))))
192 memset((
char *)(conversion + conversions), 0,
sizeof(*conversion));
193 conversion[conversions].epochName = s_arg[i_arg].list[2];
194 s_arg[i_arg].list[2] = s_arg[i_arg].list[1];
195 s_arg[i_arg].n_items -= 2;
197 s_arg[i_arg].list + 2, &s_arg[i_arg].n_items, 0,
198 "column", -1, NULL, 0, IS_COLUMN,
199 "parameter", -1, NULL, 0, IS_PARAMETER,
200 "year",
SDDS_STRING, &conversion[conversions].yearName, 1, YEAR_GIVEN,
201 "julianday",
SDDS_STRING, &conversion[conversions].jDayName, 1, JDAY_GIVEN,
202 "month",
SDDS_STRING, &conversion[conversions].monthName, 1, MONTH_GIVEN,
203 "day",
SDDS_STRING, &conversion[conversions].dayName, 1, DAY_GIVEN,
204 "hour",
SDDS_STRING, &conversion[conversions].hourName, 1, HOUR_GIVEN,
205 "text",
SDDS_STRING, &conversion[conversions].textName, 1, TEXT_GIVEN, NULL))
207 conversion[conversions].flags |= EPOCH_GIVEN | DO_BREAKDOWN;
208 if (!(conversion[conversions].flags & (IS_COLUMN | IS_PARAMETER)))
209 SDDS_Bomb(
"Specify 'column' or 'parameter' qualifier with -breakdown");
210 if (conversion[conversions].flags & IS_COLUMN && conversion[conversions].flags & IS_PARAMETER)
211 SDDS_Bomb(
"Specify only one of 'column' or 'parameter' qualifier with -breakdown");
212 if (!(conversion[conversions].flags & (YEAR_GIVEN | JDAY_GIVEN | MONTH_GIVEN | DAY_GIVEN | HOUR_GIVEN | TEXT_GIVEN)))
213 SDDS_Bomb(
"Specify at least one of year, julianDay, month, day, hour, or text qualifiers with -breakdown");
217 if (s_arg[i_arg].n_items < 4)
219 if (!(conversion =
SDDS_Realloc(conversion,
sizeof(*conversion) * (conversions + 1))))
221 memset((
char *)(conversion + conversions), 0,
sizeof(*conversion));
222 conversion[conversions].textName = s_arg[i_arg].list[3];
223 conversion[conversions].epochName = s_arg[i_arg].list[2];
224 s_arg[i_arg].list[3] = s_arg[i_arg].list[1];
225 s_arg[i_arg].n_items -= 3;
227 s_arg[i_arg].list + 3, &s_arg[i_arg].n_items, 0,
228 "column", -1, NULL, 0, IS_COLUMN,
229 "parameter", -1, NULL, 0, IS_PARAMETER,
230 "format",
SDDS_STRING, &conversion[conversions].format, 1, FORMAT_GIVEN, NULL))
232 conversion[conversions].flags |= DO_DATECONVERSION;
233 if (!(conversion[conversions].flags & (IS_COLUMN | IS_PARAMETER)))
234 SDDS_Bomb(
"Specify 'column' or 'parameter' qualifier with -dateToTime");
235 if (conversion[conversions].flags & IS_COLUMN && conversion[conversions].flags & IS_PARAMETER)
236 SDDS_Bomb(
"Specify only one of 'column' or 'parameter' qualifier with -dateToTime");
237 if (!(conversion[conversions].flags & FORMAT_GIVEN))
238 SDDS_Bomb(
"Format string not provided for date to time conversion");
242 if (!
processPipeOption(s_arg[i_arg].list + 1, s_arg[i_arg].n_items - 1, &pipeFlags))
246 fprintf(stderr,
"Error: Unknown option: %s\n", s_arg[i_arg].list[0]);
252 input = s_arg[i_arg].list[0];
254 output = s_arg[i_arg].list[0];
256 fprintf(stderr,
"Error: Argument '%s' is invalid: too many filenames (sddstimeconvert)\n", s_arg[i_arg].list[0]);
269 CheckEpochConversionElements(&SDDSin, conversion, conversions);
270 CheckBreakdownConversionElements(&SDDSin, conversion, conversions);
271 CheckDateConversionElements(&SDDSin, conversion, conversions);
273 InitializeOutput(&SDDSout, output, conversion, conversions, &SDDSin, columnMajorOrder);
280 for (iconv = 0; iconv < conversions; iconv++) {
281 if (conversion[iconv].flags & DO_EPOCH) {
282 if (conversion[iconv].flags & IS_PARAMETER)
283 DoParameterEpochConversion(&SDDSout, &SDDSin, conversion + iconv);
285 DoColumnEpochConversion(&SDDSout, &SDDSin, conversion + iconv);
286 }
else if (conversion[iconv].flags & DO_BREAKDOWN) {
287 if (conversion[iconv].flags & IS_PARAMETER)
288 DoParameterBreakdownConversion(&SDDSout, &SDDSin, conversion + iconv);
290 DoColumnBreakdownConversion(&SDDSout, &SDDSin, conversion + iconv);
293 if (conversion[iconv].flags & IS_PARAMETER)
294 DoParameterDateToTimeConversion(&SDDSout, &SDDSin, conversion + iconv);
296 DoColumnDateToTimeConversion(&SDDSout, &SDDSin, conversion + iconv);
313 while (conversions-- > 0) {
314 if (!(conversion[conversions].flags & DO_EPOCH))
316 if (conversion->flags & IS_PARAMETER) {
318 (conversion->jDayName &&
320 (conversion->dayName &&
322 (conversion->monthName &&
328 conversion->dayIndex = conversion->jDayIndex = conversion->monthIndex = -1;
329 if (conversion->dayName)
331 if (conversion->jDayName)
333 if (conversion->monthName)
337 (conversion->jDayName &&
339 (conversion->dayName &&
341 (conversion->monthName &&
347 conversion->dayIndex = conversion->jDayIndex = conversion->monthIndex = -1;
348 if (conversion->dayName)
350 if (conversion->jDayName)
352 if (conversion->monthName)
360 while (conversions-- > 0) {
361 if (!(conversion[conversions].flags & DO_BREAKDOWN))
363 if (conversion->flags & IS_PARAMETER) {
377 while (conversions-- > 0) {
378 if (!(conversion[conversions].flags & DO_DATECONVERSION))
380 if (conversion->flags & IS_PARAMETER) {
389 if (conversion->textIndex < 0) {
390 fprintf(stderr,
"Error: '%s' does not exist in input file.\n", conversion->textName);
401 if (columnMajorOrder != -1)
402 SDDSout->layout.data_mode.column_major = columnMajorOrder;
404 SDDSout->layout.data_mode.column_major = SDDSin->layout.data_mode.column_major;
405 while (conversions-- > 0) {
406 if (conversion->flags & DO_EPOCH) {
407 if (conversion->flags & IS_PARAMETER) {
409 NULL,
"s",
"Time since start of epoch", NULL,
SDDS_DOUBLE, NULL)) < 0)
413 NULL,
"s",
"Time since start of epoch", NULL,
SDDS_DOUBLE, 0)) < 0)
416 }
else if (conversion->flags & DO_BREAKDOWN) {
417 if (conversion->flags & IS_PARAMETER) {
418 if ((conversion->yearName &&
419 (conversion->yearIndex =
SDDS_DefineParameter(SDDSout, conversion->yearName, NULL, NULL,
"Year", NULL,
421 (conversion->dayName &&
422 (conversion->dayIndex =
SDDS_DefineParameter(SDDSout, conversion->dayName, NULL, NULL,
"Day of month",
424 (conversion->monthName &&
425 (conversion->monthIndex =
SDDS_DefineParameter(SDDSout, conversion->monthName, NULL, NULL,
"Month", NULL,
427 (conversion->jDayName &&
428 (conversion->jDayIndex =
SDDS_DefineParameter(SDDSout, conversion->jDayName, NULL, NULL,
"Julian day",
430 (conversion->hourName &&
431 (conversion->hourIndex =
SDDS_DefineParameter(SDDSout, conversion->hourName, NULL, NULL,
"Hour of day",
433 (conversion->textName &&
434 (conversion->textIndex =
SDDS_DefineParameter(SDDSout, conversion->textName, NULL, NULL,
"Timestamp",
438 if ((conversion->yearName &&
439 (conversion->yearIndex =
SDDS_DefineColumn(SDDSout, conversion->yearName, NULL, NULL,
"Year", NULL,
441 (conversion->dayName &&
442 (conversion->dayIndex =
SDDS_DefineColumn(SDDSout, conversion->dayName, NULL, NULL,
"Day of month",
444 (conversion->monthName &&
445 (conversion->monthIndex =
SDDS_DefineColumn(SDDSout, conversion->monthName, NULL, NULL,
"Month", NULL,
447 (conversion->jDayName &&
448 (conversion->jDayIndex =
SDDS_DefineColumn(SDDSout, conversion->jDayName, NULL, NULL,
"Julian day",
450 (conversion->hourName &&
451 (conversion->hourIndex =
SDDS_DefineColumn(SDDSout, conversion->hourName, NULL, NULL,
"Hour of day",
453 (conversion->textName &&
454 (conversion->textIndex =
SDDS_DefineColumn(SDDSout, conversion->textName, NULL, NULL,
"Timestamp",
460 if (conversion->flags & IS_PARAMETER) {
462 NULL,
"s",
"Time since start of epoch", NULL,
SDDS_DOUBLE, NULL)) < 0)
466 NULL,
"s",
"Time since start of epoch", NULL,
SDDS_DOUBLE, 0)) < 0)
478 double month = 0, day = 0, jDay = 0, year, epochTime;
495 double hour, epochTime;
496 short year, jDay, month, day;
503 if ((conversion->yearName &&
505 conversion->yearIndex, (
double)year, -1)) ||
506 (conversion->dayName &&
508 conversion->dayIndex, (
double)day, -1)) ||
509 (conversion->jDayName &&
511 conversion->jDayIndex, (
double)jDay, -1)) ||
512 (conversion->monthName &&
514 conversion->monthIndex, (
double)month, -1)) ||
515 (conversion->hourName &&
517 conversion->hourIndex, (
double)hour, -1)) ||
518 (conversion->textName &&
519 !
SDDS_SetParameters(SDDSout, SDDS_BY_INDEX | SDDS_PASS_BY_VALUE, conversion->textIndex, text, -1)))
525 fprintf(stderr,
"Error: strptime function needed by DoParameterDateToTimeConversion is not available on Windows\n");
529 double month = 0, day = 0, jDay = 0, year, epochTime;
530 char *timestr = NULL;
541 if (strptime(timestr, conversion->format, &tm) == NULL) {
542 fprintf(stderr,
"Error: Failed to parse date string '%s' with format '%s'\n", timestr, conversion->format);
545 year = tm.tm_year + 1900;
546 month = tm.tm_mon + 1;
548 hour = tm.tm_hour + tm.tm_min / 60.0 + tm.tm_sec / 3600.0;
558 double *month, *day, *jDay, *year, *epochTime;
566 jDay = month = day = NULL;
574 if (!(epochTime = (
double *)malloc(
sizeof(*epochTime) * rows)))
577 for (row = 0; row < rows; row++)
578 TimeBreakdownToEpoch((
short)year[row], jDay ? (
short)jDay[row] : 0, month ? (
short)month[row] : 0, day ? (
short)day[row] : 0, hour[row], epochTime + row);
594 fprintf(stderr,
"Error: strptime function needed by DoColumnDateToTimeConversion is not available on Windows\n");
598 double month = 0, day = 0, year = 0, jDay = 0, *epochTime;
600 char **timestr = NULL;
612 if (!(epochTime = (
double *)malloc(
sizeof(*epochTime) * rows)))
615 for (row = 0; row < rows; row++) {
616 if (strptime(timestr[row], conversion->format, &tm) == NULL) {
617 fprintf(stderr,
"Error: Failed to parse date string '%s' with format '%s'\n", timestr[row], conversion->format);
620 year = tm.tm_year + 1900;
621 month = tm.tm_mon + 1;
623 hour = tm.tm_hour + tm.tm_min / 60.0 + tm.tm_sec / 3600.0;
624 TimeBreakdownToEpoch((
short)year, (
short)jDay, (
short)month, (
short)day, hour, epochTime + row);
634 double *hour, *epochTime;
635 short *month, *day, *jDay, *year;
646 month = day = jDay = year = NULL;
648 if ((conversion->hourName && !(hour = (
double *)malloc(
sizeof(*hour) * rows))) ||
649 (conversion->monthName && !(month = (
short *)malloc(
sizeof(*month) * rows))) ||
650 (conversion->dayName && !(day = (
short *)malloc(
sizeof(*day) * rows))) ||
651 (conversion->jDayName && !(jDay = (
short *)malloc(
sizeof(*jDay) * rows))) ||
652 (conversion->textName && !(text = (
char **)malloc(
sizeof(*text) * rows))) ||
653 (conversion->yearName && !(year = (
short *)malloc(
sizeof(*year) * rows))))
656 for (row = 0; row < rows; row++) {
658 text[row] = malloc(
sizeof(**text) * 30);
659 if (!
TimeEpochToBreakdown(year ? year + row : NULL, jDay ? jDay + row : NULL, month ? month + row : NULL, day ? day + row : NULL, hour ? hour + row : NULL, epochTime[row]) ||
661 SDDS_Bomb(
"Problem performing time breakdown");
664 if ((year && !
SDDS_SetColumn(SDDSout, SDDS_BY_NAME, year, rows, conversion->yearName)) ||
665 (day && !
SDDS_SetColumn(SDDSout, SDDS_BY_NAME, day, rows, conversion->dayName)) ||
666 (month && !
SDDS_SetColumn(SDDSout, SDDS_BY_NAME, month, rows, conversion->monthName)) ||
667 (jDay && !
SDDS_SetColumn(SDDSout, SDDS_BY_NAME, jDay, rows, conversion->jDayName)) ||
668 (hour && !
SDDS_SetColumn(SDDSout, SDDS_BY_NAME, hour, rows, conversion->hourName)) ||
669 (text && !
SDDS_SetColumn(SDDSout, SDDS_BY_NAME, text, rows, conversion->textName)))
684 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.