taxis.c 27.7 KB
Newer Older
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1
2
3
4
5
6
7
8
9
10
#if defined (HAVE_CONFIG_H)
#  include "config.h"
#endif

#include <string.h>

#include "dmemory.h"

#include "cdi.h"
#include "stream_int.h"
11
#include "calendar.h"
Uwe Schulzweida's avatar
Uwe Schulzweida committed
12

Uwe Schulzweida's avatar
Uwe Schulzweida committed
13
14
extern int cdiDefaultCalendar;

15
16
static int DefaultTimeType = TAXIS_ABSOLUTE;
static int DefaultTimeUnit = TUNIT_HOUR;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
17
18
19
20
21
22
23
24
25
26


char *Timeunits[] = {
  "undefined",
  "seconds",
  "minutes",
  "hours",
  "days",
  "months",
  "years",
27
  "quarter",
Uwe Schulzweida's avatar
Uwe Schulzweida committed
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
};


char *tunitNamePtr(int unitID)
{
  char *name;
  int size = sizeof(Timeunits)/sizeof(char *);

  if ( unitID > 0 && unitID < size )
    name = Timeunits[unitID];
  else
    name = Timeunits[0];

  return (name);
}


Uwe Schulzweida's avatar
Uwe Schulzweida committed
45
void taxis_defaults(void)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
46
{
Uwe Schulzweida's avatar
Uwe Schulzweida committed
47
  static char func[] = "taxis_defaults";
Uwe Schulzweida's avatar
Uwe Schulzweida committed
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
  char *timeunit;

  timeunit = getenv("TIMEUNIT");
  if ( timeunit )
    {
      if ( strcmp(timeunit, "minute") == 0 )
	DefaultTimeUnit = TUNIT_MINUTE;
      else if ( strcmp(timeunit, "hour") == 0 )
	DefaultTimeUnit = TUNIT_HOUR;
      else if ( strcmp(timeunit, "day") == 0 )
	DefaultTimeUnit = TUNIT_DAY;
      else if ( strcmp(timeunit, "month") == 0 )
	DefaultTimeUnit = TUNIT_MONTH;
      else if ( strcmp(timeunit, "year") == 0 )
	DefaultTimeUnit = TUNIT_YEAR;
      else
	Warning(func, "Unsupported TIMEUNIT %s!", timeunit);
    }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
}


static int  TAXIS_Debug = 0;   /* If set to 1, debugging */

static int _taxis_max = MAX_TAXIS;

static void taxis_initialize(void);

static int _taxis_init = FALSE;

#if  defined  (HAVE_LIBPTHREAD)
#  include <pthread.h>

static pthread_once_t _taxis_init_thread = PTHREAD_ONCE_INIT;
static pthread_mutex_t _taxis_mutex;

#  define TAXIS_LOCK           pthread_mutex_lock(&_taxis_mutex);
#  define TAXIS_UNLOCK         pthread_mutex_unlock(&_taxis_mutex);
#  define TAXIS_INIT                               \
   if ( _taxis_init == FALSE ) pthread_once(&_taxis_init_thread, taxis_initialize);

#else

#  define TAXIS_LOCK
#  define TAXIS_UNLOCK
#  define TAXIS_INIT                               \
   if ( _taxis_init == FALSE ) taxis_initialize();

#endif

Uwe Schulzweida's avatar
Uwe Schulzweida committed
97

Uwe Schulzweida's avatar
Uwe Schulzweida committed
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
typedef struct _taxisPtrToIdx {
  int idx;
  TAXIS *ptr;
  struct _taxisPtrToIdx *next;
} taxisPtrToIdx;


static taxisPtrToIdx *_taxisList  = NULL;
static taxisPtrToIdx *_taxisAvail = NULL;


static void taxis_list_new(void)
{
  static char func[] = "taxis_list_new";

  assert(_taxisList == NULL);

  _taxisList = (taxisPtrToIdx *) malloc(_taxis_max*sizeof(taxisPtrToIdx));
Uwe Schulzweida's avatar
Uwe Schulzweida committed
116
117
118
}


Uwe Schulzweida's avatar
Uwe Schulzweida committed
119
static void taxis_list_delete(void)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
120
{
Uwe Schulzweida's avatar
Uwe Schulzweida committed
121
  static char func[] = "taxis_list_delete";
Uwe Schulzweida's avatar
Uwe Schulzweida committed
122

Uwe Schulzweida's avatar
Uwe Schulzweida committed
123
  if ( _taxisList ) free(_taxisList);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
124
125
126
}


Uwe Schulzweida's avatar
Uwe Schulzweida committed
127
static void taxis_init_pointer(void)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
128
{
Uwe Schulzweida's avatar
Uwe Schulzweida committed
129
130
131
132
133
134
135
136
137
138
139
140
  int  i;
  
  for ( i = 0; i < _taxis_max; i++ )
    {
      _taxisList[i].next = _taxisList + i + 1;
      _taxisList[i].idx  = i;
      _taxisList[i].ptr  = 0;
    }

  _taxisList[_taxis_max-1].next = 0;

  _taxisAvail = _taxisList;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
141
142
143
}


Uwe Schulzweida's avatar
Uwe Schulzweida committed
144
TAXIS *taxis_to_pointer(int idx)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
145
{
Uwe Schulzweida's avatar
Uwe Schulzweida committed
146
147
  static char func[] = "taxis_to_pointer";
  TAXIS *taxisptr = NULL;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
148

Uwe Schulzweida's avatar
Uwe Schulzweida committed
149
  TAXIS_INIT
Uwe Schulzweida's avatar
Uwe Schulzweida committed
150

Uwe Schulzweida's avatar
Uwe Schulzweida committed
151
  if ( idx >= 0 && idx < _taxis_max )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
152
    {
Uwe Schulzweida's avatar
Uwe Schulzweida committed
153
      TAXIS_LOCK
Uwe Schulzweida's avatar
Uwe Schulzweida committed
154

Uwe Schulzweida's avatar
Uwe Schulzweida committed
155
      taxisptr = _taxisList[idx].ptr;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
156

Uwe Schulzweida's avatar
Uwe Schulzweida committed
157
      TAXIS_UNLOCK
Uwe Schulzweida's avatar
Uwe Schulzweida committed
158
159
    }
  else
Uwe Schulzweida's avatar
Uwe Schulzweida committed
160
161
162
163
164
165
166
167
168
169
170
171
172
173
    Error(func, "taxis index %d undefined!", idx);

  return (taxisptr);
}


/* Create an index from a pointer */
static int taxis_from_pointer(TAXIS *ptr)
{
  static char func[] = "taxis_from_pointer";
  int      idx = -1;
  taxisPtrToIdx *newptr;

  if ( ptr )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
174
    {
Uwe Schulzweida's avatar
Uwe Schulzweida committed
175
176
177
      TAXIS_LOCK

      if ( _taxisAvail )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
178
	{
Uwe Schulzweida's avatar
Uwe Schulzweida committed
179
	  newptr       = _taxisAvail;
180
	  _taxisAvail  = _taxisAvail->next;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
181
182
183
184
185
186
	  newptr->next = 0;
	  idx	       = newptr->idx;
	  newptr->ptr  = ptr;
      
	  if ( TAXIS_Debug )
	    Message(func, "Pointer %p has idx %d from taxis list", ptr, idx);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
187
	}
Uwe Schulzweida's avatar
Uwe Schulzweida committed
188
189
190
191
      else
	Warning(func, "Too many open taxis (limit is %d)!", _taxis_max);

      TAXIS_UNLOCK
Uwe Schulzweida's avatar
Uwe Schulzweida committed
192
    }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
193
194
  else
    Error(func, "Internal problem (pointer %p undefined)", ptr);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
195

Uwe Schulzweida's avatar
Uwe Schulzweida committed
196
197
  return (idx);
}
Uwe Schulzweida's avatar
Uwe Schulzweida committed
198
199


Uwe Schulzweida's avatar
Uwe Schulzweida committed
200
201
202
203
204
205
206
207
208
209
void taxis_init_ptr(TAXIS *taxisptr)
{
  taxisptr->self       = -1;

  taxisptr->used       = FALSE;
  taxisptr->type       = DefaultTimeType;
  taxisptr->vdate      = 0;
  taxisptr->vtime      = 0;
  taxisptr->rdate      = CDI_UNDEFID;
  taxisptr->rtime      = 0;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
210
  taxisptr->calendar   = cdiDefaultCalendar;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
211
212
213
214
215
216
217
218
  taxisptr->unit       = DefaultTimeUnit;
  taxisptr->numavg     = 0;
  taxisptr->has_bounds = FALSE;
  taxisptr->vdate_lb   = 0;
  taxisptr->vtime_lb   = 0;
  taxisptr->vdate_ub   = 0;
  taxisptr->vtime_ub   = 0;
}
Uwe Schulzweida's avatar
Uwe Schulzweida committed
219

220

Uwe Schulzweida's avatar
Uwe Schulzweida committed
221
222
223
void taxis_init_entry(TAXIS *taxisptr)
{
  taxis_init_ptr(taxisptr);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
224

Uwe Schulzweida's avatar
Uwe Schulzweida committed
225
  taxisptr->self       = taxis_from_pointer(taxisptr);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
226
227
228
}


Uwe Schulzweida's avatar
Uwe Schulzweida committed
229
static TAXIS *taxis_new_entry(void)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
230
{
Uwe Schulzweida's avatar
Uwe Schulzweida committed
231
232
233
234
  static char func[] = "taxis_new_entry";
  TAXIS *taxisptr;

  taxisptr = (TAXIS *) malloc(sizeof(TAXIS));
Uwe Schulzweida's avatar
Uwe Schulzweida committed
235

Uwe Schulzweida's avatar
Uwe Schulzweida committed
236
  if ( taxisptr ) taxis_init_entry(taxisptr);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
237

238
239
  /*  fprintf(stderr, "self: %d %p\n", taxisptr->self, taxisptr); */

Uwe Schulzweida's avatar
Uwe Schulzweida committed
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
  return (taxisptr);
}


static void taxis_delete_entry(TAXIS *taxisptr)
{
  static char func[] = "taxis_delete_entry";
  int idx;

  idx = taxisptr->self;

  TAXIS_LOCK

  free(taxisptr);

  _taxisList[idx].next = _taxisAvail;
  _taxisList[idx].ptr  = 0;
  _taxisAvail          = &_taxisList[idx];

  TAXIS_UNLOCK

  if ( TAXIS_Debug )
    Message(func, "Removed idx %d from taxis list", idx);
}


static void taxis_initialize(void)
{
  char *env;

#if  defined  (HAVE_LIBPTHREAD)
  /* initialize global API mutex lock */
  pthread_mutex_init(&_taxis_mutex, NULL);
#endif

  env = getenv("TAXIS_DEBUG");
  if ( env ) TAXIS_Debug = atoi(env);

  taxis_list_new();
  atexit(taxis_list_delete);

281
282
  TAXIS_LOCK

Uwe Schulzweida's avatar
Uwe Schulzweida committed
283
  taxis_init_pointer();
284
285
  
  TAXIS_UNLOCK
Uwe Schulzweida's avatar
Uwe Schulzweida committed
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306

  _taxis_init = TRUE;

  taxis_defaults();
}


static void taxis_copy(TAXIS *taxisptr2, TAXIS *taxisptr1)
{
  int taxisID2;

  taxisID2 = taxisptr2->self;
  memcpy(taxisptr2, taxisptr1, sizeof(TAXIS));
  taxisptr2->self = taxisID2;
}


static void taxis_check_ptr(const char *func, TAXIS *taxisptr)
{
  if ( taxisptr == NULL )
    Error(func, "taxis undefined!");
Uwe Schulzweida's avatar
Uwe Schulzweida committed
307
308
309
310
}


/*
311
@Function  taxisCreate
312
@Title     Create a Time axis
Uwe Schulzweida's avatar
Uwe Schulzweida committed
313

314
@Prototype int taxisCreate(int taxistype)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
315
@Parameter
Uwe Schulzweida's avatar
Uwe Schulzweida committed
316
317
    @Item  taxistype  The type of the Time axis, one of the set of predefined CDI time axis types.
                      The valid CDI time axis types are @func{TAXIS_ABSOLUTE} and @func{TAXIS_RELATIVE}.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
318
319

@Description
320
The function @func{taxisCreate} creates a Time axis.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
321
322

@Result
323
@func{taxisCreate} returns an identifier to the Time axis.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
324

Uwe Schulzweida's avatar
Uwe Schulzweida committed
325
326
327
328
329
330
331
332
333
334
335
336
@Example
Here is an example using @func{taxisCreate} to create a relative T-axis
with a standard calendar.

@Source
#include "cdi.h"
   ...
int taxisID;
   ...
taxisID = taxisCreate(TAXIS_RELATIVE);
taxisDefCalendar(taxisID, CALENDAR_STANDARD);
taxisDefRdate(taxisID, 19870101);
337
taxisDefRtime(taxisID, 120000);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
338
339
   ...
@EndSource
Uwe Schulzweida's avatar
Uwe Schulzweida committed
340
341
@EndFunction
*/
342
int taxisCreate(int taxistype)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
343
{
344
  static char func[] = "taxisCreate";
Uwe Schulzweida's avatar
Uwe Schulzweida committed
345
  int taxisID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
346
  TAXIS *taxisptr;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
347
348
349
350

  if ( CDI_Debug )
    Message(func, "taxistype: %d", taxistype);

Uwe Schulzweida's avatar
Uwe Schulzweida committed
351
352
353
354
355
356
357
  TAXIS_INIT

  taxisptr = taxis_new_entry();
  if ( ! taxisptr ) Error(func, "No memory");

  taxisID = taxisptr->self;
  taxisptr->type = taxistype;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
358
359
360
361
362
363
364
365

  if ( CDI_Debug )
    Message(func, "taxisID: %d", taxisID);

  return (taxisID);
}


366
367
368
369
370
371
/*
@Function  taxisDestroy
@Title     Destroy a Time axis

@Prototype void taxisDestroy(int taxisID)
@Parameter
372
    @Item  taxisID  Time axis ID, from a previous call to @func{taxisCreate}
373
374
375
376
377

@EndFunction
*/
void taxisDestroy(int taxisID)
{
378
379
380
381
382
383
384
385
  static char func[] = "taxisDestroy";
  TAXIS *taxisptr;

  taxisptr = taxis_to_pointer(taxisID);

  taxis_check_ptr(func, taxisptr);

  taxis_delete_entry(taxisptr);
386
387
388
}


Uwe Schulzweida's avatar
Uwe Schulzweida committed
389
390
391
392
int taxisDuplicate(int taxisID1)
{
  static char func[] = "taxisDuplicate";
  int taxisID2;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
393
394
395
396
397
398
399
400
401
  TAXIS *taxisptr1;
  TAXIS *taxisptr2;

  taxisptr1 = taxis_to_pointer(taxisID1);

  taxisptr2 = taxis_new_entry();
  if ( ! taxisptr2 ) Error(func, "No memory");

  taxisID2 = taxisptr2->self;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
402
403

  if ( CDI_Debug )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
404
    Message(func, "taxisID2: %d", taxisID2);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
405

Uwe Schulzweida's avatar
Uwe Schulzweida committed
406
  ptaxisCopy(taxisptr2, taxisptr1);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
407

408
  // taxisptr2->has_bounds = FALSE;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
409

Uwe Schulzweida's avatar
Uwe Schulzweida committed
410
411
412
413
414
415
416
  return (taxisID2);
}


void taxisDefType(int taxisID, int type)
{
  static char func[] = "taxisDefType";
Uwe Schulzweida's avatar
Uwe Schulzweida committed
417
418
419
  TAXIS *taxisptr;

  taxisptr = taxis_to_pointer(taxisID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
420

Uwe Schulzweida's avatar
Uwe Schulzweida committed
421
  taxis_check_ptr(func, taxisptr);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
422

Uwe Schulzweida's avatar
Uwe Schulzweida committed
423
  taxisptr->type = type;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
424
425
426
427
428
429
430
431
432
}


/*
@Function  taxisDefVdate
@Title     Define the verification date

@Prototype void taxisDefVdate(int taxisID, int vdate)
@Parameter
Uwe Schulzweida's avatar
Uwe Schulzweida committed
433
    @Item  taxisID  Time axis ID, from a previous call to @fref{taxisCreate}
Uwe Schulzweida's avatar
Uwe Schulzweida committed
434
435
436
    @Item  vdate    Verification date (YYYYMMDD)

@Description
437
The function @func{taxisDefVdate} defines the verification date of a Time axis.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
438
439
440
441
442
443

@EndFunction
*/
void taxisDefVdate(int taxisID, int vdate)
{
  static char func[] = "taxisDefVdate";
Uwe Schulzweida's avatar
Uwe Schulzweida committed
444
  TAXIS *taxisptr;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
445

Uwe Schulzweida's avatar
Uwe Schulzweida committed
446
  taxisptr = taxis_to_pointer(taxisID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
447

Uwe Schulzweida's avatar
Uwe Schulzweida committed
448
449
450
  taxis_check_ptr(func, taxisptr);

  taxisptr->vdate = vdate;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
451
452
453
454
455
456
457
458
459
}


/*
@Function  taxisDefVtime
@Title     Define the verification time

@Prototype void taxisDefVtime(int taxisID, int vtime)
@Parameter
Uwe Schulzweida's avatar
Uwe Schulzweida committed
460
    @Item  taxisID  Time axis ID, from a previous call to @fref{taxisCreate}
461
    @Item  vtime    Verification time (hhmmss)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
462
463

@Description
464
The function @func{taxisDefVtime} defines the verification time of a Time axis.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
465
466
467
468
469
470

@EndFunction
*/
void taxisDefVtime(int taxisID, int vtime)
{
  static char func[] = "taxisDefVtime";
Uwe Schulzweida's avatar
Uwe Schulzweida committed
471
472
473
  TAXIS *taxisptr;

  taxisptr = taxis_to_pointer(taxisID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
474

Uwe Schulzweida's avatar
Uwe Schulzweida committed
475
  taxis_check_ptr(func, taxisptr);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
476

Uwe Schulzweida's avatar
Uwe Schulzweida committed
477
  taxisptr->vtime = vtime;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
478
479
480
481
482
483
484
485
486
}


/*
@Function  taxisDefRdate
@Title     Define the reference date

@Prototype void taxisDefRdate(int taxisID, int rdate)
@Parameter
Uwe Schulzweida's avatar
Uwe Schulzweida committed
487
    @Item  taxisID  Time axis ID, from a previous call to @fref{taxisCreate}
Uwe Schulzweida's avatar
Uwe Schulzweida committed
488
489
490
    @Item  rdate    Reference date (YYYYMMDD)

@Description
491
The function @func{taxisDefVdate} defines the reference date of a Time axis.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
492
493
494
495
496
497

@EndFunction
*/
void taxisDefRdate(int taxisID, int rdate)
{
  static char func[] = "taxisDefRdate";
Uwe Schulzweida's avatar
Uwe Schulzweida committed
498
  TAXIS *taxisptr;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
499

Uwe Schulzweida's avatar
Uwe Schulzweida committed
500
  taxisptr = taxis_to_pointer(taxisID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
501

Uwe Schulzweida's avatar
Uwe Schulzweida committed
502
503
504
  taxis_check_ptr(func, taxisptr);

  taxisptr->rdate = rdate;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
505
506
507
508
509
510
511
512
513
}


/*
@Function  taxisDefRtime
@Title     Define the reference time

@Prototype void taxisDefRtime(int taxisID, int rtime)
@Parameter
Uwe Schulzweida's avatar
Uwe Schulzweida committed
514
    @Item  taxisID  Time axis ID, from a previous call to @fref{taxisCreate}
515
    @Item  rtime    Reference time (hhmmss)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
516
517

@Description
518
The function @func{taxisDefVdate} defines the reference time of a Time axis.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
519
520
521
522
523
524

@EndFunction
*/
void taxisDefRtime(int taxisID, int rtime)
{
  static char func[] = "taxisDefRtime";
Uwe Schulzweida's avatar
Uwe Schulzweida committed
525
526
527
  TAXIS *taxisptr;

  taxisptr = taxis_to_pointer(taxisID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
528

Uwe Schulzweida's avatar
Uwe Schulzweida committed
529
  taxis_check_ptr(func, taxisptr);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
530

Uwe Schulzweida's avatar
Uwe Schulzweida committed
531
  taxisptr->rtime = rtime;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
532
533
534
535
536
537
538
539
540
}


/*
@Function  taxisDefCalendar
@Title     Define the calendar

@Prototype void taxisDefCalendar(int taxisID, int calendar)
@Parameter
Uwe Schulzweida's avatar
Uwe Schulzweida committed
541
    @Item  taxisID  Time axis ID, from a previous call to @fref{taxisCreate}
542
    @Item  calendar The type of the calendar, one of the set of predefined CDI calendar types.
543
544
                    The valid CDI calendar types are @func{CALENDAR_STANDARD}, @func{CALENDAR_PROLEPTIC}, 
                    @func{CALENDAR_360DAYS}, @func{CALENDAR_365DAYS} and @func{CALENDAR_366DAYS}.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
545
546

@Description
547
The function @func{taxisDefCalendar} defines the calendar of a Time axis.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
548
549
550
551
552
553

@EndFunction
*/
void taxisDefCalendar(int taxisID, int calendar)
{
  static char func[] = "taxisDefCalendar";
Uwe Schulzweida's avatar
Uwe Schulzweida committed
554
  TAXIS *taxisptr;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
555

Uwe Schulzweida's avatar
Uwe Schulzweida committed
556
  taxisptr = taxis_to_pointer(taxisID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
557

Uwe Schulzweida's avatar
Uwe Schulzweida committed
558
559
560
  taxis_check_ptr(func, taxisptr);

  taxisptr->calendar = calendar;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
561
562
563
564
565
566
}


void taxisDefTunit(int taxisID, int unit)
{
  static char func[] = "taxisDefTunit";
Uwe Schulzweida's avatar
Uwe Schulzweida committed
567
568
569
  TAXIS *taxisptr;

  taxisptr = taxis_to_pointer(taxisID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
570

Uwe Schulzweida's avatar
Uwe Schulzweida committed
571
  taxis_check_ptr(func, taxisptr);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
572

Uwe Schulzweida's avatar
Uwe Schulzweida committed
573
  taxisptr->unit = unit;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
574
575
576
577
578
}

void taxisDefNumavg(int taxisID, int numavg)
{
  static char func[] = "taxisDefNumavg";
Uwe Schulzweida's avatar
Uwe Schulzweida committed
579
  TAXIS *taxisptr;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
580

Uwe Schulzweida's avatar
Uwe Schulzweida committed
581
  taxisptr = taxis_to_pointer(taxisID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
582

Uwe Schulzweida's avatar
Uwe Schulzweida committed
583
584
585
  taxis_check_ptr(func, taxisptr);

  taxisptr->numavg = numavg;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
586
587
588
589
590
591
592
593
594
595
}


/*
The type of the time axis, one of the set of predefined CDI time types.
The valid CDI time types are TAXIS_ABSOLUTE and TAXIS_RELATIVE.
*/
int taxisInqType(int taxisID)
{
  static char func[] = "taxisInqType";
Uwe Schulzweida's avatar
Uwe Schulzweida committed
596
597
598
  TAXIS *taxisptr;

  taxisptr = taxis_to_pointer(taxisID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
599

Uwe Schulzweida's avatar
Uwe Schulzweida committed
600
  taxis_check_ptr(func, taxisptr);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
601

Uwe Schulzweida's avatar
Uwe Schulzweida committed
602
  return (taxisptr->type);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
603
604
605
}


Uwe Schulzweida's avatar
Uwe Schulzweida committed
606
607
608
609
610
611
612
613
614
615
616
617
618
int taxisHasBounds(int taxisID)
{
  static char func[] = "taxisHasBounds";
  TAXIS *taxisptr;

  taxisptr = taxis_to_pointer(taxisID);

  taxis_check_ptr(func, taxisptr);

  return (taxisptr->has_bounds);
}


619
620
621
622
623
624
625
626
627
628
629
630
631
void taxisDeleteBounds(int taxisID)
{
  static char func[] = "taxisDeleteBounds";
  TAXIS *taxisptr;

  taxisptr = taxis_to_pointer(taxisID);

  taxis_check_ptr(func, taxisptr);

  taxisptr->has_bounds = FALSE;
}


Uwe Schulzweida's avatar
Uwe Schulzweida committed
632
void taxisCopyTimestep(int taxisID2, int taxisID1)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
633
634
{
  static char func[] = "taxisCopyTimestep";
Uwe Schulzweida's avatar
Uwe Schulzweida committed
635
636
  TAXIS *taxisptr1;
  TAXIS *taxisptr2;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
637

Uwe Schulzweida's avatar
Uwe Schulzweida committed
638
639
  taxisptr1 = taxis_to_pointer(taxisID1);
  taxisptr2 = taxis_to_pointer(taxisID2);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
640

Uwe Schulzweida's avatar
Uwe Schulzweida committed
641
642
  taxis_check_ptr(func, taxisptr1);
  taxis_check_ptr(func, taxisptr2);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
643

644
645
646
  taxisptr2->rdate = taxisptr1->rdate;
  taxisptr2->rtime = taxisptr1->rtime;

Uwe Schulzweida's avatar
Uwe Schulzweida committed
647
648
649
650
  taxisptr2->vdate = taxisptr1->vdate;
  taxisptr2->vtime = taxisptr1->vtime;

  if ( taxisptr2->has_bounds )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
651
    {
Uwe Schulzweida's avatar
Uwe Schulzweida committed
652
653
654
655
      taxisptr2->vdate_lb = taxisptr1->vdate_lb;
      taxisptr2->vtime_lb = taxisptr1->vtime_lb;
      taxisptr2->vdate_ub = taxisptr1->vdate_ub;
      taxisptr2->vtime_ub = taxisptr1->vtime_ub;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
656
657
658
659
660
661
662
663
664
665
    }
}


/*
@Function  taxisInqVdate
@Title     Get the verification date

@Prototype int taxisInqVdate(int taxisID)
@Parameter
Uwe Schulzweida's avatar
Uwe Schulzweida committed
666
    @Item  taxisID  Time axis ID, from a previous call to @fref{taxisCreate}
Uwe Schulzweida's avatar
Uwe Schulzweida committed
667
668

@Description
669
The function @func{taxisInqVdate} returns the verification date of a Time axis.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
670
671

@Result
672
@func{taxisInqVdate} returns the verification date.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
673
674
675
676
677
678

@EndFunction
*/
int taxisInqVdate(int taxisID)
{
  static char func[] = "taxisInqVdate";
Uwe Schulzweida's avatar
Uwe Schulzweida committed
679
680
681
  TAXIS *taxisptr;

  taxisptr = taxis_to_pointer(taxisID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
682

Uwe Schulzweida's avatar
Uwe Schulzweida committed
683
  taxis_check_ptr(func, taxisptr);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
684

Uwe Schulzweida's avatar
Uwe Schulzweida committed
685
  return (taxisptr->vdate);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
686
687
688
}


Uwe Schulzweida's avatar
Uwe Schulzweida committed
689
690
691
692
693
694
695
696
697
698
699
700
701
702
void taxisInqVdateBounds(int taxisID, int *vdate_lb, int *vdate_ub)
{
  static char func[] = "taxisInqVdateBounds";
  TAXIS *taxisptr;

  taxisptr = taxis_to_pointer(taxisID);

  taxis_check_ptr(func, taxisptr);

  *vdate_lb = taxisptr->vdate_lb;
  *vdate_ub = taxisptr->vdate_ub;
}


703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
void taxisDefVdateBounds(int taxisID, int vdate_lb, int vdate_ub)
{
  static char func[] = "taxisDefVdateBounds";
  TAXIS *taxisptr;

  taxisptr = taxis_to_pointer(taxisID);

  taxis_check_ptr(func, taxisptr);

  taxisptr->vdate_lb = vdate_lb;
  taxisptr->vdate_ub = vdate_ub;
 
  taxisptr->has_bounds = TRUE;
}


Uwe Schulzweida's avatar
Uwe Schulzweida committed
719
720
721
722
723
724
/*
@Function  taxisInqVtime
@Title     Get the verification time

@Prototype int taxisInqVtime(int taxisID)
@Parameter
Uwe Schulzweida's avatar
Uwe Schulzweida committed
725
    @Item  taxisID  Time axis ID, from a previous call to @fref{taxisCreate}
Uwe Schulzweida's avatar
Uwe Schulzweida committed
726
727

@Description
728
The function @func{taxisInqVtime} returns the verification time of a Time axis.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
729
730

@Result
731
@func{taxisInqVtime} returns the verification time.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
732
733
734
735
736
737

@EndFunction
*/
int taxisInqVtime(int taxisID)
{
  static char func[] = "taxisInqVtime";
Uwe Schulzweida's avatar
Uwe Schulzweida committed
738
  TAXIS *taxisptr;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
739

Uwe Schulzweida's avatar
Uwe Schulzweida committed
740
  taxisptr = taxis_to_pointer(taxisID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
741

Uwe Schulzweida's avatar
Uwe Schulzweida committed
742
743
744
  taxis_check_ptr(func, taxisptr);

  return (taxisptr->vtime);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
745
746
747
}


Uwe Schulzweida's avatar
Uwe Schulzweida committed
748
749
750
751
752
753
754
755
756
757
758
759
760
761
void taxisInqVtimeBounds(int taxisID, int *vtime_lb, int *vtime_ub)
{
  static char func[] = "taxisInqVtimeBounds";
  TAXIS *taxisptr;

  taxisptr = taxis_to_pointer(taxisID);

  taxis_check_ptr(func, taxisptr);

  *vtime_lb = taxisptr->vtime_lb;
  *vtime_ub = taxisptr->vtime_ub;
}


762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
void taxisDefVtimeBounds(int taxisID, int vtime_lb, int vtime_ub)
{
  static char func[] = "taxisDefVtimeBounds";
  TAXIS *taxisptr;

  taxisptr = taxis_to_pointer(taxisID);

  taxis_check_ptr(func, taxisptr);

  taxisptr->vtime_lb = vtime_lb;
  taxisptr->vtime_ub = vtime_ub;
 
  taxisptr->has_bounds = TRUE;
}


Uwe Schulzweida's avatar
Uwe Schulzweida committed
778
779
780
781
782
783
/*
@Function  taxisInqRdate
@Title     Get the reference date

@Prototype int taxisInqRdate(int taxisID)
@Parameter
Uwe Schulzweida's avatar
Uwe Schulzweida committed
784
    @Item  taxisID  Time axis ID, from a previous call to @fref{taxisCreate}
Uwe Schulzweida's avatar
Uwe Schulzweida committed
785
786

@Description
787
The function @func{taxisInqRdate} returns the reference date of a Time axis.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
788
789

@Result
790
@func{taxisInqVdate} returns the reference date.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
791
792
793
794
795
796

@EndFunction
*/
int taxisInqRdate(int taxisID)
{
  static char func[] = "taxisInqRdate";
Uwe Schulzweida's avatar
Uwe Schulzweida committed
797
798
799
  TAXIS *taxisptr;

  taxisptr = taxis_to_pointer(taxisID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
800

Uwe Schulzweida's avatar
Uwe Schulzweida committed
801
  taxis_check_ptr(func, taxisptr);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
802

Uwe Schulzweida's avatar
Uwe Schulzweida committed
803
  if ( taxisptr->rdate == -1 )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
804
    {
Uwe Schulzweida's avatar
Uwe Schulzweida committed
805
806
      taxisptr->rdate = taxisptr->vdate;
      taxisptr->rtime = taxisptr->vtime;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
807
808
    }

Uwe Schulzweida's avatar
Uwe Schulzweida committed
809
  return (taxisptr->rdate);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
810
811
812
813
814
815
816
817
818
}


/*
@Function  taxisInqRtime
@Title     Get the reference time

@Prototype int taxisInqRtime(int taxisID)
@Parameter
Uwe Schulzweida's avatar
Uwe Schulzweida committed
819
    @Item  taxisID  Time axis ID, from a previous call to @fref{taxisCreate}
Uwe Schulzweida's avatar
Uwe Schulzweida committed
820
821

@Description
822
The function @func{taxisInqRtime} returns the reference time of a Time axis.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
823
824

@Result
825
@func{taxisInqVtime} returns the reference time.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
826
827
828
829
830
831

@EndFunction
*/
int taxisInqRtime(int taxisID)
{
  static char func[] = "taxisInqRtime";
Uwe Schulzweida's avatar
Uwe Schulzweida committed
832
833
834
  TAXIS *taxisptr;

  taxisptr = taxis_to_pointer(taxisID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
835

Uwe Schulzweida's avatar
Uwe Schulzweida committed
836
  taxis_check_ptr(func, taxisptr);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
837

Uwe Schulzweida's avatar
Uwe Schulzweida committed
838
  if ( taxisptr->rdate == -1 )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
839
    {
Uwe Schulzweida's avatar
Uwe Schulzweida committed
840
841
      taxisptr->rdate = taxisptr->vdate;
      taxisptr->rtime = taxisptr->vtime;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
842
843
    }

Uwe Schulzweida's avatar
Uwe Schulzweida committed
844
  return (taxisptr->rtime);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
845
846
847
848
849
850
851
852
853
}


/*
@Function  taxisInqCalendar
@Title     Get the calendar

@Prototype int taxisInqCalendar(int taxisID)
@Parameter
Uwe Schulzweida's avatar
Uwe Schulzweida committed
854
    @Item  taxisID  Time axis ID, from a previous call to @fref{taxisCreate}
Uwe Schulzweida's avatar
Uwe Schulzweida committed
855
856

@Description
857
The function @func{taxisInqCalendar} returns the calendar of a Time axis.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
858
859

@Result
860
@func{taxisInqCalendar} returns the type of the calendar,
Uwe Schulzweida's avatar
Uwe Schulzweida committed
861
one of the set of predefined CDI calendar types.
862
863
The valid CDI calendar types are @func{CALENDAR_STANDARD}, @func{CALENDAR_PROLEPRIC}, 
@func{CALENDAR_360DAYS}, @func{CALENDAR_365DAYS} and @func{CALENDAR_366DAYS}.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
864
865
866
867
868
869

@EndFunction
*/
int taxisInqCalendar(int taxisID)
{
  static char func[] = "taxisInqCalendar";
Uwe Schulzweida's avatar
Uwe Schulzweida committed
870
  TAXIS *taxisptr;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
871

Uwe Schulzweida's avatar
Uwe Schulzweida committed
872
  taxisptr = taxis_to_pointer(taxisID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
873

Uwe Schulzweida's avatar
Uwe Schulzweida committed
874
875
876
  taxis_check_ptr(func, taxisptr);

  return (taxisptr->calendar);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
877
878
879
880
881
882
}


int taxisInqTunit(int taxisID)
{
  static char func[] = "taxisInqTunit";
Uwe Schulzweida's avatar
Uwe Schulzweida committed
883
884
885
  TAXIS *taxisptr;

  taxisptr = taxis_to_pointer(taxisID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
886

Uwe Schulzweida's avatar
Uwe Schulzweida committed
887
  taxis_check_ptr(func, taxisptr);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
888

Uwe Schulzweida's avatar
Uwe Schulzweida committed
889
  return (taxisptr->unit);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
890
891
892
893
894
895
}


int taxisInqNumavg(int taxisID)
{
  static char func[] = "taxisInqNumavg";
Uwe Schulzweida's avatar
Uwe Schulzweida committed
896
  TAXIS *taxisptr;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
897

Uwe Schulzweida's avatar
Uwe Schulzweida committed
898
  taxisptr = taxis_to_pointer(taxisID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
899

Uwe Schulzweida's avatar
Uwe Schulzweida committed
900
901
902
  taxis_check_ptr(func, taxisptr);

  return (taxisptr->numavg);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
903
904
905
906
907
908
}


TAXIS *taxisPtr(int taxisID)
{
  static char func[] = "taxisPtr";
Uwe Schulzweida's avatar
Uwe Schulzweida committed
909
910
911
  TAXIS *taxisptr;

  taxisptr = taxis_to_pointer(taxisID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
912

Uwe Schulzweida's avatar
Uwe Schulzweida committed
913
  taxis_check_ptr(func, taxisptr);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
914

Uwe Schulzweida's avatar
Uwe Schulzweida committed
915
  return (taxisptr);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
916
917
918
}


Uwe Schulzweida's avatar
Uwe Schulzweida committed
919
void cdiDecodeTimevalue(int timeunit, double timevalue, int *days, int *secs)
920
{
Uwe Schulzweida's avatar
Uwe Schulzweida committed
921
  static char func[] = "cdiDecodeTimevalue";
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
  static int lwarn = TRUE;

  if ( timeunit == TUNIT_MINUTE )
    {
      timevalue *= 60;
      timeunit = TUNIT_SECOND;
    }
  else if ( timeunit == TUNIT_HOUR )
    {
      timevalue /= 24;
      timeunit = TUNIT_DAY;
    }

  if ( timeunit == TUNIT_SECOND )
    {
      *days = (int) (timevalue/86400);
      *secs = (int) (timevalue - *days*86400.);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
939
      if ( *secs < 0 ) { *days -= 1; *secs += 86400; };
940
941
942
943
944
945
946
947
948
949
950
      /*
      {
	double cval = *days*86400. + *secs;
	if ( cval != timevalue )
	  printf("TUNIT_SECOND error: %g %g %d %d\n", timevalue, cval, *days, *secs);
      }
      */
    }
  else if ( timeunit == TUNIT_DAY )
    {
      *days = (int) timevalue;
951
      *secs = (int) ((timevalue - *days)*86400 + 0.5);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
952
      if ( *secs < 0 ) { *days -= 1; *secs += 86400; };
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
      /*
      {
	double cval = *days + *secs/86400.;
	if ( cval != timevalue )
	  printf("TUNIT_DAY error: %g %g %d %d\n", timevalue, cval, *days, *secs);
      }
      */
    }
  else
    {
      if ( lwarn )
	{
	  Warning(func, "timeunit %s unsupported!", tunitNamePtr(timeunit));
	  lwarn = FALSE;
	}
    }
}

971
static
Uwe Schulzweida's avatar
Uwe Schulzweida committed
972
void cdiEncodeTimevalue(int days, int secs, int timeunit, double *timevalue)
973
{
Uwe Schulzweida's avatar
Uwe Schulzweida committed
974
  static char func[] = "cdiEncodeTimevalue";
975
976
977
978
979
980
981
982
983
984
  static int lwarn = TRUE;

  if ( timeunit == TUNIT_SECOND )
    {
      *timevalue = days*86400. + secs;
    }
  else if ( timeunit == TUNIT_MINUTE )
    {
      *timevalue = days*1440. + secs/60.;
    }
985
986
987
988
  else if ( timeunit == TUNIT_QUARTER )
    {
      *timevalue = days*1440. + secs/60.;
    }
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
  else if ( timeunit == TUNIT_HOUR )
    {
      *timevalue = days*24. + secs/3600.;
    }
  else if ( timeunit == TUNIT_DAY )
    {
      *timevalue = days + secs/86400.;
    }
  else
    {
      if ( lwarn )
	{
	  Warning(func, "timeunit %s unsupported!", tunitNamePtr(timeunit));
	  lwarn = FALSE;
	}
    }
}

1007
int days_per_month(int calendar, int year, int month);
1008

Uwe Schulzweida's avatar
Uwe Schulzweida committed
1009
1010
void timeval2vtime(double timevalue, TAXIS *taxis, int *vdate, int *vtime)
{
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1011
  static char func[] = "timeval2vtime";
1012
  int year, month, day, hour, minute, second;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1013
1014
  int rdate, rtime;
  int timeunit;
1015
1016
  int calendar;
  int julday, secofday, days, secs;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1017
  static int lwarn = TRUE;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1018
1019
1020
1021
1022
1023
1024
1025
1026

  *vdate = 0;
  *vtime = 0;

  timeunit = (*taxis).unit;
  calendar = (*taxis).calendar;

  rdate  = (*taxis).rdate;
  rtime  = (*taxis).rtime;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1027
1028
  cdiDecodeDate(rdate, &year, &month, &day);
  cdiDecodeTime(rtime, &hour, &minute, &second);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1029

1030
1031
1032
1033
1034
1035
  if ( timeunit == TUNIT_MONTH && calendar == CALENDAR_360DAYS )
    {
      timeunit = TUNIT_DAY;
      timevalue *= 30;
    }

Uwe Schulzweida's avatar
Uwe Schulzweida committed
1036
1037
  if ( timeunit == TUNIT_MONTH || timeunit == TUNIT_YEAR )
    {
1038
      static int lold = FALSE;
1039

Uwe Schulzweida's avatar
Uwe Schulzweida committed
1040
1041
1042
1043
1044
      if ( timeunit == TUNIT_YEAR )
	{
	  timeunit = TUNIT_MONTH;
	  timevalue *= 12;
	}
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1045

1046
      if ( lold )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1047
	{
1048
	  int nmon;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1049

1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
	  if ( (NINT(timevalue*10))%10 && lwarn )
	    {
	      Warning(func, "Possible wrong calculation of date/time!\n"
		      "Non integer time offset unsupported for time unit MONTH and YEAR!");
	      lwarn = FALSE;
	    }

	  nmon = (int) (timevalue+0.001);

	  month += nmon;
	  
	  while ( month > 12 ) { month -= 12; year++; }
	  while ( month <  1 ) { month += 12; year--; }
	}
      else
	{
	  int nmon, dpm;
	  double fmon;
	  
	  nmon = (int) timevalue;
	  fmon = timevalue - nmon;
	  
	  month += nmon;
	  
	  while ( month > 12 ) { month -= 12; year++; }
	  while ( month <  1 ) { month += 12; year--; }

	  dpm = days_per_month(calendar, year, month);
	  timeunit = TUNIT_DAY;
	  timevalue = fmon*dpm;
	}
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1081
    }
1082
1083

  if ( timeunit != TUNIT_MONTH && timeunit != TUNIT_YEAR )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1084
    {
1085
      encode_caldaysec(calendar, year, month, day, hour, minute, second, &julday, &secofday);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1086

Uwe Schulzweida's avatar
Uwe Schulzweida committed
1087
      cdiDecodeTimevalue(timeunit, timevalue, &days, &secs);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1088

1089
      julday_add(days, secs, &julday, &secofday);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1090

1091
      decode_caldaysec(calendar, julday, secofday, &year, &month, &day, &hour, &minute, &second);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1092
1093
    }

Uwe Schulzweida's avatar
Uwe Schulzweida committed
1094
1095
  *vdate = cdiEncodeDate(year, month, day);
  *vtime = cdiEncodeTime(hour, minute, second);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1096
1097
1098
1099
1100
1101
}


double vtime2timeval(int vdate, int vtime, TAXIS *taxis)
{
  int ryear, rmonth;
1102
  int year, month, day, hour, minute, second;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1103
  int rdate, rtime;
1104
  double value = 0;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1105
  int timeunit;
1106
  int timeunit0;
1107
1108
  int calendar;
  int julday1, secofday1, julday2, secofday2, days, secs;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1109
1110
1111
1112

  timeunit = (*taxis).unit;
  calendar = (*taxis).calendar;

1113
1114
  rdate = (*taxis).rdate;
  rtime = (*taxis).rtime;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1115
1116
1117
1118
1119
1120
  if ( rdate == -1 )
    {
      rdate  = (*taxis).vdate;
      rtime  = (*taxis).vtime;
    }

Uwe Schulzweida's avatar
Uwe Schulzweida committed
1121
1122
  cdiDecodeDate(rdate, &ryear, &rmonth, &day);
  cdiDecodeTime(rtime, &hour, &minute, &second);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1123

1124
  encode_caldaysec(calendar, ryear, rmonth, day, hour, minute, second, &julday1, &secofday1);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1125

Uwe Schulzweida's avatar
Uwe Schulzweida committed
1126
1127
  cdiDecodeDate(vdate, &year, &month, &day);
  cdiDecodeTime(vtime, &hour, &minute, &second);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1128

1129
1130
1131
1132
1133
1134
1135
  timeunit0 = timeunit;

  if ( timeunit == TUNIT_MONTH && calendar == CALENDAR_360DAYS )
    {
      timeunit = TUNIT_DAY;
    }

Uwe Schulzweida's avatar
Uwe Schulzweida committed
1136
1137
  if ( timeunit == TUNIT_MONTH || timeunit == TUNIT_YEAR )
    {
1138
1139
1140
1141
      int nmonth, dpm;

      dpm = days_per_month(calendar, year, month);

Uwe Schulzweida's avatar
Uwe Schulzweida committed
1142
      value = (year-ryear)*12 - rmonth + month;
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155

      nmonth = (int) value;
      month -= nmonth;

      while ( month > 12 ) { month -= 12; year++; }
      while ( month <  1 ) { month += 12; year--; }

      encode_caldaysec(calendar, year, month, day, hour, minute, second, &julday2, &secofday2);

      julday_sub(julday1, secofday1, julday2, secofday2, &days, &secs);

      value += (days+secs/86400.)/dpm;

Uwe Schulzweida's avatar
Uwe Schulzweida committed
1156
1157
1158
1159
      if ( timeunit == TUNIT_YEAR ) value = NINT(value/12);
    }
  else
    {
1160
      encode_caldaysec(calendar, year, month, day, hour, minute, second, &julday2, &secofday2);
1161
1162

      julday_sub(julday1, secofday1, julday2, secofday2, &days, &secs);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1163

Uwe Schulzweida's avatar
Uwe Schulzweida committed
1164
      cdiEncodeTimevalue(days, secs, timeunit, &value);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1165
1166
    }

1167
1168
1169
1170
1171
  if ( timeunit0 == TUNIT_MONTH && calendar == CALENDAR_360DAYS )
    {
      value /= 30;
    }

Uwe Schulzweida's avatar
Uwe Schulzweida committed
1172
1173
1174
1175
1176
1177
1178
1179
  return (value);
}


void splitTimevalue(double timevalue, int timeunit, int *date, int *time)
{
  static char func[] = "splitTimevalue";
  int vdate = 0, vtime = 0;
1180
  int hour, minute, second;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1181
  int year, month, day;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1182
  int daysec;
1183
  static int lwarn = TRUE;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1184
1185
1186
1187

  if ( timeunit == TUNIT_HOUR )
    {
      timevalue /= 24;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1188
      vdate = (int) timevalue;
1189
      if ( vdate < 0 )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1190
	daysec = (int) (-(timevalue - vdate)*86400 + 0.01);
1191
      else
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1192
	daysec = (int) ( (timevalue - vdate)*86400 + 0.01);
1193
 
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1194
1195
1196
      hour   =  daysec / 3600;
      minute = (daysec - hour*3600)/60;
      second =  daysec - hour*3600 - minute*60;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1197
      vtime  = cdiEncodeTime(hour, minute, second);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1198
1199
1200
    }
  else if ( timeunit == TUNIT_DAY )
    {
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1201
      vdate = (int) timevalue;
1202
      if ( vdate < 0 )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1203
	daysec = (int) (-(timevalue - vdate)*86400 + 0.01);
1204
      else
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1205
	daysec = (int) ( (timevalue - vdate)*86400 + 0.01);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1206

Uwe Schulzweida's avatar
Uwe Schulzweida committed
1207
1208
1209
      hour   =  daysec / 3600;
      minute = (daysec - hour*3600)/60;
      second =  daysec - hour*3600 - minute*60;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1210
      vtime  = cdiEncodeTime(hour, minute, second);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1211
1212
1213
1214
1215
1216
    }
  else if ( timeunit == TUNIT_MONTH )
    {
      vdate = (int) timevalue*100;
      vtime = 0;
    }
1217
1218
  else if ( timeunit == TUNIT_YEAR )
    {
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
      if ( timevalue < -214700 )
	{
	  Warning(func, "Year %g out of range, set to -214700", timevalue);
	  timevalue = -214700;
	}
      else if ( timevalue > 214700 )
	{
	  Warning(func, "Year %g out of range, set to 214700", timevalue);
	  timevalue = 214700;
	}

1230
1231
1232
      vdate = (int) timevalue*10000;
      vtime = 0;
    }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1233
1234
  else
    {
1235
1236
1237
1238
1239
      if ( lwarn )
	{
	  Warning(func, "timeunit %s unsupported!", tunitNamePtr(timeunit));
	  lwarn = FALSE;
	}
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1240
1241
    }

Uwe Schulzweida's avatar
Uwe Schulzweida committed
1242
1243
  /* verify date and time */

Uwe Schulzweida's avatar
Uwe Schulzweida committed
1244
1245
  cdiDecodeDate(vdate, &year, &month, &day);
  cdiDecodeTime(vtime, &hour, &minute, &second);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1246

1247
  if ( month > 17 || day > 31 || hour > 23 || minute > 59 || second > 59 )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1248
1249
1250
1251
1252
1253
    {
      if ( (month  > 17 || day > 31) && (year < -9999 || year > 9999) ) year = 1;
      if ( month  > 17 ) month  = 1;
      if ( day    > 31 ) day    = 1;
      if ( hour   > 23 ) hour   = 0;
      if ( minute > 59 ) minute = 0;
1254
      if ( second > 59 ) second = 0;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1255

Uwe Schulzweida's avatar
Uwe Schulzweida committed
1256
1257
      vdate = cdiEncodeDate(year, month, day);
      vtime = cdiEncodeTime(hour, minute, second);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1258

1259
1260
      Warning(func, "Reset wrong date/time to %4.4d-%2.2d-%2.2d %2.2d:%2.2d:%2.2d!",
	      year, month, day, hour, minute, second);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1261
1262
    }

Uwe Schulzweida's avatar
Uwe Schulzweida committed
1263
1264
1265
1266
1267
  *date = vdate;
  *time = vtime;
}


Uwe Schulzweida's avatar
Uwe Schulzweida committed
1268
void cdiDecodeTimeval(double timevalue, TAXIS *taxis, int *date, int *time)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1269
1270
1271
1272
1273
1274
1275
1276
{
  if ( taxis->type == TAXIS_ABSOLUTE )
    splitTimevalue(timevalue, taxis->unit, date, time);
  else
    timeval2vtime(timevalue, taxis, date, time);
}


Uwe Schulzweida's avatar
Uwe Schulzweida committed
1277
double cdiEncodeTimeval(int date, int time, TAXIS *taxis)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1278
1279
1280
1281
1282
{
  double timevalue;

  if ( taxis->type == TAXIS_ABSOLUTE )
    {
1283
1284
1285
      if ( taxis->unit == TUNIT_YEAR )
	{
	  int year, month, day;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1286
	  cdiDecodeDate(date, &year, &month, &day);
1287
1288
1289
1290

	  timevalue = year;
	}
      else if ( taxis->unit == TUNIT_MONTH )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1291
	{
1292
	  int year, month, day;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1293
	  cdiDecodeDate(date, &year, &month, &day);
1294
1295
1296
1297
	  if ( day == 0 )
	    timevalue = date/100;
	  else
	    timevalue = date/100 + 0.5;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1298
1299
1300
	}
      else
	{
1301
	  int hour, minute, second;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1302
	  cdiDecodeTime(time, &hour, &minute, &second);
1303
	  if ( date < 0 )