taxis.c 39.4 KB
Newer Older
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1
2
3
4
#if defined (HAVE_CONFIG_H)
#  include "config.h"
#endif

5
#include <stddef.h>
Uwe Schulzweida's avatar
Uwe Schulzweida committed
6
7
8
#include <string.h>

#include "cdi.h"
9
10
#include "calendar.h"
#include "dmemory.h"
11
#include "error.h"
12
#include "taxis.h"
13
#include "cdi_cksum.h"
14
#include "cdi_int.h"
Deike Kleberg's avatar
Deike Kleberg committed
15
#include "namespace.h"
16
#include "serialize.h"
17
#include "resource_handle.h"
18
#include "resource_unpack.h"
Uwe Schulzweida's avatar
Uwe Schulzweida committed
19

20
21
static int DefaultTimeType = TAXIS_ABSOLUTE;
static int DefaultTimeUnit = TUNIT_HOUR;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
22
23


Thomas Jahns's avatar
Thomas Jahns committed
24
static const char *Timeunits[] = {
Uwe Schulzweida's avatar
Uwe Schulzweida committed
25
26
27
  "undefined",
  "seconds",
  "minutes",
Deike Kleberg's avatar
Deike Kleberg committed
28
  "quarters",
29
30
  "30minutes",
  "hours",
31
32
33
  "3hours",
  "6hours",
  "12hours",
34
35
36
  "days",
  "months",
  "years",
Uwe Schulzweida's avatar
Uwe Schulzweida committed
37
38
39
};


40
41
static int    taxisCompareP    ( void * taxisptr1, void * taxisptr2 );
static void   taxisDestroyP    ( void * taxisptr );
Thomas Jahns's avatar
Thomas Jahns committed
42
static void   taxisPrintKernel(taxis_t *taxisptr, FILE * fp);
43
static int    taxisGetPackSize ( void * taxisptr, void *context );
44
static void   taxisPack        ( void * taxisptr, void *buf, int size,
45
				 int *position, void *context );
46
static int    taxisTxCode      ( void );
47

48
49
50
const resOps taxisOps = {
  taxisCompareP,
  taxisDestroyP,
Thomas Jahns's avatar
Thomas Jahns committed
51
  (void (*)(void *, FILE *))taxisPrintKernel,
52
53
54
  taxisGetPackSize,
  taxisPack,
  taxisTxCode
55
};
56

57
#define container_of(ptr, type, member) \
Thomas Jahns's avatar
Thomas Jahns committed
58
  ((type *)(void*)((unsigned char *)ptr - offsetof(type,member)))
Uwe Schulzweida's avatar
Uwe Schulzweida committed
59

60
61
62
63
64
65
66
67
68
69
struct refcount_string
{
  int ref_count;
  char string[];
};

static char *
new_refcount_string(size_t len)
{
  struct refcount_string *container
70
    = (struct refcount_string *) Malloc(sizeof (*container) + len + 1);
71
72
73
74
75
76
77
78
79
80
81
82
  container->ref_count = 1;
  return container->string;
}

static void
delete_refcount_string(void *p)
{
  if (p)
    {
      struct refcount_string *container
        = container_of(p, struct refcount_string, string);
      if (!--(container->ref_count))
83
        Free(container);
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
    }
}

static char *
dup_refcount_string(char *p)
{
  if (p)
    {
      struct refcount_string *container
        = container_of(p, struct refcount_string, string);
      ++(container->ref_count);
    }
  return p;
}


#undef container_of
101
102
103
104

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


105
const char *tunitNamePtr(int unitID)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
106
{
107
108
  const char *name;
  int size = sizeof(Timeunits)/sizeof(*Timeunits);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
109
110
111
112
113
114
115
116
117

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

  return (name);
}

118
#if 0
119
static
Uwe Schulzweida's avatar
Uwe Schulzweida committed
120
void taxis_defaults(void)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
121
122
123
124
125
126
{
  char *timeunit;

  timeunit = getenv("TIMEUNIT");
  if ( timeunit )
    {
Deike Kleberg's avatar
Deike Kleberg committed
127
      if ( strcmp(timeunit, "minutes") == 0 )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
128
	DefaultTimeUnit = TUNIT_MINUTE;
Deike Kleberg's avatar
Deike Kleberg committed
129
      else if ( strcmp(timeunit, "hours") == 0 )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
130
	DefaultTimeUnit = TUNIT_HOUR;
131
132
133
134
135
136
      else if ( strcmp(timeunit, "3hours") == 0 )
	DefaultTimeUnit = TUNIT_3HOURS;
      else if ( strcmp(timeunit, "6hours") == 0 )
	DefaultTimeUnit = TUNIT_6HOURS;
      else if ( strcmp(timeunit, "12hours") == 0 )
	DefaultTimeUnit = TUNIT_12HOURS;
Deike Kleberg's avatar
Deike Kleberg committed
137
      else if ( strcmp(timeunit, "days") == 0 )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
138
	DefaultTimeUnit = TUNIT_DAY;
Deike Kleberg's avatar
Deike Kleberg committed
139
      else if ( strcmp(timeunit, "months") == 0 )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
140
	DefaultTimeUnit = TUNIT_MONTH;
Deike Kleberg's avatar
Deike Kleberg committed
141
      else if ( strcmp(timeunit, "years") == 0 )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
142
143
	DefaultTimeUnit = TUNIT_YEAR;
      else
144
	Warning("Unsupported TIMEUNIT %s!", timeunit);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
145
    }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
146
}
147
#endif
Uwe Schulzweida's avatar
Uwe Schulzweida committed
148

149
static
150
void taxisDefaultValue(taxis_t* taxisptr)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
151
{
152
153
154
155
156
157
158
  taxisptr->self        = CDI_UNDEFID;
  taxisptr->used        = FALSE;
  taxisptr->type        = DefaultTimeType;
  taxisptr->vdate       = 0;
  taxisptr->vtime       = 0;
  taxisptr->rdate       = CDI_UNDEFID;
  taxisptr->rtime       = 0;
159
160
  taxisptr->fdate       = CDI_UNDEFID;
  taxisptr->ftime       = 0;
161
162
163
  taxisptr->calendar    = cdiDefaultCalendar;
  taxisptr->unit        = DefaultTimeUnit;
  taxisptr->numavg      = 0;
164
  taxisptr->climatology = FALSE;
165
166
167
168
169
  taxisptr->has_bounds  = FALSE;
  taxisptr->vdate_lb    = 0;
  taxisptr->vtime_lb    = 0;
  taxisptr->vdate_ub    = 0;
  taxisptr->vtime_ub    = 0;
170
171
  taxisptr->fc_unit     = DefaultTimeUnit;
  taxisptr->fc_period   = 0;
172
173
  taxisptr->name        = NULL;
  taxisptr->longname    = NULL;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
174
}
Uwe Schulzweida's avatar
Uwe Schulzweida committed
175

176
177
static taxis_t *
taxisNewEntry(cdiResH resH)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
178
{
179
  taxis_t *taxisptr = (taxis_t*) Malloc(sizeof(taxis_t));
Uwe Schulzweida's avatar
Uwe Schulzweida committed
180

181
182
183
184
185
186
187
188
  taxisDefaultValue(taxisptr);
  if (resH == CDI_UNDEFID)
    taxisptr->self = reshPut(taxisptr, &taxisOps);
  else
    {
      taxisptr->self = resH;
      reshReplace(resH, taxisptr, &taxisOps);
    }
189
190

  return (taxisptr);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
191
192
}

193
static
194
void taxisInit (void)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
195
{
196
197
  static int taxisInitialized = 0;
  char *env;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
198

199
  if ( taxisInitialized ) return;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
200

201
  taxisInitialized = 1;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
202

203
204
  env = getenv("TAXIS_DEBUG");
  if ( env ) TAXIS_Debug = atoi(env);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
205
206
}

207
#if 0
208
209
static
void taxis_copy(taxis_t *taxisptr2, taxis_t *taxisptr1)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
210
{
211
  int taxisID2 = taxisptr2->self;
212
  memcpy(taxisptr2, taxisptr1, sizeof(taxis_t));
Uwe Schulzweida's avatar
Uwe Schulzweida committed
213
214
  taxisptr2->self = taxisID2;
}
215
#endif
Uwe Schulzweida's avatar
Uwe Schulzweida committed
216

Uwe Schulzweida's avatar
Uwe Schulzweida committed
217
/*
218
@Function  taxisCreate
219
@Title     Create a Time axis
Uwe Schulzweida's avatar
Uwe Schulzweida committed
220

221
@Prototype int taxisCreate(int taxistype)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
222
@Parameter
Uwe Schulzweida's avatar
Uwe Schulzweida committed
223
224
    @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
225
226

@Description
227
The function @func{taxisCreate} creates a Time axis.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
228
229

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

Uwe Schulzweida's avatar
Uwe Schulzweida committed
232
233
234
235
236
237
238
239
240
241
242
@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);
243
taxisDefRdate(taxisID, 19850101);
244
taxisDefRtime(taxisID, 120000);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
245
246
   ...
@EndSource
Uwe Schulzweida's avatar
Uwe Schulzweida committed
247
248
@EndFunction
*/
249
int taxisCreate(int taxistype)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
250
251
{
  if ( CDI_Debug )
252
    Message("taxistype: %d", taxistype);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
253

254
255
  taxisInit ();

256
  taxis_t *taxisptr = taxisNewEntry(CDI_UNDEFID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
257
  taxisptr->type = taxistype;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
258

259
260
  int taxisID = taxisptr->self;

Uwe Schulzweida's avatar
Uwe Schulzweida committed
261
  if ( CDI_Debug )
262
    Message("taxisID: %d", taxisID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
263
264
265
266

  return (taxisID);
}

267
void taxisDestroyKernel(taxis_t *taxisptr)
268
{
269
270
  delete_refcount_string(taxisptr->name);
  delete_refcount_string(taxisptr->longname);
271
272
}

273
274
275
276
277
278
/*
@Function  taxisDestroy
@Title     Destroy a Time axis

@Prototype void taxisDestroy(int taxisID)
@Parameter
279
    @Item  taxisID  Time axis ID, from a previous call to @func{taxisCreate}
280
281
282
283
284

@EndFunction
*/
void taxisDestroy(int taxisID)
{
285
  taxis_t *taxisptr = (taxis_t *)reshGetVal(taxisID, &taxisOps);
Thomas Jahns's avatar
Thomas Jahns committed
286
  reshRemove(taxisID, &taxisOps);
287
  taxisDestroyKernel(taxisptr);
288
  Free(taxisptr);
289
}
290

Uwe Schulzweida's avatar
Uwe Schulzweida committed
291
292

void taxisDestroyP( void * taxisptr )
293
{
294
  taxisDestroyKernel((taxis_t *)taxisptr);
295
  Free(taxisptr);
296
297
298
}


Uwe Schulzweida's avatar
Uwe Schulzweida committed
299
300
int taxisDuplicate(int taxisID1)
{
301
  taxis_t *taxisptr1 = (taxis_t *)reshGetVal(taxisID1, &taxisOps);
302
  taxis_t *taxisptr2 = taxisNewEntry(CDI_UNDEFID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
303

304
  int taxisID2 = taxisptr2->self;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
305
306

  if ( CDI_Debug )
307
    Message("taxisID2: %d", taxisID2);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
308

Uwe Schulzweida's avatar
Uwe Schulzweida committed
309
  ptaxisCopy(taxisptr2, taxisptr1);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
310
311
312
313
314
315
  return (taxisID2);
}


void taxisDefType(int taxisID, int type)
{
316
  taxis_t *taxisptr = ( taxis_t * ) reshGetVal ( taxisID, &taxisOps );
Uwe Schulzweida's avatar
Uwe Schulzweida committed
317

318
319
320
321
322
  if (taxisptr->type != type)
    {
      taxisptr->type = type;
      reshSetStatus(taxisID, &taxisOps, RESH_DESYNC_IN_USE);
    }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
323
324
325
326
327
328
329
330
}

/*
@Function  taxisDefVdate
@Title     Define the verification date

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

@Description
335
The function @func{taxisDefVdate} defines the verification date of a Time axis.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
336
337
338
339
340

@EndFunction
*/
void taxisDefVdate(int taxisID, int vdate)
{
341
  taxis_t *taxisptr = (taxis_t *)reshGetVal(taxisID, &taxisOps);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
342

343
344
345
346
347
  if (taxisptr->vdate != vdate)
    {
      taxisptr->vdate = vdate;
      reshSetStatus(taxisID, &taxisOps, RESH_DESYNC_IN_USE);
    }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
348
349
350
351
352
353
354
355
}

/*
@Function  taxisDefVtime
@Title     Define the verification time

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

@Description
360
The function @func{taxisDefVtime} defines the verification time of a Time axis.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
361
362
363
364
365

@EndFunction
*/
void taxisDefVtime(int taxisID, int vtime)
{
366
  taxis_t *taxisptr = (taxis_t *)reshGetVal(taxisID, &taxisOps);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
367

368
369
370
371
372
  if (taxisptr->vtime != vtime)
    {
      taxisptr->vtime = vtime;
      reshSetStatus(taxisID, &taxisOps, RESH_DESYNC_IN_USE);
    }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
373
374
375
376
377
378
379
380
}

/*
@Function  taxisDefRdate
@Title     Define the reference date

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

@Description
385
The function @func{taxisDefRdate} defines the reference date of a Time axis.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
386
387
388
389
390

@EndFunction
*/
void taxisDefRdate(int taxisID, int rdate)
{
391
  taxis_t *taxisptr = ( taxis_t * ) reshGetVal ( taxisID, &taxisOps );
Uwe Schulzweida's avatar
Uwe Schulzweida committed
392

393
394
395
396
397
  if (taxisptr->rdate != rdate)
    {
      taxisptr->rdate = rdate;
      reshSetStatus(taxisID, &taxisOps, RESH_DESYNC_IN_USE);
    }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
398
399
400
401
402
403
404
405
}

/*
@Function  taxisDefRtime
@Title     Define the reference time

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

@Description
410
The function @func{taxisDefRtime} defines the reference time of a Time axis.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
411
412
413
414
415

@EndFunction
*/
void taxisDefRtime(int taxisID, int rtime)
{
416
  taxis_t *taxisptr = ( taxis_t * ) reshGetVal ( taxisID, &taxisOps );
Uwe Schulzweida's avatar
Uwe Schulzweida committed
417

418
419
420
421
422
  if (taxisptr->rtime != rtime)
    {
      taxisptr->rtime = rtime;
      reshSetStatus(taxisID, &taxisOps, RESH_DESYNC_IN_USE);
    }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
423
424
}

425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
/*
@Function  taxisDefFdate
@Title     Define the forecast reference date

@Prototype void taxisDefFdate(int taxisID, int fdate)
@Parameter
    @Item  taxisID  Time axis ID, from a previous call to @fref{taxisCreate}
    @Item  fdate    Forecast reference date (YYYYMMDD)

@Description
The function @func{taxisDefFdate} defines the forecast reference date of a Time axis.

@EndFunction
*/
void taxisDefFdate(int taxisID, int fdate)
{
441
  taxis_t *taxisptr = ( taxis_t * ) reshGetVal ( taxisID, &taxisOps );
442

443
444
445
446
447
  if (taxisptr->fdate != fdate)
    {
      taxisptr->fdate = fdate;
      reshSetStatus(taxisID, &taxisOps, RESH_DESYNC_IN_USE);
    }
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
}

/*
@Function  taxisDefFtime
@Title     Define the forecast reference time

@Prototype void taxisDefFtime(int taxisID, int ftime)
@Parameter
    @Item  taxisID  Time axis ID, from a previous call to @fref{taxisCreate}
    @Item  ftime    Forecast reference time (hhmmss)

@Description
The function @func{taxisDefFtime} defines the forecast reference time of a Time axis.

@EndFunction
*/
void taxisDefFtime(int taxisID, int ftime)
{
466
  taxis_t *taxisptr = ( taxis_t * ) reshGetVal ( taxisID, &taxisOps );
467

468
469
470
471
472
  if (taxisptr->ftime != ftime)
    {
      taxisptr->ftime = ftime;
      reshSetStatus(taxisID, &taxisOps, RESH_DESYNC_IN_USE);
    }
473
474
}

Uwe Schulzweida's avatar
Uwe Schulzweida committed
475
476
477
478
479
480
/*
@Function  taxisDefCalendar
@Title     Define the calendar

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

@Description
487
The function @func{taxisDefCalendar} defines the calendar of a Time axis.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
488
489
490
491
492

@EndFunction
*/
void taxisDefCalendar(int taxisID, int calendar)
{
493
  taxis_t *taxisptr = ( taxis_t * ) reshGetVal ( taxisID, &taxisOps );
Uwe Schulzweida's avatar
Uwe Schulzweida committed
494

495
496
497
498
499
  if (taxisptr->calendar != calendar)
    {
      taxisptr->calendar = calendar;
      reshSetStatus(taxisID, &taxisOps, RESH_DESYNC_IN_USE);
    }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
500
501
502
503
504
}


void taxisDefTunit(int taxisID, int unit)
{
505
  taxis_t *taxisptr = ( taxis_t * ) reshGetVal ( taxisID, &taxisOps );
Uwe Schulzweida's avatar
Uwe Schulzweida committed
506

507
508
509
510
511
  if (taxisptr->unit != unit)
    {
      taxisptr->unit = unit;
      reshSetStatus(taxisID, &taxisOps, RESH_DESYNC_IN_USE);
    }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
512
513
}

514

515
516
void taxisDefForecastTunit(int taxisID, int unit)
{
517
  taxis_t *taxisptr = (taxis_t *)reshGetVal(taxisID, &taxisOps);
518

519
520
521
522
523
  if (taxisptr->fc_unit != unit)
    {
      taxisptr->fc_unit = unit;
      reshSetStatus(taxisID, &taxisOps, RESH_DESYNC_IN_USE);
    }
524
525
526
}


527
528
529
530
void taxisDefForecastPeriod(int taxisID, double fc_period)
{
  taxis_t *taxisptr = ( taxis_t * ) reshGetVal ( taxisID, &taxisOps );

531
  if ( IS_NOT_EQUAL(taxisptr->fc_period, fc_period) )
532
533
534
535
    {
      taxisptr->fc_period = fc_period;
      reshSetStatus(taxisID, &taxisOps, RESH_DESYNC_IN_USE);
    }
536
537
538
}


Uwe Schulzweida's avatar
Uwe Schulzweida committed
539
540
void taxisDefNumavg(int taxisID, int numavg)
{
541
  taxis_t *taxisptr = ( taxis_t * ) reshGetVal ( taxisID, &taxisOps );
Uwe Schulzweida's avatar
Uwe Schulzweida committed
542

543
544
545
546
547
  if (taxisptr->numavg != numavg)
    {
      taxisptr->numavg = numavg;
      reshSetStatus(taxisID, &taxisOps, RESH_DESYNC_IN_USE);
    }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
548
549
550
551
552
553
554
555
}

/*
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)
{
556
  taxis_t *taxisptr = (taxis_t *)reshGetVal(taxisID, &taxisOps);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
557

Uwe Schulzweida's avatar
Uwe Schulzweida committed
558
  return (taxisptr->type);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
559
560
561
}


Uwe Schulzweida's avatar
Uwe Schulzweida committed
562
563
int taxisHasBounds(int taxisID)
{
564
  taxis_t *taxisptr = (taxis_t *)reshGetVal(taxisID, &taxisOps);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
565
566
567
568
569

  return (taxisptr->has_bounds);
}


570
571
void taxisDeleteBounds(int taxisID)
{
572
  taxis_t *taxisptr = ( taxis_t * ) reshGetVal ( taxisID, &taxisOps );
573

574
575
576
577
578
  if (taxisptr->has_bounds != FALSE)
    {
      taxisptr->has_bounds = FALSE;
      reshSetStatus(taxisID, &taxisOps, RESH_DESYNC_IN_USE);
    }
579
580
581
}


Uwe Schulzweida's avatar
Uwe Schulzweida committed
582
void taxisCopyTimestep(int taxisID2, int taxisID1)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
583
{
584
585
  taxis_t *taxisptr1 = (taxis_t *)reshGetVal(taxisID1, &taxisOps),
    *taxisptr2 = (taxis_t *)reshGetVal(taxisID2, &taxisOps);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
586

587
  reshLock();
Uwe Schulzweida's avatar
Uwe Schulzweida committed
588

589
590
591
  taxisptr2->rdate = taxisptr1->rdate;
  taxisptr2->rtime = taxisptr1->rtime;

Uwe Schulzweida's avatar
Uwe Schulzweida committed
592
593
594
595
  taxisptr2->vdate = taxisptr1->vdate;
  taxisptr2->vtime = taxisptr1->vtime;

  if ( taxisptr2->has_bounds )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
596
    {
Uwe Schulzweida's avatar
Uwe Schulzweida committed
597
598
599
600
      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
601
602
    }

603
604
605
606
607
608
  taxisptr2->fdate = taxisptr1->fdate;
  taxisptr2->ftime = taxisptr1->ftime;

  taxisptr2->fc_unit   = taxisptr1->fc_unit;
  taxisptr2->fc_period = taxisptr1->fc_period;

609
610
  reshSetStatus(taxisID2, &taxisOps, RESH_DESYNC_IN_USE);
  reshUnlock();
611
}
Uwe Schulzweida's avatar
Uwe Schulzweida committed
612
613
614
615
616
617
618

/*
@Function  taxisInqVdate
@Title     Get the verification date

@Prototype int taxisInqVdate(int taxisID)
@Parameter
619
    @Item  taxisID  Time axis ID, from a previous call to @fref{taxisCreate} or @fref{vlistInqTaxis}
Uwe Schulzweida's avatar
Uwe Schulzweida committed
620
621

@Description
622
The function @func{taxisInqVdate} returns the verification date of a Time axis.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
623
624

@Result
625
@func{taxisInqVdate} returns the verification date.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
626
627
628
629
630

@EndFunction
*/
int taxisInqVdate(int taxisID)
{
631
  taxis_t *taxisptr = (taxis_t *)reshGetVal(taxisID, &taxisOps);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
632

Uwe Schulzweida's avatar
Uwe Schulzweida committed
633
  return (taxisptr->vdate);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
634
635
636
}


Uwe Schulzweida's avatar
Uwe Schulzweida committed
637
638
void taxisInqVdateBounds(int taxisID, int *vdate_lb, int *vdate_ub)
{
639
  taxis_t *taxisptr = (taxis_t *)reshGetVal(taxisID, &taxisOps);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
640
641
642
643
644
645

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


646
647
void taxisDefVdateBounds(int taxisID, int vdate_lb, int vdate_ub)
{
648
  taxis_t *taxisptr = ( taxis_t * ) reshGetVal ( taxisID, &taxisOps );
649

650
651
652
653
654
655
656
657
658
  if (taxisptr->vdate_lb != vdate_lb
      || taxisptr->vdate_ub != vdate_ub
      || taxisptr->has_bounds != TRUE)
    {
      taxisptr->vdate_lb = vdate_lb;
      taxisptr->vdate_ub = vdate_ub;
      taxisptr->has_bounds = TRUE;
      reshSetStatus(taxisID, &taxisOps, RESH_DESYNC_IN_USE);
    }
659
660
}

Uwe Schulzweida's avatar
Uwe Schulzweida committed
661
662
663
664
665
666
/*
@Function  taxisInqVtime
@Title     Get the verification time

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

@Description
670
The function @func{taxisInqVtime} returns the verification time of a Time axis.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
671
672

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

@EndFunction
*/
int taxisInqVtime(int taxisID)
{
679
  taxis_t *taxisptr = (taxis_t *)reshGetVal(taxisID, &taxisOps);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
680

Uwe Schulzweida's avatar
Uwe Schulzweida committed
681
  return (taxisptr->vtime);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
682
683
684
}


Uwe Schulzweida's avatar
Uwe Schulzweida committed
685
686
void taxisInqVtimeBounds(int taxisID, int *vtime_lb, int *vtime_ub)
{
687
  taxis_t *taxisptr = (taxis_t *)reshGetVal(taxisID, &taxisOps);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
688
689
690
691
692
693

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


694
695
void taxisDefVtimeBounds(int taxisID, int vtime_lb, int vtime_ub)
{
696
  taxis_t *taxisptr = ( taxis_t * ) reshGetVal ( taxisID, &taxisOps );
697

698
699
700
701
702
703
704
705
706
  if (taxisptr->vtime_lb != vtime_lb
      || taxisptr->vtime_ub != vtime_ub
      || taxisptr->has_bounds != TRUE)
    {
      taxisptr->vtime_lb = vtime_lb;
      taxisptr->vtime_ub = vtime_ub;
      taxisptr->has_bounds = TRUE;
      reshSetStatus(taxisID, &taxisOps, RESH_DESYNC_IN_USE);
    }
707
708
}

Uwe Schulzweida's avatar
Uwe Schulzweida committed
709
710
711
712
713
714
/*
@Function  taxisInqRdate
@Title     Get the reference date

@Prototype int taxisInqRdate(int taxisID)
@Parameter
715
    @Item  taxisID  Time axis ID, from a previous call to @fref{taxisCreate} or @fref{vlistInqTaxis}
Uwe Schulzweida's avatar
Uwe Schulzweida committed
716
717

@Description
718
The function @func{taxisInqRdate} returns the reference date of a Time axis.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
719
720

@Result
721
@func{taxisInqRdate} returns the reference date.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
722
723
724
725
726

@EndFunction
*/
int taxisInqRdate(int taxisID)
{
727
  taxis_t *taxisptr = (taxis_t *)reshGetVal(taxisID, &taxisOps);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
728

Uwe Schulzweida's avatar
Uwe Schulzweida committed
729
  if ( taxisptr->rdate == -1 )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
730
    {
Uwe Schulzweida's avatar
Uwe Schulzweida committed
731
732
      taxisptr->rdate = taxisptr->vdate;
      taxisptr->rtime = taxisptr->vtime;
733
      reshSetStatus(taxisID, &taxisOps, RESH_DESYNC_IN_USE);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
734
735
    }

Uwe Schulzweida's avatar
Uwe Schulzweida committed
736
  return (taxisptr->rdate);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
737
738
739
740
741
742
743
744
}

/*
@Function  taxisInqRtime
@Title     Get the reference time

@Prototype int taxisInqRtime(int taxisID)
@Parameter
745
    @Item  taxisID  Time axis ID, from a previous call to @fref{taxisCreate} or @fref{vlistInqTaxis}
Uwe Schulzweida's avatar
Uwe Schulzweida committed
746
747

@Description
748
The function @func{taxisInqRtime} returns the reference time of a Time axis.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
749
750

@Result
751
@func{taxisInqRtime} returns the reference time.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
752
753
754
755
756

@EndFunction
*/
int taxisInqRtime(int taxisID)
{
757
  taxis_t *taxisptr = (taxis_t *)reshGetVal(taxisID, &taxisOps);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
758

Uwe Schulzweida's avatar
Uwe Schulzweida committed
759
  if ( taxisptr->rdate == -1 )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
760
    {
Uwe Schulzweida's avatar
Uwe Schulzweida committed
761
762
      taxisptr->rdate = taxisptr->vdate;
      taxisptr->rtime = taxisptr->vtime;
763
      reshSetStatus(taxisID, &taxisOps, RESH_DESYNC_IN_USE);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
764
765
    }

Uwe Schulzweida's avatar
Uwe Schulzweida committed
766
  return (taxisptr->rtime);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
767
768
}

769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
/*
@Function  taxisInqFdate
@Title     Get the forecast reference date

@Prototype int taxisInqFdate(int taxisID)
@Parameter
    @Item  taxisID  Time axis ID, from a previous call to @fref{taxisCreate} or @fref{vlistInqTaxis}

@Description
The function @func{taxisInqFdate} returns the forecast reference date of a Time axis.

@Result
@func{taxisInqFdate} returns the forecast reference date.

@EndFunction
*/
int taxisInqFdate(int taxisID)
{
787
  taxis_t *taxisptr = (taxis_t *)reshGetVal(taxisID, &taxisOps);
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815

  if ( taxisptr->fdate == -1 )
    {
      taxisptr->fdate = taxisptr->vdate;
      taxisptr->ftime = taxisptr->vtime;
    }

  return (taxisptr->fdate);
}

/*
@Function  taxisInqFtime
@Title     Get the forecast reference time

@Prototype int taxisInqFtime(int taxisID)
@Parameter
    @Item  taxisID  Time axis ID, from a previous call to @fref{taxisCreate} or @fref{vlistInqTaxis}

@Description
The function @func{taxisInqFtime} returns the forecast reference time of a Time axis.

@Result
@func{taxisInqFtime} returns the forecast reference time.

@EndFunction
*/
int taxisInqFtime(int taxisID)
{
816
  taxis_t *taxisptr = (taxis_t *)reshGetVal(taxisID, &taxisOps);
817
818
819
820
821
822
823
824
825
826

  if ( taxisptr->fdate == -1 )
    {
      taxisptr->fdate = taxisptr->vdate;
      taxisptr->ftime = taxisptr->vtime;
    }

  return (taxisptr->ftime);
}

Uwe Schulzweida's avatar
Uwe Schulzweida committed
827
828
829
830
831
832
/*
@Function  taxisInqCalendar
@Title     Get the calendar

@Prototype int taxisInqCalendar(int taxisID)
@Parameter
833
    @Item  taxisID  Time axis ID, from a previous call to @fref{taxisCreate} or @fref{vlistInqTaxis}
Uwe Schulzweida's avatar
Uwe Schulzweida committed
834
835

@Description
836
The function @func{taxisInqCalendar} returns the calendar of a Time axis.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
837
838

@Result
839
@func{taxisInqCalendar} returns the type of the calendar,
Uwe Schulzweida's avatar
Uwe Schulzweida committed
840
one of the set of predefined CDI calendar types.
841
The valid CDI calendar types are @func{CALENDAR_STANDARD}, @func{CALENDAR_PROLEPTIC},
842
@func{CALENDAR_360DAYS}, @func{CALENDAR_365DAYS} and @func{CALENDAR_366DAYS}.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
843
844
845
846
847

@EndFunction
*/
int taxisInqCalendar(int taxisID)
{
848
  taxis_t *taxisptr = ( taxis_t * ) reshGetVal ( taxisID, &taxisOps );
Uwe Schulzweida's avatar
Uwe Schulzweida committed
849

Uwe Schulzweida's avatar
Uwe Schulzweida committed
850
  return (taxisptr->calendar);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
851
852
853
854
855
}


int taxisInqTunit(int taxisID)
{
856
  taxis_t *taxisptr = ( taxis_t * ) reshGetVal ( taxisID, &taxisOps );
Uwe Schulzweida's avatar
Uwe Schulzweida committed
857

Uwe Schulzweida's avatar
Uwe Schulzweida committed
858
  return (taxisptr->unit);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
859
860
861
}


862
863
864
865
866
867
868
869
int taxisInqForecastTunit(int taxisID)
{
  taxis_t *taxisptr = ( taxis_t * ) reshGetVal ( taxisID, &taxisOps );

  return (taxisptr->fc_unit);
}


870
871
872
873
874
875
876
877
double taxisInqForecastPeriod(int taxisID)
{
  taxis_t *taxisptr = ( taxis_t * ) reshGetVal ( taxisID, &taxisOps );

  return (taxisptr->fc_period);
}


Uwe Schulzweida's avatar
Uwe Schulzweida committed
878
879
int taxisInqNumavg(int taxisID)
{
880
  taxis_t *taxisptr = ( taxis_t * ) reshGetVal ( taxisID, &taxisOps );
Uwe Schulzweida's avatar
Uwe Schulzweida committed
881

Uwe Schulzweida's avatar
Uwe Schulzweida committed
882
  return (taxisptr->numavg);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
883
884
885
}


886
taxis_t *taxisPtr(int taxisID)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
887
{
888
  taxis_t *taxisptr = (taxis_t *)reshGetVal(taxisID, &taxisOps);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
889

Uwe Schulzweida's avatar
Uwe Schulzweida committed
890
  return (taxisptr);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
891
892
}

893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
void
ptaxisDefName(taxis_t *taxisptr, const char *name)
{
  if (name)
    {
      size_t len = strlen(name);
      delete_refcount_string(taxisptr->name);
      char *taxisname = taxisptr->name = new_refcount_string(len);
      strcpy(taxisname, name);
    }
}

void
ptaxisDefLongname(taxis_t *taxisptr, const char *longname)
{
  if (longname)
    {
      size_t len = strlen(longname);
      delete_refcount_string(taxisptr->longname);
      char *taxislongname = taxisptr->longname = new_refcount_string(len);
      strcpy(taxislongname, longname);
    }
}
Uwe Schulzweida's avatar
Uwe Schulzweida committed
916

917

Thomas Jahns's avatar
Thomas Jahns committed
918
919
static void
cdiDecodeTimevalue(int timeunit, double timevalue, int *days, int *secs)
920
921
922
{
  static int lwarn = TRUE;

923
924
925
  *days = 0;
  *secs = 0;

926
927
928
929
930
931
932
933
934
935
936
937
938
939
  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);
940
      double seconds = timevalue - *days*86400.;
Thomas Jahns's avatar
Thomas Jahns committed
941
      *secs = (int)lround(seconds);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
942
      if ( *secs < 0 ) { *days -= 1; *secs += 86400; };
943
944
945
946
947
948
949
950
951
952
953
      /*
      {
	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;
954
      double seconds = (timevalue - *days)*86400;
Thomas Jahns's avatar
Thomas Jahns committed
955
      *secs = (int)lround(seconds);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
956
      if ( *secs < 0 ) { *days -= 1; *secs += 86400; };
957
958
959
960
961
962
963
964
965
966
967
968
      /*
      {
	double cval = *days + *secs/86400.;
	if ( cval != timevalue )
	  printf("TUNIT_DAY error: %g %g %d %d\n", timevalue, cval, *days, *secs);
      }
      */
    }
  else
    {
      if ( lwarn )
	{
969
	  Warning("timeunit %s unsupported!", tunitNamePtr(timeunit));
970
971
972
973
974
	  lwarn = FALSE;
	}
    }
}

975
static
Uwe Schulzweida's avatar
Uwe Schulzweida committed
976
void cdiEncodeTimevalue(int days, int secs, int timeunit, double *timevalue)
977
978
979
980
981
982
983
{
  static int lwarn = TRUE;

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

1011
void timeval2vtime(double timevalue, taxis_t *taxis, int *vdate, int *vtime)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1012
{
1013
  int year, month, day, hour, minute, second;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1014
1015
  int rdate, rtime;
  int timeunit;
1016
1017
  int calendar;
  int julday, secofday, days, secs;
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;
1027
1028
1029

  if ( rdate == 0 && rtime == 0 && DBL_IS_EQUAL(timevalue, 0.) ) return;

Uwe Schulzweida's avatar
Uwe Schulzweida committed
1030
1031
  cdiDecodeDate(rdate, &year, &month, &day);
  cdiDecodeTime(rtime, &hour, &minute, &second);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1032

1033
1034
1035
1036
1037
1038
  if ( timeunit == TUNIT_MONTH && calendar == CALENDAR_360DAYS )
    {
      timeunit = TUNIT_DAY;
      timevalue *= 30;
    }

Uwe Schulzweida's avatar
Uwe Schulzweida committed
1039
1040
  if ( timeunit == TUNIT_MONTH || timeunit == TUNIT_YEAR )
    {
1041
1042
      int nmon, dpm;
      double fmon;
1043

1044
      if ( timeunit == TUNIT_YEAR ) timevalue *= 12;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1045

1046
1047
      nmon = (int) timevalue;
      fmon = timevalue - nmon;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1048

1049
      month += nmon;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1050

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

1054
1055
1056
      dpm = days_per_month(calendar, year, month);
      timeunit = TUNIT_DAY;
      timevalue = fmon*dpm;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1057
    }
1058

1059
  encode_caldaysec(calendar, year, month, day, hour, minute, second, &julday, &secofday);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1060

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

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

1065
  decode_caldaysec(calendar, julday, secofday, &year, &month, &day, &hour, &minute, &second);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1066

Uwe Schulzweida's avatar
Uwe Schulzweida committed
1067
1068
  *vdate = cdiEncodeDate(year, month, day);
  *vtime = cdiEncodeTime(hour, minute, second);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1069
1070
1071
}


1072
double vtime2timeval(int vdate, int vtime, taxis_t *taxis)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1073
1074
{
  int ryear, rmonth;
1075
  int year, month, day, hour, minute, second;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1076
  int rdate, rtime;
1077
  double value = 0;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1078
  int timeunit;
1079
  int timeunit0;
1080
1081
  int calendar;
  int julday1, secofday1, julday2, secofday2, days, secs;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1082
1083
1084
1085

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

1086
1087
  rdate = (*taxis).rdate;
  rtime = (*taxis).rtime;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1088
1089
1090
1091
1092
1093
  if ( rdate == -1 )
    {
      rdate  = (*taxis).vdate;
      rtime  = (*taxis).vtime;
    }

1094
1095
  if ( rdate == 0 && rtime == 0 && vdate == 0 && vtime == 0 ) return(value);

Uwe Schulzweida's avatar
Uwe Schulzweida committed
1096
1097
  cdiDecodeDate(rdate, &ryear, &rmonth, &day);
  cdiDecodeTime(rtime, &hour, &minute, &second);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1098

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

Uwe Schulzweida's avatar
Uwe Schulzweida committed
1101
1102
  cdiDecodeDate(vdate, &year, &month, &day);
  cdiDecodeTime(vtime, &hour, &minute, &second);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1103

1104
1105
1106
1107
1108
1109
1110
  timeunit0 = timeunit;

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

Uwe Schulzweida's avatar
Uwe Schulzweida committed
1111
1112
  if ( timeunit == TUNIT_MONTH || timeunit == TUNIT_YEAR )
    {
1113
1114
      int nmonth, dpm;

Uwe Schulzweida's avatar
Uwe Schulzweida committed
1115
      value = (year-ryear)*12 - rmonth + month;
1116
1117
1118
1119
1120
1121
1122

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

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

1123
1124
      dpm = days_per_month(calendar, year, month);

1125
1126
1127
1128
1129
1130
      encode_caldaysec(calendar, year, month, day, hour, minute, second, &julday2, &secofday2);

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

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

1131
      if ( timeunit == TUNIT_YEAR ) value = value/12;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1132
1133
1134
    }
  else
    {