SDDSlib
Loading...
Searching...
No Matches
sddstimeconvert.c
Go to the documentation of this file.
1/**
2 * @file sddstimeconvert.c
3 * @brief Perform time conversions on SDDS (Self Describing Data Sets) data.
4 *
5 * This program allows users to convert and manipulate time-related data within SDDS files.
6 * It supports various operations such as breaking down epoch times into components,
7 * converting date strings to epoch times, and specifying the major order of output data.
8 *
9 * ## Usage
10 * ```
11 * sddstimeconvert [<SDDSinput>] [<SDDSoutput>]
12 * [-pipe=<input>[,<output>]]
13 * [-majorOrder=row|column]
14 * [-breakdown={column|parameter},<timeName>[,year=<newName>][,julianDay=<newName>][,month=<newName>][,day=<newName>][,hour=<newName>][,text=<newName>]]
15 * [-dateToTime={column|parameter},<timeName>,<newName>,<stringName>,format=<formatString>]
16 * [-epoch={column|parameter},<newName>,year=<name>,[julianDay=<name>|month=<name>,day=<name>],hour=<name>]
17 * ```
18 *
19 * ## Options
20 * -pipe=<input>[,<output>]
21 * -majorOrder=row|column
22 * -breakdown={column|parameter},<timeName>[,year=<newName>][,julianDay=<newName>][,month=<newName>][,day=<newName>][,hour=<newName>][,text=<newName>]
23 * -dateToTime={column|parameter},<timeName>,<newName>,<stringName>,format=<formatString>
24 * -epoch={column|parameter},<newName>,year=<name>,[julianDay=<name>|month=<name>,day=<name>],hour=<name>
25 *
26 * @copyright
27 * - (c) 2002 The University of Chicago, as Operator of Argonne National Laboratory.
28 * - (c) 2002 The Regents of the University of California, as Operator of Los Alamos National Laboratory.
29 *
30 * @license
31 * This file is distributed under the terms of the Software License Agreement
32 * found in the file LICENSE included with this distribution.
33 *
34 * @author M. Borland, R. Soliday, H. Shang
35 */
36
37#include "mdb.h"
38#include "SDDS.h"
39#include "scan.h"
40#include <time.h>
41
42/* Enumeration for option types */
43enum option_type {
44 SET_EPOCH,
45 SET_PIPE,
46 SET_BREAKDOWN,
47 SET_MAJOR_ORDER,
48 SET_DATE,
49 N_OPTIONS
50};
51
52char *option[N_OPTIONS] = {
53 "epoch",
54 "pipe",
55 "breakdown",
56 "majorOrder",
57 "date",
58};
59
60/* Improved and more readable usage message */
61char *USAGE =
62 "Usage:\n"
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"
73 "Options:\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";
80
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
94
95typedef struct
96{
97 char *epochName, *yearName, *jDayName, *monthName, *dayName, *hourName;
98 char *textName, *format;
99 long epochIndex, yearIndex, jDayIndex, monthIndex, dayIndex, hourIndex;
100 long textIndex;
101 unsigned long flags;
103
104void DoColumnEpochConversion(SDDS_DATASET *SDDSout, SDDS_DATASET *SDDSin, TIME_CONVERSION *conversion);
105void DoParameterEpochConversion(SDDS_DATASET *SDDSout, SDDS_DATASET *SDDSin, TIME_CONVERSION *conversion);
106void DoColumnDateToTimeConversion(SDDS_DATASET *SDDSout, SDDS_DATASET *SDDSin, TIME_CONVERSION *conversion);
107void DoParameterDateToTimeConversion(SDDS_DATASET *SDDSout, SDDS_DATASET *SDDSin, TIME_CONVERSION *conversion);
108void DoColumnBreakdownConversion(SDDS_DATASET *SDDSout, SDDS_DATASET *SDDSin, TIME_CONVERSION *conversion);
109void DoParameterBreakdownConversion(SDDS_DATASET *SDDSout, SDDS_DATASET *SDDSin, TIME_CONVERSION *conversion);
110void InitializeOutput(SDDS_DATASET *SDDSout, char *outputfile, TIME_CONVERSION *conversion, long conversions,
111 SDDS_DATASET *SDDSin, short columnMajorOrder);
112void CheckEpochConversionElements(SDDS_DATASET *SDDSin, TIME_CONVERSION *conversion, long conversions);
113void CheckBreakdownConversionElements(SDDS_DATASET *SDDSin, TIME_CONVERSION *conversion, long conversions);
114void CheckDateConversionElements(SDDS_DATASET *SDDSin, TIME_CONVERSION *conversion, long conversions);
115
116int main(int argc, char **argv) {
117 SDDS_DATASET SDDSin, SDDSout;
118 long i_arg, iconv;
119 SCANNED_ARG *s_arg;
120 char *input, *output;
121 TIME_CONVERSION *conversion;
122 long conversions;
123 unsigned long pipeFlags, majorOrderFlag;
124 short columnMajorOrder = -1;
125
127 argc = scanargs(&s_arg, argc, argv);
128 if (argc < 3) {
129 fprintf(stderr, "%s", USAGE);
130 exit(EXIT_FAILURE);
131 }
132
133 input = output = NULL;
134 conversions = 0;
135 conversion = NULL;
136 pipeFlags = 0;
137
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:
142 majorOrderFlag = 0;
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;
153 break;
154 case SET_EPOCH:
155 if (s_arg[i_arg].n_items < 4)
156 SDDS_Bomb("Invalid -epoch syntax");
157 if (!(conversion = SDDS_Realloc(conversion, sizeof(*conversion) * (conversions + 1))))
158 SDDS_Bomb("Memory allocation failure");
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;
163 if (!scanItemList(&conversion[conversions].flags,
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))
172 SDDS_Bomb("invalid -epoch syntax");
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");
185 conversions++;
186 break;
187 case SET_BREAKDOWN:
188 if (s_arg[i_arg].n_items < 4)
189 SDDS_Bomb("Invalid -breakdown syntax");
190 if (!(conversion = SDDS_Realloc(conversion, sizeof(*conversion) * (conversions + 1))))
191 SDDS_Bomb("Memory allocation failure");
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;
196 if (!scanItemList(&conversion[conversions].flags,
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))
206 SDDS_Bomb("invalid -breakdown syntax");
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");
214 conversions++;
215 break;
216 case SET_DATE:
217 if (s_arg[i_arg].n_items < 4)
218 SDDS_Bomb("Invalid -dateToTime syntax");
219 if (!(conversion = SDDS_Realloc(conversion, sizeof(*conversion) * (conversions + 1))))
220 SDDS_Bomb("Memory allocation failure");
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;
226 if (!scanItemList(&conversion[conversions].flags,
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))
231 SDDS_Bomb("invalid -dateToTime syntax");
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");
239 conversions++;
240 break;
241 case SET_PIPE:
242 if (!processPipeOption(s_arg[i_arg].list + 1, s_arg[i_arg].n_items - 1, &pipeFlags))
243 SDDS_Bomb("Invalid -pipe syntax");
244 break;
245 default:
246 fprintf(stderr, "Error: Unknown option: %s\n", s_arg[i_arg].list[0]);
247 SDDS_Bomb(NULL);
248 break;
249 }
250 } else {
251 if (!input)
252 input = s_arg[i_arg].list[0];
253 else if (!output)
254 output = s_arg[i_arg].list[0];
255 else {
256 fprintf(stderr, "Error: Argument '%s' is invalid: too many filenames (sddstimeconvert)\n", s_arg[i_arg].list[0]);
257 exit(EXIT_FAILURE);
258 }
259 }
260 }
261
262 processFilenames("sddstimeconvert", &input, &output, pipeFlags, 0, NULL);
263
264 if (!SDDS_InitializeInput(&SDDSin, input)) {
265 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
266 exit(EXIT_FAILURE);
267 }
268
269 CheckEpochConversionElements(&SDDSin, conversion, conversions);
270 CheckBreakdownConversionElements(&SDDSin, conversion, conversions);
271 CheckDateConversionElements(&SDDSin, conversion, conversions);
272
273 InitializeOutput(&SDDSout, output, conversion, conversions, &SDDSin, columnMajorOrder);
274
275 while (SDDS_ReadPage(&SDDSin) > 0) {
276 if (!SDDS_CopyPage(&SDDSout, &SDDSin)) {
277 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
278 exit(EXIT_FAILURE);
279 }
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);
284 else
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);
289 else
290 DoColumnBreakdownConversion(&SDDSout, &SDDSin, conversion + iconv);
291 } else {
292 /* Convert date string to double time */
293 if (conversion[iconv].flags & IS_PARAMETER)
294 DoParameterDateToTimeConversion(&SDDSout, &SDDSin, conversion + iconv);
295 else
296 DoColumnDateToTimeConversion(&SDDSout, &SDDSin, conversion + iconv);
297 }
298 }
299 if (!SDDS_WritePage(&SDDSout)) {
300 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
301 exit(EXIT_FAILURE);
302 }
303 }
304 if (!SDDS_Terminate(&SDDSin) || !SDDS_Terminate(&SDDSout)) {
305 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
306 exit(EXIT_FAILURE);
307 }
308
309 return EXIT_SUCCESS;
310}
311
312void CheckEpochConversionElements(SDDS_DATASET *SDDSin, TIME_CONVERSION *conversion, long conversions) {
313 while (conversions-- > 0) {
314 if (!(conversion[conversions].flags & DO_EPOCH))
315 continue;
316 if (conversion->flags & IS_PARAMETER) {
317 if (SDDS_CheckParameter(SDDSin, conversion->yearName, NULL, SDDS_ANY_NUMERIC_TYPE, stderr) != SDDS_CHECK_OK ||
318 (conversion->jDayName &&
319 SDDS_CheckParameter(SDDSin, conversion->jDayName, NULL, SDDS_ANY_NUMERIC_TYPE, stderr) != SDDS_CHECK_OK) ||
320 (conversion->dayName &&
321 SDDS_CheckParameter(SDDSin, conversion->dayName, NULL, SDDS_ANY_NUMERIC_TYPE, stderr) != SDDS_CHECK_OK) ||
322 (conversion->monthName &&
323 SDDS_CheckParameter(SDDSin, conversion->monthName, NULL, SDDS_ANY_NUMERIC_TYPE, stderr) != SDDS_CHECK_OK) ||
324 SDDS_CheckParameter(SDDSin, conversion->hourName, NULL, SDDS_ANY_NUMERIC_TYPE, stderr) != SDDS_CHECK_OK)
325 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
326 conversion->yearIndex = SDDS_GetParameterIndex(SDDSin, conversion->yearName);
327 conversion->hourIndex = SDDS_GetParameterIndex(SDDSin, conversion->hourName);
328 conversion->dayIndex = conversion->jDayIndex = conversion->monthIndex = -1;
329 if (conversion->dayName)
330 conversion->dayIndex = SDDS_GetParameterIndex(SDDSin, conversion->dayName);
331 if (conversion->jDayName)
332 conversion->jDayIndex = SDDS_GetParameterIndex(SDDSin, conversion->jDayName);
333 if (conversion->monthName)
334 conversion->monthIndex = SDDS_GetParameterIndex(SDDSin, conversion->monthName);
335 } else {
336 if (SDDS_CheckColumn(SDDSin, conversion->yearName, NULL, SDDS_ANY_NUMERIC_TYPE, stderr) != SDDS_CHECK_OK ||
337 (conversion->jDayName &&
338 SDDS_CheckColumn(SDDSin, conversion->jDayName, NULL, SDDS_ANY_NUMERIC_TYPE, stderr) != SDDS_CHECK_OK) ||
339 (conversion->dayName &&
340 SDDS_CheckColumn(SDDSin, conversion->dayName, NULL, SDDS_ANY_NUMERIC_TYPE, stderr) != SDDS_CHECK_OK) ||
341 (conversion->monthName &&
342 SDDS_CheckColumn(SDDSin, conversion->monthName, NULL, SDDS_ANY_NUMERIC_TYPE, stderr) != SDDS_CHECK_OK) ||
343 SDDS_CheckColumn(SDDSin, conversion->hourName, NULL, SDDS_ANY_NUMERIC_TYPE, stderr) != SDDS_CHECK_OK)
344 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
345 conversion->yearIndex = SDDS_GetColumnIndex(SDDSin, conversion->yearName);
346 conversion->hourIndex = SDDS_GetColumnIndex(SDDSin, conversion->hourName);
347 conversion->dayIndex = conversion->jDayIndex = conversion->monthIndex = -1;
348 if (conversion->dayName)
349 conversion->dayIndex = SDDS_GetColumnIndex(SDDSin, conversion->dayName);
350 if (conversion->jDayName)
351 conversion->jDayIndex = SDDS_GetColumnIndex(SDDSin, conversion->jDayName);
352 if (conversion->monthName)
353 conversion->monthIndex = SDDS_GetColumnIndex(SDDSin, conversion->monthName);
354 }
355 conversion++;
356 }
357}
358
359void CheckBreakdownConversionElements(SDDS_DATASET *SDDSin, TIME_CONVERSION *conversion, long conversions) {
360 while (conversions-- > 0) {
361 if (!(conversion[conversions].flags & DO_BREAKDOWN))
362 continue;
363 if (conversion->flags & IS_PARAMETER) {
364 if (SDDS_CheckParameter(SDDSin, conversion->epochName, NULL, SDDS_ANY_NUMERIC_TYPE, stderr) != SDDS_CHECK_OK)
365 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
366 conversion->epochIndex = SDDS_GetParameterIndex(SDDSin, conversion->epochName);
367 } else {
368 if (SDDS_CheckColumn(SDDSin, conversion->epochName, NULL, SDDS_ANY_NUMERIC_TYPE, stderr) != SDDS_CHECK_OK)
369 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
370 conversion->epochIndex = SDDS_GetColumnIndex(SDDSin, conversion->epochName);
371 }
372 conversion++;
373 }
374}
375
376void CheckDateConversionElements(SDDS_DATASET *SDDSin, TIME_CONVERSION *conversion, long conversions) {
377 while (conversions-- > 0) {
378 if (!(conversion[conversions].flags & DO_DATECONVERSION))
379 continue;
380 if (conversion->flags & IS_PARAMETER) {
381 if (SDDS_CheckParameter(SDDSin, conversion->textName, NULL, SDDS_STRING, stderr) != SDDS_CHECK_OK)
382 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
383 conversion->textIndex = SDDS_GetParameterIndex(SDDSin, conversion->textName);
384 } else {
385 if (SDDS_CheckColumn(SDDSin, conversion->textName, NULL, SDDS_STRING, stderr) != SDDS_CHECK_OK)
386 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
387 conversion->textIndex = SDDS_GetColumnIndex(SDDSin, conversion->textName);
388 }
389 if (conversion->textIndex < 0) {
390 fprintf(stderr, "Error: '%s' does not exist in input file.\n", conversion->textName);
391 exit(EXIT_FAILURE);
392 }
393 conversion++;
394 }
395}
396
397void InitializeOutput(SDDS_DATASET *SDDSout, char *outputfile, TIME_CONVERSION *conversion, long conversions,
398 SDDS_DATASET *SDDSin, short columnMajorOrder) {
399 if (!SDDS_InitializeCopy(SDDSout, SDDSin, outputfile, "w"))
400 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
401 if (columnMajorOrder != -1)
402 SDDSout->layout.data_mode.column_major = columnMajorOrder;
403 else
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) {
408 if ((conversion->epochIndex = SDDS_DefineParameter(SDDSout, conversion->epochName,
409 NULL, "s", "Time since start of epoch", NULL, SDDS_DOUBLE, NULL)) < 0)
410 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
411 } else {
412 if ((conversion->epochIndex = SDDS_DefineColumn(SDDSout, conversion->epochName,
413 NULL, "s", "Time since start of epoch", NULL, SDDS_DOUBLE, 0)) < 0)
414 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
415 }
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,
420 SDDS_SHORT, NULL)) < 0) ||
421 (conversion->dayName &&
422 (conversion->dayIndex = SDDS_DefineParameter(SDDSout, conversion->dayName, NULL, NULL, "Day of month",
423 NULL, SDDS_SHORT, NULL)) < 0) ||
424 (conversion->monthName &&
425 (conversion->monthIndex = SDDS_DefineParameter(SDDSout, conversion->monthName, NULL, NULL, "Month", NULL,
426 SDDS_SHORT, NULL)) < 0) ||
427 (conversion->jDayName &&
428 (conversion->jDayIndex = SDDS_DefineParameter(SDDSout, conversion->jDayName, NULL, NULL, "Julian day",
429 NULL, SDDS_SHORT, NULL)) < 0) ||
430 (conversion->hourName &&
431 (conversion->hourIndex = SDDS_DefineParameter(SDDSout, conversion->hourName, NULL, NULL, "Hour of day",
432 NULL, SDDS_DOUBLE, NULL)) < 0) ||
433 (conversion->textName &&
434 (conversion->textIndex = SDDS_DefineParameter(SDDSout, conversion->textName, NULL, NULL, "Timestamp",
435 NULL, SDDS_STRING, NULL)) < 0))
436 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
437 } else {
438 if ((conversion->yearName &&
439 (conversion->yearIndex = SDDS_DefineColumn(SDDSout, conversion->yearName, NULL, NULL, "Year", NULL,
440 SDDS_SHORT, 0)) < 0) ||
441 (conversion->dayName &&
442 (conversion->dayIndex = SDDS_DefineColumn(SDDSout, conversion->dayName, NULL, NULL, "Day of month",
443 NULL, SDDS_SHORT, 0)) < 0) ||
444 (conversion->monthName &&
445 (conversion->monthIndex = SDDS_DefineColumn(SDDSout, conversion->monthName, NULL, NULL, "Month", NULL,
446 SDDS_SHORT, 0)) < 0) ||
447 (conversion->jDayName &&
448 (conversion->jDayIndex = SDDS_DefineColumn(SDDSout, conversion->jDayName, NULL, NULL, "Julian day",
449 NULL, SDDS_SHORT, 0)) < 0) ||
450 (conversion->hourName &&
451 (conversion->hourIndex = SDDS_DefineColumn(SDDSout, conversion->hourName, NULL, NULL, "Hour of day",
452 NULL, SDDS_DOUBLE, 0)) < 0) ||
453 (conversion->textName &&
454 (conversion->textIndex = SDDS_DefineColumn(SDDSout, conversion->textName, NULL, NULL, "Timestamp",
455 NULL, SDDS_STRING, 0)) < 0))
456 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
457 }
458 } else {
459 /* Date to time conversion */
460 if (conversion->flags & IS_PARAMETER) {
461 if ((conversion->epochIndex = SDDS_DefineParameter(SDDSout, conversion->epochName,
462 NULL, "s", "Time since start of epoch", NULL, SDDS_DOUBLE, NULL)) < 0)
463 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
464 } else {
465 if ((conversion->epochIndex = SDDS_DefineColumn(SDDSout, conversion->epochName,
466 NULL, "s", "Time since start of epoch", NULL, SDDS_DOUBLE, 0)) < 0)
467 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
468 }
469 }
470 conversion++;
471 }
472 if (!SDDS_WriteLayout(SDDSout))
473 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
474}
475
476void DoParameterEpochConversion(SDDS_DATASET *SDDSout, SDDS_DATASET *SDDSin, TIME_CONVERSION *conversion) {
477 double hour;
478 double month = 0, day = 0, jDay = 0, year, epochTime;
479
480 jDay = 0;
481 if (!SDDS_GetParameterAsDouble(SDDSin, conversion->hourName, &hour) ||
482 !SDDS_GetParameterAsDouble(SDDSin, conversion->yearName, &year) ||
483 (conversion->jDayName && !SDDS_GetParameterAsDouble(SDDSin, conversion->jDayName, &jDay)) ||
484 (conversion->monthName && !SDDS_GetParameterAsDouble(SDDSin, conversion->monthName, &month)) ||
485 (conversion->dayName && !SDDS_GetParameterAsDouble(SDDSin, conversion->dayName, &day))) {
486 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
487 exit(EXIT_FAILURE);
488 }
489 TimeBreakdownToEpoch((short)year, (short)jDay, (short)month, (short)day, hour, &epochTime);
490 if (!SDDS_SetParametersFromDoubles(SDDSout, SDDS_BY_NAME | SDDS_PASS_BY_VALUE, conversion->epochName, epochTime, NULL))
491 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
492}
493
494void DoParameterBreakdownConversion(SDDS_DATASET *SDDSout, SDDS_DATASET *SDDSin, TIME_CONVERSION *conversion) {
495 double hour, epochTime;
496 short year, jDay, month, day;
497 char text[30];
498
499 if (!SDDS_GetParameterAsDouble(SDDSin, conversion->epochName, &epochTime))
500 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
501 TimeEpochToBreakdown(&year, &jDay, &month, &day, &hour, epochTime);
502 TimeEpochToText(text, epochTime);
503 if ((conversion->yearName &&
504 !SDDS_SetParametersFromDoubles(SDDSout, SDDS_BY_INDEX | SDDS_PASS_BY_VALUE,
505 conversion->yearIndex, (double)year, -1)) ||
506 (conversion->dayName &&
507 !SDDS_SetParametersFromDoubles(SDDSout, SDDS_BY_INDEX | SDDS_PASS_BY_VALUE,
508 conversion->dayIndex, (double)day, -1)) ||
509 (conversion->jDayName &&
510 !SDDS_SetParametersFromDoubles(SDDSout, SDDS_BY_INDEX | SDDS_PASS_BY_VALUE,
511 conversion->jDayIndex, (double)jDay, -1)) ||
512 (conversion->monthName &&
513 !SDDS_SetParametersFromDoubles(SDDSout, SDDS_BY_INDEX | SDDS_PASS_BY_VALUE,
514 conversion->monthIndex, (double)month, -1)) ||
515 (conversion->hourName &&
516 !SDDS_SetParametersFromDoubles(SDDSout, SDDS_BY_INDEX | SDDS_PASS_BY_VALUE,
517 conversion->hourIndex, (double)hour, -1)) ||
518 (conversion->textName &&
519 !SDDS_SetParameters(SDDSout, SDDS_BY_INDEX | SDDS_PASS_BY_VALUE, conversion->textIndex, text, -1)))
520 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
521}
522
523void DoParameterDateToTimeConversion(SDDS_DATASET *SDDSout, SDDS_DATASET *SDDSin, TIME_CONVERSION *conversion) {
524#if defined(_WIN32)
525 fprintf(stderr, "Error: strptime function needed by DoParameterDateToTimeConversion is not available on Windows\n");
526 exit(EXIT_FAILURE);
527#else
528 double hour;
529 double month = 0, day = 0, jDay = 0, year, epochTime;
530 char *timestr = NULL;
531 struct tm tm = {0};
532 /* Note that tm struct:
533 tm_year: years since 1900
534 tm_mon: months since January (0-11)
535 */
536
537 if (!SDDS_GetParameter(SDDSin, conversion->textName, &timestr)) {
538 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
539 exit(EXIT_FAILURE);
540 }
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);
543 exit(EXIT_FAILURE);
544 }
545 year = tm.tm_year + 1900;
546 month = tm.tm_mon + 1;
547 day = tm.tm_mday;
548 hour = tm.tm_hour + tm.tm_min / 60.0 + tm.tm_sec / 3600.0;
549
550 TimeBreakdownToEpoch((short)year, (short)jDay, (short)month, (short)day, hour, &epochTime);
551 if (!SDDS_SetParametersFromDoubles(SDDSout, SDDS_BY_NAME | SDDS_PASS_BY_VALUE, conversion->epochName, epochTime, NULL))
552 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
553#endif
554}
555
556void DoColumnEpochConversion(SDDS_DATASET *SDDSout, SDDS_DATASET *SDDSin, TIME_CONVERSION *conversion) {
557 double *hour;
558 double *month, *day, *jDay, *year, *epochTime;
559 int64_t row, rows;
560
561 year = NULL;
562
563 if (!(rows = SDDS_CountRowsOfInterest(SDDSin)))
564 return;
565
566 jDay = month = day = NULL;
567 if (!(hour = SDDS_GetColumnInDoubles(SDDSin, conversion->hourName)) ||
568 !(year = SDDS_GetColumnInDoubles(SDDSin, conversion->yearName)) ||
569 (conversion->jDayName && !(jDay = SDDS_GetColumnInDoubles(SDDSin, conversion->jDayName))) ||
570 (conversion->monthName && !(month = SDDS_GetColumnInDoubles(SDDSin, conversion->monthName))) ||
571 (conversion->dayName && !(day = SDDS_GetColumnInDoubles(SDDSin, conversion->dayName))))
572 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
573
574 if (!(epochTime = (double *)malloc(sizeof(*epochTime) * rows)))
575 SDDS_Bomb("Memory allocation failure");
576
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);
579 if (!SDDS_SetColumnFromDoubles(SDDSout, SDDS_BY_NAME, epochTime, rows, conversion->epochName))
580 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
581 free(hour);
582 free(year);
583 free(epochTime);
584 if (jDay)
585 free(jDay);
586 if (month)
587 free(month);
588 if (day)
589 free(day);
590}
591
592void DoColumnDateToTimeConversion(SDDS_DATASET *SDDSout, SDDS_DATASET *SDDSin, TIME_CONVERSION *conversion) {
593#if defined(_WIN32)
594 fprintf(stderr, "Error: strptime function needed by DoColumnDateToTimeConversion is not available on Windows\n");
595 exit(EXIT_FAILURE);
596#else
597 double hour;
598 double month = 0, day = 0, year = 0, jDay = 0, *epochTime;
599 int64_t row, rows;
600 char **timestr = NULL;
601 struct tm tm = {0};
602 /* Note that tm struct:
603 tm_year: years since 1900
604 tm_mon: months since January (0-11)
605 */
606 if (!(rows = SDDS_CountRowsOfInterest(SDDSin)))
607 return;
608
609 if (!(timestr = SDDS_GetColumn(SDDSin, conversion->textName)))
610 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
611
612 if (!(epochTime = (double *)malloc(sizeof(*epochTime) * rows)))
613 SDDS_Bomb("Memory allocation failure");
614
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);
618 exit(EXIT_FAILURE);
619 }
620 year = tm.tm_year + 1900;
621 month = tm.tm_mon + 1;
622 day = tm.tm_mday;
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);
625 }
626 if (!SDDS_SetColumnFromDoubles(SDDSout, SDDS_BY_NAME, epochTime, rows, conversion->epochName))
627 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
628 SDDS_FreeStringArray(timestr, rows);
629 free(epochTime);
630#endif
631}
632
633void DoColumnBreakdownConversion(SDDS_DATASET *SDDSout, SDDS_DATASET *SDDSin, TIME_CONVERSION *conversion) {
634 double *hour, *epochTime;
635 short *month, *day, *jDay, *year;
636 char **text;
637 int64_t row, rows;
638
639 if (!(rows = SDDS_CountRowsOfInterest(SDDSin)))
640 return;
641
642 if (!(epochTime = SDDS_GetColumnInDoubles(SDDSin, conversion->epochName)))
643 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
644
645 hour = NULL;
646 month = day = jDay = year = NULL;
647 text = 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))))
654 SDDS_Bomb("Memory allocation failure");
655
656 for (row = 0; row < rows; row++) {
657 if (text)
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]) ||
660 (text && !TimeEpochToText(text[row], epochTime[row])))
661 SDDS_Bomb("Problem performing time breakdown");
662 }
663
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)))
670 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
671 if (hour)
672 free(hour);
673 if (year)
674 free(year);
675 if (epochTime)
676 free(epochTime);
677 if (jDay)
678 free(jDay);
679 if (month)
680 free(month);
681 if (day)
682 free(day);
683 if (text) {
684 for (row = 0; row < rows; row++)
685 free(text[row]);
686 free(text);
687 }
688}
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)
Definition SDDS_copy.c:40
int32_t SDDS_CopyPage(SDDS_DATASET *SDDS_target, SDDS_DATASET *SDDS_source)
Definition SDDS_copy.c:578
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.
void * SDDS_GetColumn(SDDS_DATASET *SDDS_dataset, char *column_name)
Retrieves a copy of the data for a specified column, including only rows marked as "of interest".
double * SDDS_GetParameterAsDouble(SDDS_DATASET *SDDS_dataset, char *parameter_name, double *memory)
Retrieves the value of a specified parameter as a double from the current data table of an SDDS datas...
int64_t SDDS_CountRowsOfInterest(SDDS_DATASET *SDDS_dataset)
Counts the number of rows marked as "of interest" in the current data table.
void * SDDS_GetParameter(SDDS_DATASET *SDDS_dataset, char *parameter_name, void *memory)
Retrieves the value of a specified parameter from the current data table of a data set.
double * SDDS_GetColumnInDoubles(SDDS_DATASET *SDDS_dataset, char *column_name)
Retrieves the data of a specified numerical column as an array of doubles, considering only rows mark...
int32_t SDDS_InitializeInput(SDDS_DATASET *SDDS_dataset, char *filename)
Definition SDDS_input.c:49
int32_t SDDS_Terminate(SDDS_DATASET *SDDS_dataset)
int32_t SDDS_ReadPage(SDDS_DATASET *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.
Definition SDDS_utils.c:432
void SDDS_RegisterProgramName(const char *name)
Registers the executable program name for use in error messages.
Definition SDDS_utils.c:288
void SDDS_Bomb(char *message)
Terminates the program after printing an error message and recorded errors.
Definition SDDS_utils.c:342
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.
Definition SDDS_utils.c:677
#define SDDS_STRING
Identifier for the string data type.
Definition SDDStypes.h:85
#define SDDS_SHORT
Identifier for the signed short integer data type.
Definition SDDStypes.h:73
#define SDDS_ANY_NUMERIC_TYPE
Special identifier used by SDDS_Check*() routines to accept any numeric type.
Definition SDDStypes.h:157
#define SDDS_DOUBLE
Identifier for the double data type.
Definition SDDStypes.h:37
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)
Definition scanargs.c:36
long processPipeOption(char **item, long items, unsigned long *flags)
Definition scanargs.c:356
void processFilenames(char *programName, char **input, char **output, unsigned long pipeFlags, long noWarnings, long *tmpOutputUsed)
Definition scanargs.c:390
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.