GRASS GIS 8 Programmer's Manual 8.3.2(2024)-exported
Loading...
Searching...
No Matches
timestamp.c
Go to the documentation of this file.
1/*!
2 * \file lib/gis/timestamp.c
3 *
4 * \brief GIS Library - Timestamp management
5 *
6 * Provides DateTime functions for timestamp management.
7 *
8 * The timestamp values must use the format as described in the GRASS
9 * datetime library. The source tree for this library should have a
10 * description of the format. For convenience, the formats as of Feb, 1996
11 * are reproduced here:
12 *
13 * There are two types of datetime values: absolute and relative. Absolute
14 * values specify exact dates and/or times. Relative values specify a span
15 * of time. Some examples will help clarify:
16 *
17 * Absolute
18 *
19 * The general format for absolute values is:
20 *
21 * day month year [bc] hour:minute:seconds timezone
22 *
23 * day is 1-31
24 * month is jan,feb,...,dec
25 * year is 4 digit year
26 * [bc] if present, indicates dates is BC
27 * hour is 0-23 (24 hour clock)
28 * mintue is 0-59
29 * second is 0-59.9999 (fractions of second allowed)
30 * timezone is +hhmm or -hhmm (eg, -0600)
31 *
32 * parts can be missing
33 *
34 * 1994 [bc]
35 * Jan 1994 [bc]
36 * 15 jan 1000 [bc]
37 * 15 jan 1994 [bc] 10 [+0000]
38 * 15 jan 1994 [bc] 10:00 [+0100]
39 * 15 jan 1994 [bc] 10:00:23.34 [-0500]
40 *
41 * Relative
42 *
43 * There are two types of relative datetime values, year- month and day-second.
44 *
45 * The formats are:
46 *
47 * [-] # years # months
48 * [-] # days # hours # minutes # seconds
49 *
50 * The words years, months, days, hours, minutes, seconds are literal words,
51 * and the # are the numeric values.
52 *
53 * Examples:
54 *
55 * 2 years
56 * 5 months
57 * 2 years 5 months
58 * 100 days
59 * 15 hours 25 minutes 35.34 seconds
60 * 100 days 25 minutes
61 * 1000 hours 35.34 seconds
62 *
63 * The following are illegal because it mixes year-month and day-second
64 * (because the number of days in a month or in a year vary):
65 *
66 * 3 months 15 days
67 * 3 years 10 days
68 *
69 * (C) 2001-2009 by the GRASS Development Team
70 *
71 * This program is free software under the GNU General Public License
72 * (>=v2). Read the file COPYING that comes with GRASS for details.
73 *
74 * \author Michael Shapiro & Bill Brown, CERL
75 * \author raster3d functions by Michael Pelizzari, LMCO
76 * \author Soeren Gebbert, vector timestamp implementation update
77 */
78
79#include <string.h>
80#include <unistd.h>
81#include <grass/gis.h>
82#include <grass/vect/dig_defines.h>
83#include <grass/glocale.h>
84
85#define RAST_MISC "cell_misc"
86#define GRID3 "grid3"
87
88/*!
89 \brief Initialize timestamp structure
90
91 \param ts pointer to TimeStamp structure
92 */
93void G_init_timestamp(struct TimeStamp *ts)
94{
95 ts->count = 0;
96}
97
98/*!
99 \brief Set timestamp (single)
100
101 \param ts pointer to TimeStamp structure
102 \param dt pointer to DateTime structure (date/time to be set)
103 */
104void G_set_timestamp(struct TimeStamp *ts, const DateTime *dt)
105{
106 datetime_copy(&ts->dt[0], dt);
107 ts->count = 1;
108}
109
110/*!
111 \brief Set timestamp (range)
112
113 \param ts pointer to TimeStamp structure
114 \param dt1,dt2 pointer to DateTime structures
115 */
116void G_set_timestamp_range(struct TimeStamp *ts, const DateTime *dt1,
117 const DateTime *dt2)
118{
119 datetime_copy(&ts->dt[0], dt1);
120 datetime_copy(&ts->dt[1], dt2);
121 ts->count = 2;
122}
123
124/*!
125 \brief Read timestamp
126
127 \param fd file descriptor
128 \param[out] ts pointer to TimeStamp structure
129
130 \return -2 EOF
131 \return -1 on error
132 \return 0 on success
133 */
134int G__read_timestamp(FILE *fd, struct TimeStamp *ts)
135{
136 char buf[1024];
137 char comment[2];
138
139 while (fgets(buf, sizeof(buf), fd)) {
140 if (sscanf(buf, "%1s", comment) != 1 || *comment == '#')
141 continue;
142 return (G_scan_timestamp(ts, buf) > 0 ? 0 : -1);
143 }
144 return -2; /* nothing in the file */
145}
146
147/*!
148 \brief Output TimeStamp structure to a file as a formatted string
149
150 A handy fd might be "stdout".
151
152 \param[in,out] fd file descriptor
153 \param ts pointer to TimeStamp structure
154
155 \return 0 on success
156 \return -1 on error
157 */
158int G_write_timestamp(FILE *fd, const struct TimeStamp *ts)
159{
160 char buf[1024];
161
162 if (G_format_timestamp(ts, buf) < 0)
163 return -1;
164 fprintf(fd, "%s\n", buf);
165 return 0;
166}
167
168/*!
169 \brief Create text string from TimeStamp structure
170
171 Fills string *buf with info from TimeStamp structure *ts in a
172 pretty way. The TimeStamp struct is defined in gis.h and populated
173 with e.g. G_read_raster_timestamp().
174
175 \param ts TimeStamp structure containing time info
176 \param buf string to receive formatted timestamp
177
178 \return 1 on success
179 \return -1 error
180 */
181int G_format_timestamp(const struct TimeStamp *ts, char *buf)
182{
183 char temp1[128], temp2[128];
184
185 *buf = 0;
186 if (ts->count > 0) {
187 if (datetime_format(&ts->dt[0], temp1) != 0)
188 return -1;
189 }
190 if (ts->count > 1) {
191 if (datetime_format(&ts->dt[1], temp2) != 0)
192 return -1;
193 }
194 if (ts->count == 1)
195 strcpy(buf, temp1);
196 else if (ts->count == 2)
197 sprintf(buf, "%s / %s", temp1, temp2);
198
199 return 1;
200}
201
202/*!
203 \brief Fill a TimeStamp structure from a datetime string
204
205 Populate a TimeStamp structure (defined in gis.h) from a text
206 string. Checks to make sure text string is in valid GRASS datetime
207 format.
208
209 \param ts TimeStamp structure to be populated
210 \param buf string containing formatted time info
211
212 \return 1 on success
213 \return -1 error
214 */
215int G_scan_timestamp(struct TimeStamp *ts, const char *buf)
216{
217 char temp[1024], *t;
218 const char *slash;
219 DateTime dt1, dt2;
220
222 for (slash = buf; *slash; slash++)
223 if (*slash == '/')
224 break;
225 if (*slash) {
226 t = temp;
227 while (buf != slash)
228 *t++ = *buf++;
229 *t = 0;
230 buf++;
231 if (datetime_scan(&dt1, temp) != 0 || datetime_scan(&dt2, buf) != 0)
232 return -1;
233 G_set_timestamp_range(ts, &dt1, &dt2);
234 }
235 else {
236 if (datetime_scan(&dt2, buf) != 0)
237 return -1;
238 G_set_timestamp(ts, &dt2);
239 }
240 return 1;
241}
242
243/*!
244 \brief Copy TimeStamp into [two] Datetimes structs
245
246 Use to copy the TimeStamp information into Datetimes, as the members
247 of struct TimeStamp shouldn't be accessed directly.
248
249 - count=0 means no datetimes were copied
250 - count=1 means 1 datetime was copied into dt1
251 - count=2 means 2 datetimes were copied
252
253 \param ts source TimeStamp structure
254 \param[out] dt1 first DateTime struct to be filled
255 \param[out] dt2 second DateTime struct to be filled
256 \param[out] count return code
257 */
258void G_get_timestamps(const struct TimeStamp *ts, DateTime *dt1, DateTime *dt2,
259 int *count)
260{
261 *count = 0;
262 if (ts->count > 0) {
263 datetime_copy(dt1, &ts->dt[0]);
264 *count = 1;
265 }
266 if (ts->count > 1) {
267 datetime_copy(dt2, &ts->dt[1]);
268 *count = 2;
269 }
270}
271
272/*!
273 \brief Write timestamp file
274
275 \param maptype map type
276 \param dir directory
277 \param name map name
278 \param ts pointer to TimeStamp
279
280 \return 1 on success
281 \return -1 error - can't create timestamp file
282 \return -2 error - invalid datetime in ts
283 */
284static int write_timestamp(const char *maptype, const char *dir,
285 const char *name, const struct TimeStamp *ts)
286{
287 FILE *fd;
288 int stat;
289
290 fd = G_fopen_new_misc(dir, "timestamp", name);
291 if (fd == NULL) {
292 G_warning(_("Unable to create timestamp file for %s map <%s@%s>"),
293 maptype, name, G_mapset());
294 return -1;
295 }
296
297 stat = G_write_timestamp(fd, ts);
298 fclose(fd);
299 if (stat == 0)
300 return 1;
301 G_warning(_("Invalid timestamp specified for %s map <%s@%s>"), maptype,
302 name, G_mapset());
303 return -2;
304}
305
306/*!
307 \brief Read timestamp file
308
309 \param maptype map type
310 \param dir directory
311 \param name map name
312 \param mapset mapset name
313 \param ts pointer to TimeStamp
314
315 \return 0 no timestamp file
316 \return 1 on success
317 \return -1 error - can't open timestamp file
318 \return -2 error - invalid datetime values in timestamp file
319 */
320static int read_timestamp(const char *maptype, const char *dir,
321 const char *name, const char *mapset,
322 struct TimeStamp *ts)
323{
324 FILE *fd;
325 int stat;
326
327 if (!G_find_file2_misc(dir, "timestamp", name, mapset))
328 return 0;
329 fd = G_fopen_old_misc(dir, "timestamp", name, mapset);
330 if (fd == NULL) {
331 G_warning(_("Unable to open timestamp file for %s map <%s@%s>"),
332 maptype, name, mapset);
333 return -1;
334 }
335
336 stat = G__read_timestamp(fd, ts);
337 fclose(fd);
338 if (stat == 0)
339 return 1;
340 G_warning(_("Invalid timestamp file for %s map <%s@%s>"), maptype, name,
341 mapset);
342 return -2;
343}
344
345/*!
346 \brief Check if timestamp for raster map exists
347
348 \param name map name
349 \param mapset mapset name
350
351 \return 1 on success
352 \return 0 no timestamp present
353 */
354int G_has_raster_timestamp(const char *name, const char *mapset)
355{
356 if (!G_find_file2_misc(RAST_MISC, "timestamp", name, mapset))
357 return 0;
358
359 return 1;
360}
361
362/*!
363 \brief Read timestamp from raster map
364
365 \param name map name
366 \param mapset mapset the map lives in
367 \param[out] ts TimeStamp struct to populate
368
369 \return 1 on success
370 \return 0 or negative on error
371 */
372int G_read_raster_timestamp(const char *name, const char *mapset,
373 struct TimeStamp *ts)
374{
375 return read_timestamp("raster", RAST_MISC, name, mapset, ts);
376}
377
378/*!
379 \brief Write timestamp of raster map
380
381 \param name map name
382 \param[out] ts TimeStamp struct to populate
383
384 \return 1 on success
385 \return -1 error - can't create timestamp file
386 \return -2 error - invalid datetime in ts
387
388 */
389int G_write_raster_timestamp(const char *name, const struct TimeStamp *ts)
390{
391 return write_timestamp("raster", RAST_MISC, name, ts);
392}
393
394/*!
395 \brief Remove timestamp from raster map
396
397 Only timestamp files in current mapset can be removed.
398
399 \param name map name
400
401 \return 0 if no file
402 \return 1 on success
403 \return -1 on error
404 */
406{
407 return G_remove_misc(RAST_MISC, "timestamp", name);
408}
409
410/*!
411 \brief Check if timestamp for vector map exists
412
413 \param name map name
414 \param layer The layer names, in case of NULL, layer one is assumed
415 \param mapset mapset name
416
417 \return 1 on success
418 \return 0 no timestamp present
419 */
420int G_has_vector_timestamp(const char *name, const char *layer,
421 const char *mapset)
422{
423 char dir[GPATH_MAX];
424 char path[GPATH_MAX + GNAME_MAX];
425 char ele[GNAME_MAX];
426
427 if (layer != NULL)
428 G_snprintf(ele, GNAME_MAX, "%s_%s", GV_TIMESTAMP_ELEMENT, layer);
429 else
430 G_snprintf(ele, GNAME_MAX, "%s_1", GV_TIMESTAMP_ELEMENT);
431
432 G_snprintf(dir, GPATH_MAX, "%s/%s", GV_DIRECTORY, name);
433 G_file_name(path, dir, ele, mapset);
434
435 G_debug(1, "Check for timestamp <%s>", path);
436
437 if (access(path, R_OK) != 0)
438 return 0;
439
440 return 1;
441}
442
443/*!
444 \brief Read timestamp from vector map
445
446 \param name map name
447 \param layer The layer names, in case of NULL, layer one is assumed
448 \param mapset mapset name
449 \param[out] ts TimeStamp struct to populate
450
451 \return 1 on success
452 \return 0 no timestamp present
453 \return -1 Unable to open file
454 \return -2 invalid time stamp
455 */
456int G_read_vector_timestamp(const char *name, const char *layer,
457 const char *mapset, struct TimeStamp *ts)
458{
459 FILE *fd;
460 int stat;
461 char dir[GPATH_MAX];
462 char ele[GNAME_MAX];
463
464 /* In case no timestamp file is present return 0 */
465 if (G_has_vector_timestamp(name, layer, mapset) != 1)
466 return 0;
467
468 if (layer != NULL)
469 G_snprintf(ele, GNAME_MAX, "%s_%s", GV_TIMESTAMP_ELEMENT, layer);
470 else
471 G_snprintf(ele, GNAME_MAX, "%s_1", GV_TIMESTAMP_ELEMENT);
472
473 G_snprintf(dir, GPATH_MAX, "%s/%s", GV_DIRECTORY, name);
474
475 G_debug(1, "Read timestamp <%s/%s>", dir, ele);
476
477 fd = G_fopen_old(dir, ele, mapset);
478
479 if (fd == NULL) {
480 G_warning(_("Unable to open timestamp file for vector map <%s@%s>"),
481 name, G_mapset());
482 return -1;
483 }
484
485 stat = G__read_timestamp(fd, ts);
486 fclose(fd);
487 if (stat == 0)
488 return 1;
489 G_warning(_("Invalid timestamp file for vector map <%s@%s>"), name, mapset);
490 return -2;
491}
492
493/*!
494 \brief Write timestamp of vector map
495
496 \param name map name
497 \param layer The layer names, in case of NULL, layer one is assumed
498 \param[out] ts TimeStamp struct to populate
499
500 \return 1 on success
501 \return -1 error - can't create timestamp file
502 \return -2 error - invalid datetime in ts
503
504 */
505int G_write_vector_timestamp(const char *name, const char *layer,
506 const struct TimeStamp *ts)
507{
508 FILE *fd;
509 int stat;
510 char dir[GPATH_MAX];
511 char ele[GNAME_MAX];
512
513 if (layer != NULL)
514 G_snprintf(ele, GNAME_MAX, "%s_%s", GV_TIMESTAMP_ELEMENT, layer);
515 else
516 G_snprintf(ele, GNAME_MAX, "%s_1", GV_TIMESTAMP_ELEMENT);
517
518 G_snprintf(dir, GPATH_MAX, "%s/%s", GV_DIRECTORY, name);
519
520 G_debug(1, "Write timestamp <%s/%s>", dir, ele);
521
522 fd = G_fopen_new(dir, ele);
523
524 if (fd == NULL) {
525 G_warning(_("Unable to create timestamp file for vector map <%s@%s>"),
526 name, G_mapset());
527 return -1;
528 }
529
530 stat = G_write_timestamp(fd, ts);
531 fclose(fd);
532 if (stat == 0)
533 return 1;
534 G_warning(_("Invalid timestamp specified for vector map <%s@%s>"), name,
535 G_mapset());
536 return -2;
537}
538
539/*!
540 \brief Remove timestamp from vector map
541
542 Only timestamp files in current mapset can be removed.
543
544 \param name map name
545 \param layer The layer names, in case of NULL, layer one is assumed
546
547 \return 0 if no file
548 \return 1 on success
549 \return -1 on failure
550 */
551int G_remove_vector_timestamp(const char *name, const char *layer)
552{
553 char dir[GPATH_MAX];
554 char ele[GNAME_MAX];
555
556 if (layer)
557 G_snprintf(ele, GNAME_MAX, "%s_%s", GV_TIMESTAMP_ELEMENT, layer);
558 else
559 G_snprintf(ele, GNAME_MAX, "%s_1", GV_TIMESTAMP_ELEMENT);
560
561 G_snprintf(dir, GPATH_MAX, "%s/%s", GV_DIRECTORY, name);
562 return G_remove(dir, ele);
563}
564
565/*!
566 \brief Check if timestamp for 3D raster map exists
567
568 \param name map name
569 \param mapset mapset name
570
571 \return 1 on success
572 \return 0 no timestamp present
573 */
574int G_has_raster3d_timestamp(const char *name, const char *mapset)
575{
576 if (!G_find_file2_misc(GRID3, "timestamp", name, mapset))
577 return 0;
578
579 return 1;
580}
581
582/*!
583 \brief Read timestamp from 3D raster map
584
585 \param name map name
586 \param mapset mapset name
587 \param[out] ts TimeStamp struct to populate
588
589 \return 1 on success
590 \return 0 or negative on error
591 */
592int G_read_raster3d_timestamp(const char *name, const char *mapset,
593 struct TimeStamp *ts)
594{
595 return read_timestamp("raster3d", GRID3, name, mapset, ts);
596}
597
598/*!
599 \brief Write timestamp of 3D raster map
600
601 \param name map name
602 \param[out] ts TimeStamp struct to populate
603
604 \return 1 on success
605 \return -1 error - can't create timestamp file
606 \return -2 error - invalid datetime in ts
607
608 */
609int G_write_raster3d_timestamp(const char *name, const struct TimeStamp *ts)
610{
611 return write_timestamp("raster3d", GRID3, name, ts);
612}
613
614/*!
615 \brief Remove timestamp from 3D raster map
616
617 Only timestamp files in current mapset can be removed.
618
619 \param name map name
620
621 \return 0 if no file
622 \return 1 on success
623 \return -1 on failure
624 */
626{
627 return G_remove_misc(GRID3, "timestamp", name);
628}
#define NULL
Definition ccmath.h:32
void datetime_copy(DateTime *dst, const DateTime *src)
Copies the DateTime [into/from ???] src.
Definition copy.c:20
int datetime_format(const DateTime *dt, char *buf)
formats DateTime structure as a human-readable string returns 0 when successful and 'buf' is filled w...
int G_debug(int level, const char *msg,...)
Print debugging message.
Definition debug.c:66
double t
char * G_file_name(char *path, const char *element, const char *name, const char *mapset)
Builds full path names to GIS data files.
Definition file_name.c:61
const char * G_find_file2_misc(const char *dir, const char *element, const char *name, const char *mapset)
Searches for a misc file from the mapset search list or in a specified mapset. (look but don't touch)
Definition find_file.c:257
void G_warning(const char *msg,...)
Print a warning message to stderr.
Definition gis/error.c:203
FILE * G_fopen_old(const char *element, const char *name, const char *mapset)
Open a database file for reading.
Definition gis/open.c:251
FILE * G_fopen_new(const char *element, const char *name)
Open a new database file.
Definition gis/open.c:219
int count
const char * G_mapset(void)
Get current mapset name.
Definition mapset.c:33
const char * name
Definition named_colr.c:6
FILE * G_fopen_old_misc(const char *dir, const char *element, const char *name, const char *mapset)
open a database misc file for reading
Definition open_misc.c:205
FILE * G_fopen_new_misc(const char *dir, const char *element, const char *name)
open a new database misc file
Definition open_misc.c:178
int G_remove(const char *element, const char *name)
Remove a database file.
Definition remove.c:44
int G_remove_misc(const char *dir, const char *element, const char *name)
Remove a database misc file.
Definition remove.c:65
int datetime_scan(DateTime *dt, const char *buf)
Convert the ascii string into a DateTime. This determines the mode/from/to based on the string,...
Definition scan.c:41
int G_snprintf(char *str, size_t size, const char *fmt,...)
snprintf() clone.
Definition snprintf.c:42
Definition path.h:15
void G_init_timestamp(struct TimeStamp *ts)
Initialize timestamp structure.
Definition timestamp.c:93
int G_read_raster_timestamp(const char *name, const char *mapset, struct TimeStamp *ts)
Read timestamp from raster map.
Definition timestamp.c:372
int G_has_raster_timestamp(const char *name, const char *mapset)
Check if timestamp for raster map exists.
Definition timestamp.c:354
int G_has_raster3d_timestamp(const char *name, const char *mapset)
Check if timestamp for 3D raster map exists.
Definition timestamp.c:574
int G_write_timestamp(FILE *fd, const struct TimeStamp *ts)
Output TimeStamp structure to a file as a formatted string.
Definition timestamp.c:158
int G_format_timestamp(const struct TimeStamp *ts, char *buf)
Create text string from TimeStamp structure.
Definition timestamp.c:181
int G_read_raster3d_timestamp(const char *name, const char *mapset, struct TimeStamp *ts)
Read timestamp from 3D raster map.
Definition timestamp.c:592
int G_remove_raster3d_timestamp(const char *name)
Remove timestamp from 3D raster map.
Definition timestamp.c:625
int G__read_timestamp(FILE *fd, struct TimeStamp *ts)
Read timestamp.
Definition timestamp.c:134
void G_set_timestamp(struct TimeStamp *ts, const DateTime *dt)
Set timestamp (single)
Definition timestamp.c:104
int G_write_raster_timestamp(const char *name, const struct TimeStamp *ts)
Write timestamp of raster map.
Definition timestamp.c:389
int G_scan_timestamp(struct TimeStamp *ts, const char *buf)
Fill a TimeStamp structure from a datetime string.
Definition timestamp.c:215
#define GRID3
Definition timestamp.c:86
#define RAST_MISC
Definition timestamp.c:85
void G_set_timestamp_range(struct TimeStamp *ts, const DateTime *dt1, const DateTime *dt2)
Set timestamp (range)
Definition timestamp.c:116
int G_has_vector_timestamp(const char *name, const char *layer, const char *mapset)
Check if timestamp for vector map exists.
Definition timestamp.c:420
int G_read_vector_timestamp(const char *name, const char *layer, const char *mapset, struct TimeStamp *ts)
Read timestamp from vector map.
Definition timestamp.c:456
int G_write_raster3d_timestamp(const char *name, const struct TimeStamp *ts)
Write timestamp of 3D raster map.
Definition timestamp.c:609
int G_write_vector_timestamp(const char *name, const char *layer, const struct TimeStamp *ts)
Write timestamp of vector map.
Definition timestamp.c:505
int G_remove_vector_timestamp(const char *name, const char *layer)
Remove timestamp from vector map.
Definition timestamp.c:551
void G_get_timestamps(const struct TimeStamp *ts, DateTime *dt1, DateTime *dt2, int *count)
Copy TimeStamp into [two] Datetimes structs.
Definition timestamp.c:258
int G_remove_raster_timestamp(const char *name)
Remove timestamp from raster map.
Definition timestamp.c:405