MISR Toolkit  1.5.1
cvtvalue.c
Go to the documentation of this file.
1 /*****************************************************************************
2 
3  Description: This file contains routines for converting ODL values from
4  ASCII text representation into values that can be attached
5  to an ODL tree.
6 
7  Author: Randy Davis, University of Colorado LASP
8  Carol S. W. Tsai / Applied Research Corporation
9  Peter D. Noerdlinger / SM&A Inc.
10  Abe Taaheri / SM&A Inc.
11 
12  Creation Date: 13 March 1991
13  Last Modified: 18 May 1991
14  Last Modified: 12 Jan, 1999
15  Last Modified: 21 Sep, 1999
16 
17  History:
18 
19  Creation - Beginning with Version 2.1 of the ODLC library, the routines
20  in this file supplant the routines previously found in the LEXACT.C
21  module. Previously these routines were only for processing tokens from
22  the lexical analyzer. They have now been generalized and can be called
23  directly by a user's program to convert text representations of values
24  into data values for an ODL tree. The mapping between new and old
25  routines is as follows:
26  - ODLConvertInteger combines the previous routines ODLIntegerDToken
27  and ODLIntegerBToken
28  - ODLConvertSymbol combines ODLSymbolToken and ODLNameToken
29  - ODLConvertReal is from ODLRealToken
30  - ODLConvertString implements part of ODLStringToken (the rest of that
31  earlier routine became routine yyGetStringToken in the lexical
32  analyzer)
33  - ODLConvertDate, ODLConvertTime and ODLConvertDateTime are from
34  ODLDateToken, ODLTimeToken and ODLDateTimeToken, respectively.
35 
36  Version 2.2 - 18 May 1991 - M. DeMore, Jet Propulsion Laboratory
37  Removed include statements that were Unix specific and placed them
38  in odldef.h. Removed prototypes of ODL functions.
39 
40  Modified code in order the data in UTC DATETIME format can be retrieved by
41  user using the function PGS_MET_SetAttr() from the memory when metadata file
42  was initialized or function PGS_MET_GetPCAttr() from the HDF Metadata file or
43  non-HDF Metadata file.(CSWT)
44  Added code to set valid flag defined to check whether year is outside
45  expected range or not to be 0 if it is in false case(CSWT)
46  Modified code in order the data in UTC DATETIME format with Zulu indicator or not
47  can be written in a correct format to be retrieved (CSWT) (This changing is for
48  ECSed15136 about the date_time values are too long)
49 
50  PDN Modified code so as to refuse 2 digit (or less) years for Y2K compliance.
51 
52  AT Modified code so as to set errno correctly in ODLConvertInteger and
53  ODLConvertReal.
54 *****************************************************************************/
55 #include <limits.h>
56 #include <ctype.h>
57 #include <errno.h>
58 #include <math.h>
59 #include <sys/types.h>
60 #include <stdlib.h>
61 
62 #include "odldef.h"
63 #include "odlinter.h"
64 
65 
66 
67 
68 /*****************************************************************************
69 
70  Routine: ODLConvertInteger
71 
72  Description: Convert ASCII representation of an integer value into an
73  ODLC integer data value. The input integer value can be
74  represented in either decimal or based notation.
75 
76  Input:
77  vtext - Pointer to string containing the value as ASCII text.
78  vlength - Number of characters in value string.
79 
80  Output: A value data structure containing the converted value is returned
81  as the function value.
82 
83 *****************************************************************************/
84 
85 
86 VALUE_DATA ODLConvertInteger (char vtext[], int vlength)
87 {
88  VALUE_DATA item; /* Structure to hold integer value */
89  char warning[120]; /* Warning message text */
90  int base; /* Number base */
91  char *sp; /* Pointer to substring within input */
92 
93 
94  /* Set the value type and length. The format indicator is set to show
95  whether the input value was in decimal notation (format = 0) or based
96  notation (format = base). The precision indicator has no meaning
97  for integer numbers */
98 
99  item.type = TV_INTEGER;
100  item.length = vlength;
101  item.valid = 1;
102  item.precision = 0;
103 
104  /* reset errno */
105 
106  errno = 0;
107 
108  /* Initialize the units to NONE */
109 
110  item.value.integer.units = NULL;
111 
112  /* See if there is a pound sign, denoting a based number */
113 
114  sp = strchr (vtext,'#');
115  if (sp == NULL)
116  {
117  /* No pound sign found, so this value is in decimal integer format */
118  /* Used strtol instead of atol to get errno = ERANGE and value
119  equal LONG_MAX or LONG_MIN in case of overflow or underflow */
120 
121  base =10;
122  item.format = 0;
123  item.value.integer.number = strtol (vtext, NULL, base);
124  }
125  else
126  {
127  /* The number is in based format. Get the number base and make sure
128  it is in the range 2 .. 16 */
129 
130  base = atoi (vtext);
131  if (base < 2 || base > 16)
132  {
133  ODLPrintError ("The number base must be in range 2..16");
134  item.value.integer.number = 0;
135  item.valid = 0;
136  }
137  else
138  {
139  /* See if the next character is a number sign */
140 
141  if (*++sp == '-')
142  {
143  /* There is a negative number sign: set the format word to
144  a negative value to indicate that the number is negative */
145 
146  item.format = -base;
147  }
148  else
149  {
150  /* There is a positive number sign or no number sign: set
151  the format word to a positive value to indicate this */
152 
153  item.format = base;
154  }
155 
156  /* Convert the number according to the specified number base */
157 
158  item.value.integer.number = strtol (sp, &sp, base);
159 
160  /* Check to make sure that there weren't any illegal digits */
161 
162  if (*sp != '#')
163  {
164  ODLPrintError ("Based integer contains illegal digit(s)");
165  item.value.integer.number = 0;
166  item.valid = 0;
167  }
168  }
169  }
170 
171  /* See if the value was too large to be represented. Note: this check
172  does not work for all implementations of C */
173 
174  if (((item.value.integer.number == LONG_MAX) ||
175  (item.value.integer.number == LONG_MIN)) && (errno == ERANGE))
176  {
177  sprintf (warning,
178  "Magnitude of integer number is too large.\n %s %s value.",
179  "The number has been set to the maximum",
180  (item.value.integer.number < 0 ? "negative" : "positive"));
181  ODLPrintWarning (warning);
182  errno = 0;
183  }
184 
185  return (item);
186 }
187 
188 
189 
190 
191 /*****************************************************************************
192 
193  Routine: ODLConvertReal
194 
195  Description: Convert ASCII representation of a real value into an ODLC
196  real data value.
197 
198  Input:
199  vtext - Pointer to string containing the value as ASCII text.
200  vlength - Number of characters in value string.
201 
202  Output: A value data structure containing the converted value is
203  returned as the function value.
204 
205 *****************************************************************************/
206 
207 
208 VALUE_DATA ODLConvertReal (char vtext[], int vlength)
209 {
210  VALUE_DATA item; /* Structure to hold real value */
211  char warning[120]; /* Warning message text */
212  char *sp; /* Pointer to substring within input */
213 
214 
215  /* Set the value type and length and initialize the validity indicator */
216 
217  item.type = TV_REAL;
218  item.length = vlength;
219  item.valid = 1;
220 
221  /* reset errno */
222 
223  errno = 0;
224 
225  /* Determine whether or not the number has an exponent. We record
226  this in the format field so the number can be output the same
227  way later */
228 
229  sp = strpbrk (vtext, "Ee");
230  if (sp == NULL)
231  {
232  /* Set the format code to indicate the value does not include an
233  exponent */
234 
235  item.format = 1;
236  }
237  else
238  {
239  /* Set the format code to indicate the value includes an exponent */
240 
241  item.format = 2;
242  }
243 
244  /* Determine the number of decimal places by counting the digits between
245  the decimal point and the exponent or end of number, whichever occurs
246  first */
247 
248  sp = strchr (vtext, '.');
249  item.precision = strcspn (++sp, "Ee");
250 
251  /* Convert the input string and store the value. Initialize the
252  units to NONE */
253 
254  item.value.real.number = atof (vtext);
255  item.value.real.units = NULL;
256 
257  /* Determine whether overflow occurred. Note: this check does not work
258  for all implementations of C */
259 
260  if (errno == ERANGE)
261  {
262  sprintf (warning,
263  "Magnitude of real number is too large\n %s %s value.",
264  "The number has been set to the maximum",
265  (item.value.real.number < 0.0 ? "negative" : "positive"));
266  ODLPrintWarning (warning);
267  errno = 0;
268  }
269 
270  return (item);
271 }
272 
273 
274 
275 
276 /*****************************************************************************
277 
278  Routine: ODLConvertSymbol
279 
280  Description: Convert a symbol value string into an ODLC data value.
281 
282  Input:
283  vtext - Pointer to string containing the value as ASCII text.
284  vlength - Number of characters in value string.
285  vflag - Flag indicating whether value is a name:
286  1 - Symbol is a valid name and can be represented
287  without surrounding apostrophes;
288  2 - Symbol must be delimited by apostrophes.
289  Any other value for vflag will result in the symbol
290  being delimited by apostrophes.
291 
292  Output: A value data structure containing the converted value is
293  returned as the function value.
294 
295 *****************************************************************************/
296 
297 
298 VALUE_DATA ODLConvertSymbol (char vtext[], int vlength, int vflag)
299 {
300  VALUE_DATA item; /* Structure to hold symbol value */
301  char *ntext; /* Pointer to storage for symbol value */
302  char c; /* Current character */
303  int i; /* Index into text strings */
304 
305 
306  /* Set the type and length of the data value and the format value to
307  indicate whether or not the symbol must be printed within
308  apostrophes. The precision field is not used for symbols */
309 
310  item.type = TV_SYMBOL;
311  item.length = vlength;
312  item.format = (vflag == 1)? 1 : 0;
313  item.precision = 0;
314 
315  /* Allocate memory to hold the name */
316 
317  ntext = (char *) malloc (vlength+1);
318  if (ntext == NULL)
319  {
320  /* Couldn't allocate memory to hold the symbol */
321 
322  ODLPrintWarning ("Storage allocation failed -- couldn't store symbol");
323  item.valid = 0;
324  }
325  else
326  {
327  /* Copy the symbol, converting alphabetic characters to upper case */
328 
329  for (i = 0; i < vlength; i++)
330  {
331  c = vtext[i];
332  ntext[i] = (islower (c))? toupper (c) : c;
333  }
334 
335  ntext[vlength] = '\0';
336  item.valid = 1;
337  }
338 
339  item.value.string = ntext;
340 
341  return (item);
342 }
343 
344 
345 
346 
347 /*****************************************************************************
348 
349  Routine: ODLConvertString
350 
351  Description: Convert a text string value into an ODLC data value.
352 
353  Input:
354  vtext - Pointer to string containing the value as ASCII text.
355  This does not include the opening quotation mark.
356  vlength - Number of characters in value string, not including
357  the ending quotation mark.
358 
359  Output: A value data structure containing the converted value is
360  returned as the function value.
361 
362 *****************************************************************************/
363 
364 
365 VALUE_DATA ODLConvertString (char vtext[], int vlength)
366 {
367  VALUE_DATA item; /* Structure to hold string value */
368  char *ntext; /* Pointer to storage for string value */
369 
370 
371  /* Fill in the value data structure. The format and precision indicators
372  aren't used for text strings */
373 
374  item.type = TV_STRING;
375  item.length = vlength;
376  item.format = 0;
377  item.precision = 0;
378 
379  /* Allocate memory to hold the output string value */
380 
381  ntext = (char *) malloc (vlength+1);
382  if (ntext != NULL)
383  {
384  /* Copy the string */
385 
386  strncpy (ntext, vtext, vlength);
387  ntext[vlength] = '\0';
388  item.valid = 1;
389  }
390  else
391  {
392  /* Memory couldn't be allocated to store the string */
393 
394  ODLPrintWarning ("Storage allocation failed -- couldn't store string");
395  item.valid = 0;
396  }
397 
398  item.value.string = ntext;
399 
400  return (item);
401 }
402 
403 
404 
405 
406 /*****************************************************************************
407 
408  Routine: ODLConvertDate
409 
410  Description: Convert a date value in ASCII into an ODLC data value.
411 
412  Input:
413  vtext - Pointer to string containing the value as ASCII text.
414  vlength - Number of characters in value string.
415 
416  Output: A value data structure containing the converted value is
417  returned as the function value.
418 
419 *****************************************************************************/
420 
421 
422 VALUE_DATA ODLConvertDate (char vtext[], int vlength)
423 {
424  VALUE_DATA item; /* Structure to hold string value */
425 
426  /* Set the value type and length */
427 
428  item.type = TV_DATE;
429  item.length = vlength;
430 
431  /* Initialize the format, validity and precision indicators. They may be
432  reset by the extraction routine */
433 
434  item.valid = 1;
435  item.format = 0;
436  item.precision = 0;
437 
438  /* Since this is a date only, initialize the time components of the
439  value data structure to zero */
440 
441  item.value.date_time.hours = 0;
442  item.value.date_time.minutes = 0;
443  item.value.date_time.seconds = 0;
444  item.value.date_time.nanoseconds = 0;
445 
446  item.value.date_time.zone_hours = 0;
447  item.value.date_time.zone_minutes = 0;
448 
449  /* Extract the date from the value string. If there is an error, a
450  message will be printed out by the extraction routine */
451 
452  ODLExtractDate (vtext, &item);
453 
454  return (item);
455 }
456 
457 
458 
459 
460 /*****************************************************************************
461 
462  Routine: ODLConvertTime
463 
464  Description: Convert a time value in ASCII into an ODLC data value.
465 
466  Input:
467  vtext - Pointer to string containing the value as ASCII text.
468  vlength - Number of characters in value string.
469 
470  Output: A value data structure containing the converted value is
471  returned as the function value.
472 
473 *****************************************************************************/
474 
475 
476 VALUE_DATA ODLConvertTime (char vtext[], int vlength)
477 {
478  VALUE_DATA item; /* Structure to hold string value */
479 
480  /* Set the value type and length */
481 
482  item.type = TV_TIME;
483  item.length = vlength;
484 
485  /* Initialize the format, validity and precision indicators. They may be
486  reset by the extraction routine */
487 
488  item.valid = 1;
489  item.format = 0;
490  item.precision = 0;
491 
492  /* Since this is a time only, initialize the date components of the
493  value data structure to zero */
494 
495  item.value.date_time.year = 0;
496  item.value.date_time.doy = 0;
497  item.value.date_time.month = 0;
498  item.value.date_time.day = 0;
499 
500  /* Extract the time from the value string. If there is an error, a
501  message will be printed out by the extraction routine */
502 
503  ODLExtractTime (vtext, &item);
504 
505  return (item);
506 }
507 
508 
509 
510 
511 /*****************************************************************************
512 
513  Routine: ODLConvertDateTime
514 
515  Description: Convert a date/time value text string into an ODLC data value.
516 
517  Input:
518  vtext - Pointer to string containing the value as ASCII text.
519  vlength - Number of characters in value string.
520 
521  Output: A value data structure containing the converted value is
522  returned as the function value.
523 
524 *****************************************************************************/
525 
526 
527 VALUE_DATA ODLConvertDateTime (char vtext[], int vlength)
528 {
529  VALUE_DATA item; /* Structure to hold date/time value */
530  char *sp; /* Pointer to time part of input string */
531 
532  /* Set the value type and length */
533 
534  item.type = TV_DATE_TIME;
535  item.length = vlength;
536 
537  /* Initialize the format, validity and precision indicators. They may be
538  reset by the extraction routines */
539 
540  item.valid = 1;
541  item.format = 0;
542  item.precision = 0;
543 
544  /* Locate the separator between the date part and the time part, and
545  replace it with a null character to terminate the date string. First
546  we assume that the date/time is in the newer ODL format where the
547  separator between date and time is the letter 'T' */
548 
549  sp = strchr (vtext, 'T');
550  if (sp == NULL)
551  {
552  /* The date/time must be in the old ODL Version 0 format, where the
553  date is separated from the time part by a dash character */
554 
555  sp = strchr (vtext, '-');
556  }
557 
558  *sp++ = '\0';
559 
560  /* Extract the date from the value string. If there is an error, a
561  message will be printed out by the extraction routine */
562 
563  ODLExtractDate (vtext, &item);
564 
565  /* Now extract the time from the value string. If there is an error,
566  a message will be printed out by the extraction routine */
567 
568  ODLExtractTime (sp, &item);
569 
570  return (item);
571 }
572 
573 
574 
575 /*****************************************************************************
576 
577  Routine: ODLExtractDate
578 
579  Description: Extracts the date from a date/time string.
580 
581 
582  Input: text - Character string containing date in ASCII text format.
583  item - Pointer to structure to contain date/time value.
584 
585  Output: The date fields are set in the date/time value data structure
586  along with the validity and format indicators.
587 
588 *****************************************************************************/
589 
590 
591 void ODLExtractDate (char *text, VALUE_DATA *item)
592 {
593 /* >>>>>>>>>>>>>>>>>>>>>>>>>> BEGIN CN CHANGES >>>>>>>>>>>>>>>>>>>>>>>>> */
594 /* >>>>> MDD 5/26/91 Removed declarations of unused variables >>>>> */
595 /* >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> */
596 
597  char error_msg[80]; /* Error message text */
598  long day; /* Day of month */
599  long doy; /* Day of year */
600  long month; /* Month number */
601  long year; /* Year number */
602  int leap_year; /* Set to one if leap year; otherwise zero */
603  int nparts; /* Number of parts to the date (2 or 3) */
604 
605 /* >>>>>>>>>>>>>>>>>>>>>>>>>> END OF CN CHANGES >>>>>>>>>>>>>>>>>>>>>>>>> */
606 
607  static short day_table[2][13] = /* Number of days in each month */
608  {{0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
609  {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}};
610 
611  static short doy_table[13] = /* Day of year for end of each month */
612  {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365};
613 
614 
615  /* Extract the components of the date from the input string */
616 
617  nparts = sscanf (text, "%ld%*[-/]%ld%*[-/]%ld", &year, &month, &day);
618 
619  /* Check the year number for reasonableness */
620 
621  if (year < 100)
622  {
623  ODLPrintWarning ("Year value is < 100 and not valid.");
624  item->valid = 0;
625  }
626  else if (year < 1700 || year > 2200)
627  {
628  ODLPrintWarning ("Year is outside expected range - please check");
629  item->valid = 0;
630  }
631 
632  /* Determine whether or not the specified year is a leap year */
633 
634  leap_year = year%4 == 0 && year%100 != 0 || year%400 == 0;
635 
636  /* If we only got two input fields, they are the year and day of year; if
637  we got three fields then we have year, month and day of month */
638 
639  if (nparts == 2)
640  {
641  /* The date was specified as year-doy: Check the doy value and
642  if it is OK, convert it to month and day of month */
643 
644  doy = month;
645  if (doy < 1 || (!leap_year && doy > 365) || (leap_year && doy > 366))
646  {
648  ("Day-of-year must be in range 1..365 (or 366 in a leap year)");
649  item->valid = 0;
650  }
651  else
652  {
653  day = doy;
654  for (month=1 ; day > day_table[leap_year][month] ; month++)
655  {
656  day -= day_table[leap_year][month];
657  }
658  }
659  }
660  else
661  {
662  /* The date was specified as year, month and day. Check the
663  month and day values for validity */
664 
665  if (month >= 1 && month <= 12)
666  {
667  /* The month is valid. Make sure the day is valid for the
668  specified month */
669 
670  if (day >= 1 && day <= day_table[leap_year][month])
671  {
672  /* The day is valid. Calculate the corresponding day
673  of year */
674 
675  doy = doy_table[month-1] + day;
676  if (leap_year && month > 2)
677  {
678  doy++;
679  }
680  }
681  else
682  {
683  /* The day value is not valid */
684 
685  sprintf (error_msg,
686  "Day number should be in range 1..%d",
687  day_table[leap_year][month]);
688  ODLPrintError (error_msg);
689  item->valid = 0;
690  }
691  }
692  else
693  {
694  /* The month value is not valid */
695 
696  ODLPrintError ("Month number must be in range 1..12");
697  item->valid = 0;
698  }
699  }
700 
701  item->format += nparts*10;
702  if (item->valid)
703  {
704  /* Store the completed date */
705 
706  if (nparts == 2)
707  {
708  item->value.date_time.year = (short) year;
709  item->value.date_time.doy = (short) doy;
710  item->value.date_time.month = NULL;
711  item->value.date_time.day = NULL;
712  }
713  else
714  {
715  item->value.date_time.year = (short) year;
716  item->value.date_time.doy = (short) doy;
717  item->value.date_time.month = (char) month;
718  item->value.date_time.day = (char) day;
719  }
720  }
721  else
722  {
723  /* Since the date is in error, set all of the fields to zero */
724 
725  item->value.date_time.year = 0;
726  item->value.date_time.doy = 0;
727  item->value.date_time.month = 0;
728  item->value.date_time.day = 0;
729  }
730 
731  return;
732 }
733 
734 
735 
736 
737 /*****************************************************************************
738 
739  Routine: ODLExtractTime
740 
741  Description: Extracts the time from a date/time text string.
742 
743 
744  Input: text - String containing the time value as ASCII text.
745  item - Pointer to structure that is to contain date/time value.
746 
747  Output: The time fields are placed into the date/time value data
748  structure and the validity, format and precision fields are
749  updated as appropriate.
750 
751 *****************************************************************************/
752 
753 
754 void ODLExtractTime (char *text, VALUE_DATA *item)
755 {
756 /* >>>>>>>>>>>>>>>>>>>>>>>>>> BEGIN CN CHANGES >>>>>>>>>>>>>>>>>>>>>>>>> */
757 /* >>>>> MDD 5/26/91 Removed declarations of unused variables >>>>> */
758 /* >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> */
759 
760  int nparts; /* Number of fields in time or time zone */
761  long hours; /* Hours, from input */
762  long minutes; /* Minutes, from input */
763  double seconds; /* Seconds, from input */
764  char *sp; /* Pointer to substrings in input string */
765  char *ZUTCchar = NULL;
766 
767 /* >>>>>>>>>>>>>>>>>>>>>>>>>> END OF CN CHANGES >>>>>>>>>>>>>>>>>>>>>>>>> */
768 
769  /* Extract the components of the time from the input string. We read
770  them into temporary long integer variables so that we can reduce
771  the potential for overflow problems if the user enters bad values. */
772 
773  nparts = sscanf (text, "%ld:%ld:%lf", &hours, &minutes, &seconds);
774 
775  /* Check the hours field to make sure it is valid */
776 
777  if (hours >= 24)
778  {
779  ODLPrintError ("Hours must be in range 0..23");
780  item->valid = 0;
781  }
782 
783  /* Check the minutes field */
784 
785  if (minutes > 60)
786  {
787  ODLPrintError ("Minutes must be in range 0..59");
788  item->valid = 0;
789  }
790 
791  if (nparts == 2)
792  {
793  /* No seconds parts present in the input time string. Set the
794  format code to indicate this and set the seconds field to zero */
795 
796  item->format += 2;
797  seconds = 0.0;
798  }
799  else
800  {
801 
802  /* Set the format to indicate that the time field has three parts */
803 
804  item->format += 3;
805 
806  /* Check the seconds value to make sure it is valid */
807 
808  if (seconds >= 60.0)
809  {
810  ODLPrintError ("Seconds must be less than 60");
811  item->valid = 0;
812  }
813  else
814  {
815  /* Determine the number of decimal places specified in the seconds
816  field. This will be the number of characters between a decimal
817  point, if any, and either the time zone indicator or the end of
818  string, whichever occurs first */
819 
820  sp = strchr (text, '.');
821  if (sp == NULL)
822  {
823  sp = strrchr (text, 'Z');
824  if(sp != NULL)
825  {
826  item->precision = -99;
827  }
828  }
829  else
830  {
831  item->precision = strcspn (++sp, "Z+-");
832  ZUTCchar = strrchr(sp,'Z');
833  if(ZUTCchar != NULL)
834  {
835  item->precision = -99;
836  }
837  }
838  ++sp;
839  }
840  }
841 
842  if (item->valid)
843  {
844  /* Store the completed time value */
845 
846  if(nparts == 2)
847  {
848  item->value.date_time.hours = (char) hours;
849  item->value.date_time.minutes = (char) minutes;
850  item->value.date_time.seconds = NULL;
851  item->value.date_time.nanoseconds = NULL;
852  }
853  else
854  {
855  item->value.date_time.hours = (char) hours;
856  item->value.date_time.minutes = (char) minutes;
857  item->value.date_time.seconds = (char) seconds;
858  item->value.date_time.nanoseconds =
859  (long) (modf(seconds, &seconds)*1.0E9);
860  }
861  }
862  else
863  {
864  /* The time is invalid, so set all the fields to zero */
865 
866  item->value.date_time.hours = 0;
867  item->value.date_time.minutes = 0;
868  item->value.date_time.seconds = 0;
869  item->value.date_time.nanoseconds = 0;
870  }
871 
872  /* Find the time zone indication in the input text string */
873 
874  sp = strpbrk (text, "+-");
875  if (sp == NULL)
876  {
877  /* Either a time zone was not specified or the letter Z was specified
878  to indicate UTC. Either way, set the time zone offsets to zero */
879 
880  hours = 0;
881  minutes = 0;
882  }
883  else
884  {
885  /* A delta from Greenwich was specified. Get the zone offset in
886  hours and (optionally) minutes from UTC */
887 
888  nparts = sscanf (sp, "%ld:%ld", &hours, &minutes);
889 
890  if (hours < -12 || hours > 12)
891  {
892  ODLPrintError ("Time zone hours value must be in range -12..+12");
893  item->valid = 0;
894  }
895 
896  if (nparts == 1)
897  {
898  /* There were no minutes specified in the time zone offset */
899 
900  minutes = 0;
901  }
902  else
903  {
904  /* The minutes part of the zone offset was specified: check it */
905 
906  if (minutes >= 60)
907  {
909  ("Time zone minutes value must be in range 0..59");
910  item->valid = 0;
911  }
912  }
913 
914  }
915 
916  if (item->valid)
917  {
918  /* Store the time zone information */
919 
920  item->value.date_time.zone_hours = (short) hours;
921  item->value.date_time.zone_minutes = (char) minutes;
922  }
923  else
924  {
925  item->value.date_time.zone_hours = 0;
926  item->value.date_time.zone_minutes = 0;
927  }
928 
929  return;
930 }
void ODLExtractTime(char *text, VALUE_DATA *item)
Definition: cvtvalue.c:754
VALUE_DATA ODLConvertSymbol(char vtext[], int vlength, int vflag)
Definition: cvtvalue.c:298
char hours
Definition: odldef.h:204
VALUE_DATA ODLConvertDate(char vtext[], int vlength)
Definition: cvtvalue.c:422
char day
Definition: odldef.h:201
char format
Definition: odldef.h:215
VALUE_DATA ODLConvertTime(char vtext[], int vlength)
Definition: cvtvalue.c:476
char month
Definition: odldef.h:200
Definition: odldef.h:97
void ODLExtractDate(char *text, VALUE_DATA *item)
Definition: cvtvalue.c:591
short year
Definition: odldef.h:198
Definition: odldef.h:97
struct ODLInteger integer
Definition: odldef.h:219
struct ODLDate date_time
Definition: odldef.h:221
char seconds
Definition: odldef.h:206
short length
Definition: odldef.h:217
double number
Definition: odldef.h:184
char minutes
Definition: odldef.h:205
VALUE_DATA ODLConvertReal(char vtext[], int vlength)
Definition: cvtvalue.c:208
short doy
Definition: odldef.h:199
Definition: odldef.h:96
char valid
Definition: odldef.h:214
struct ODLReal real
Definition: odldef.h:220
VALUE_DATA ODLConvertInteger(char vtext[], int vlength)
Definition: cvtvalue.c:86
short precision
Definition: odldef.h:216
char * string
Definition: odldef.h:222
VALUE_TYPE type
Definition: odldef.h:213
struct ODLUnits * units
Definition: odldef.h:185
struct ODLUnits * units
Definition: odldef.h:192
H5TOOLS_DLL void error_msg(const char *fmt,...)
VALUE_DATA ODLConvertDateTime(char vtext[], int vlength)
Definition: cvtvalue.c:527
char zone_minutes
Definition: odldef.h:203
long nanoseconds
Definition: odldef.h:207
void ODLPrintWarning()
VALUE_DATA ODLConvertString(char vtext[], int vlength)
Definition: cvtvalue.c:365
union Value_Data::@2 value
short zone_hours
Definition: odldef.h:202
void ODLPrintError()
long number
Definition: odldef.h:191

MISR Toolkit - Copyright © 2005 - 2020 Jet Propulsion Laboratory
Generated on Fri Jun 19 2020 22:49:51