GRASS 8 Programmer's Manual 8.6.0dev(2026)-56a9afeb9f
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 * minute 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 <stdio.h>
80#include <string.h>
81#include <unistd.h>
82
83#include <grass/gis.h>
85#include <grass/glocale.h>
86
87#define RAST_MISC "cell_misc"
88#define GRID3 "grid3"
89
90/*!
91 \brief Initialize timestamp structure
92
93 \param ts pointer to TimeStamp structure
94 */
96{
97 ts->count = 0;
98}
99
100/*!
101 \brief Set timestamp (single)
102
103 \param ts pointer to TimeStamp structure
104 \param dt pointer to DateTime structure (date/time to be set)
105 */
106void G_set_timestamp(struct TimeStamp *ts, const DateTime *dt)
107{
108 datetime_copy(&ts->dt[0], dt);
109 ts->count = 1;
110}
111
112/*!
113 \brief Set timestamp (range)
114
115 \param ts pointer to TimeStamp structure
116 \param dt1,dt2 pointer to DateTime structures
117 */
119 const DateTime *dt2)
120{
121 datetime_copy(&ts->dt[0], dt1);
122 datetime_copy(&ts->dt[1], dt2);
123 ts->count = 2;
124}
125
126/*!
127 \brief Read timestamp
128
129 \param fd file descriptor
130 \param[out] ts pointer to TimeStamp structure
131
132 \return -2 EOF
133 \return -1 on error
134 \return 0 on success
135 */
136int G__read_timestamp(FILE *fd, struct TimeStamp *ts)
137{
138 char buf[1024];
139 char comment[2];
140
141 while (fgets(buf, sizeof(buf), fd)) {
142 if (sscanf(buf, "%1s", comment) != 1 || *comment == '#')
143 continue;
144 return (G_scan_timestamp(ts, buf) > 0 ? 0 : -1);
145 }
146 return -2; /* nothing in the file */
147}
148
149/*!
150 \brief Output TimeStamp structure to a file as a formatted string
151
152 A handy fd might be "stdout".
153
154 \param[in,out] fd file descriptor
155 \param ts pointer to TimeStamp structure
156
157 \return 0 on success
158 \return -1 on error
159 */
160int G_write_timestamp(FILE *fd, const struct TimeStamp *ts)
161{
162 char buf[1024];
163
164 if (G_format_timestamp(ts, buf) < 0)
165 return -1;
166 fprintf(fd, "%s\n", buf);
167 return 0;
168}
169
170/*!
171 \brief Create text string from TimeStamp structure
172
173 Fills string *buf with info from TimeStamp structure *ts in a
174 pretty way. The TimeStamp struct is defined in gis.h and populated
175 with e.g. G_read_raster_timestamp().
176
177 \param ts TimeStamp structure containing time info
178 \param buf string to receive formatted timestamp
179
180 \return 1 on success
181 \return -1 error
182 */
183int G_format_timestamp(const struct TimeStamp *ts, char *buf)
184{
185 char temp1[128], temp2[128];
186
187 *buf = 0;
188 if (ts->count > 0) {
189 if (datetime_format(&ts->dt[0], temp1) != 0)
190 return -1;
191 }
192 if (ts->count > 1) {
193 if (datetime_format(&ts->dt[1], temp2) != 0)
194 return -1;
195 }
196 if (ts->count == 1)
197 strcpy(buf, temp1);
198 else if (ts->count == 2)
199 sprintf(buf, "%s / %s", temp1, temp2);
200
201 return 1;
202}
203
204/*!
205 \brief Fill a TimeStamp structure from a datetime string
206
207 Populate a TimeStamp structure (defined in gis.h) from a text
208 string. Checks to make sure text string is in valid GRASS datetime
209 format.
210
211 \param ts TimeStamp structure to be populated
212 \param buf string containing formatted time info
213
214 \return 1 on success
215 \return -1 error
216 */
217int G_scan_timestamp(struct TimeStamp *ts, const char *buf)
218{
219 char temp[1024], *t;
220 const char *slash;
222
224 for (slash = buf; *slash; slash++)
225 if (*slash == '/')
226 break;
227 if (*slash) {
228 t = temp;
229 while (buf != slash)
230 *t++ = *buf++;
231 *t = 0;
232 buf++;
233 if (datetime_scan(&dt1, temp) != 0 || datetime_scan(&dt2, buf) != 0)
234 return -1;
236 }
237 else {
238 if (datetime_scan(&dt2, buf) != 0)
239 return -1;
240 G_set_timestamp(ts, &dt2);
241 }
242 return 1;
243}
244
245/*!
246 \brief Copy TimeStamp into [two] Datetimes structs
247
248 Use to copy the TimeStamp information into Datetimes, as the members
249 of struct TimeStamp shouldn't be accessed directly.
250
251 - count=0 means no datetimes were copied
252 - count=1 means 1 datetime was copied into dt1
253 - count=2 means 2 datetimes were copied
254
255 \param ts source TimeStamp structure
256 \param[out] dt1 first DateTime struct to be filled
257 \param[out] dt2 second DateTime struct to be filled
258 \param[out] count return code
259 */
261 int *count)
262{
263 *count = 0;
264 if (ts->count > 0) {
265 datetime_copy(dt1, &ts->dt[0]);
266 *count = 1;
267 }
268 if (ts->count > 1) {
269 datetime_copy(dt2, &ts->dt[1]);
270 *count = 2;
271 }
272}
273
274/*!
275 \brief Write timestamp file
276
277 \param maptype map type
278 \param dir directory
279 \param name map name
280 \param ts pointer to TimeStamp
281
282 \return 1 on success
283 \return -1 error - can't create timestamp file
284 \return -2 error - invalid datetime in ts
285 */
286static int write_timestamp(const char *maptype, const char *dir,
287 const char *name, const struct TimeStamp *ts)
288{
289 FILE *fd;
290 int stat;
291
292 fd = G_fopen_new_misc(dir, "timestamp", name);
293 if (fd == NULL) {
294 G_warning(_("Unable to create timestamp file for %s map <%s@%s>"),
295 maptype, name, G_mapset());
296 return -1;
297 }
298
299 stat = G_write_timestamp(fd, ts);
300 fclose(fd);
301 if (stat == 0)
302 return 1;
303 G_warning(_("Invalid timestamp specified for %s map <%s@%s>"), maptype,
304 name, G_mapset());
305 return -2;
306}
307
308/*!
309 \brief Read timestamp file
310
311 \param maptype map type
312 \param dir directory
313 \param name map name
314 \param mapset mapset name
315 \param ts pointer to TimeStamp
316
317 \return 0 no timestamp file
318 \return 1 on success
319 \return -1 error - can't open timestamp file
320 \return -2 error - invalid datetime values in timestamp file
321 */
322static int read_timestamp(const char *maptype, const char *dir,
323 const char *name, const char *mapset,
324 struct TimeStamp *ts)
325{
326 FILE *fd;
327 int stat;
328
329 if (!G_find_file2_misc(dir, "timestamp", name, mapset))
330 return 0;
331 fd = G_fopen_old_misc(dir, "timestamp", name, mapset);
332 if (fd == NULL) {
333 G_warning(_("Unable to open timestamp file for %s map <%s@%s>"),
334 maptype, name, mapset);
335 return -1;
336 }
337
338 stat = G__read_timestamp(fd, ts);
339 fclose(fd);
340 if (stat == 0)
341 return 1;
342 G_warning(_("Invalid timestamp file for %s map <%s@%s>"), maptype, name,
343 mapset);
344 return -2;
345}
346
347/*!
348 \brief Check if timestamp for raster map exists
349
350 \param name map name
351 \param mapset mapset name
352
353 \return 1 on success
354 \return 0 no timestamp present
355 */
356int G_has_raster_timestamp(const char *name, const char *mapset)
357{
358 if (!G_find_file2_misc(RAST_MISC, "timestamp", name, mapset))
359 return 0;
360
361 return 1;
362}
363
364/*!
365 \brief Read timestamp from raster map
366
367 \param name map name
368 \param mapset mapset the map lives in
369 \param[out] ts TimeStamp struct to populate
370
371 \return 1 on success
372 \return 0 or negative on error
373 */
374int G_read_raster_timestamp(const char *name, const char *mapset,
375 struct TimeStamp *ts)
376{
377 return read_timestamp("raster", RAST_MISC, name, mapset, ts);
378}
379
380/*!
381 \brief Write timestamp of raster map
382
383 \param name map name
384 \param[out] ts TimeStamp struct to populate
385
386 \return 1 on success
387 \return -1 error - can't create timestamp file
388 \return -2 error - invalid datetime in ts
389
390 */
391int G_write_raster_timestamp(const char *name, const struct TimeStamp *ts)
392{
393 return write_timestamp("raster", RAST_MISC, name, ts);
394}
395
396/*!
397 \brief Remove timestamp from raster map
398
399 Only timestamp files in current mapset can be removed.
400
401 \param name map name
402
403 \return 0 if no file
404 \return 1 on success
405 \return -1 on error
406 */
408{
409 return G_remove_misc(RAST_MISC, "timestamp", name);
410}
411
412/*!
413 \brief Check if timestamp for vector map exists
414
415 \param name map name
416 \param layer The layer names, in case of NULL, layer one is assumed
417 \param mapset mapset name
418
419 \return 1 on success
420 \return 0 no timestamp present
421 */
422int G_has_vector_timestamp(const char *name, const char *layer,
423 const char *mapset)
424{
425 char dir[GPATH_MAX];
426 char path[GPATH_MAX + GNAME_MAX];
427 char ele[GNAME_MAX];
428
429 if (layer != NULL)
430 snprintf(ele, GNAME_MAX, "%s_%s", GV_TIMESTAMP_ELEMENT, layer);
431 else
433
434 snprintf(dir, GPATH_MAX, "%s/%s", GV_DIRECTORY, name);
435 G_file_name(path, dir, ele, mapset);
436
437 G_debug(1, "Check for timestamp <%s>", path);
438
439 if (access(path, R_OK) != 0)
440 return 0;
441
442 return 1;
443}
444
445/*!
446 \brief Read timestamp from vector map
447
448 \param name map name
449 \param layer The layer names, in case of NULL, layer one is assumed
450 \param mapset mapset name
451 \param[out] ts TimeStamp struct to populate
452
453 \return 1 on success
454 \return 0 no timestamp present
455 \return -1 Unable to open file
456 \return -2 invalid time stamp
457 */
458int G_read_vector_timestamp(const char *name, const char *layer,
459 const char *mapset, struct TimeStamp *ts)
460{
461 FILE *fd;
462 int stat;
463 char dir[GPATH_MAX];
464 char ele[GNAME_MAX];
465
466 /* In case no timestamp file is present return 0 */
467 if (G_has_vector_timestamp(name, layer, mapset) != 1)
468 return 0;
469
470 if (layer != NULL)
471 snprintf(ele, GNAME_MAX, "%s_%s", GV_TIMESTAMP_ELEMENT, layer);
472 else
474
475 snprintf(dir, GPATH_MAX, "%s/%s", GV_DIRECTORY, name);
476
477 G_debug(1, "Read timestamp <%s/%s>", dir, ele);
478
479 fd = G_fopen_old(dir, ele, mapset);
480
481 if (fd == NULL) {
482 G_warning(_("Unable to open timestamp file for vector map <%s@%s>"),
483 name, G_mapset());
484 return -1;
485 }
486
487 stat = G__read_timestamp(fd, ts);
488 fclose(fd);
489 if (stat == 0)
490 return 1;
491 G_warning(_("Invalid timestamp file for vector map <%s@%s>"), name, mapset);
492 return -2;
493}
494
495/*!
496 \brief Write timestamp of vector map
497
498 \param name map name
499 \param layer The layer names, in case of NULL, layer one is assumed
500 \param[out] ts TimeStamp struct to populate
501
502 \return 1 on success
503 \return -1 error - can't create timestamp file
504 \return -2 error - invalid datetime in ts
505
506 */
507int G_write_vector_timestamp(const char *name, const char *layer,
508 const struct TimeStamp *ts)
509{
510 FILE *fd;
511 int stat;
512 char dir[GPATH_MAX];
513 char ele[GNAME_MAX];
514
515 if (layer != NULL)
516 snprintf(ele, GNAME_MAX, "%s_%s", GV_TIMESTAMP_ELEMENT, layer);
517 else
519
520 snprintf(dir, GPATH_MAX, "%s/%s", GV_DIRECTORY, name);
521
522 G_debug(1, "Write timestamp <%s/%s>", dir, ele);
523
524 fd = G_fopen_new(dir, ele);
525
526 if (fd == NULL) {
527 G_warning(_("Unable to create timestamp file for vector map <%s@%s>"),
528 name, G_mapset());
529 return -1;
530 }
531
532 stat = G_write_timestamp(fd, ts);
533 fclose(fd);
534 if (stat == 0)
535 return 1;
536 G_warning(_("Invalid timestamp specified for vector map <%s@%s>"), name,
537 G_mapset());
538 return -2;
539}
540
541/*!
542 \brief Remove timestamp from vector map
543
544 Only timestamp files in current mapset can be removed.
545
546 \param name map name
547 \param layer The layer names, in case of NULL, layer one is assumed
548
549 \return 0 if no file
550 \return 1 on success
551 \return -1 on failure
552 */
553int G_remove_vector_timestamp(const char *name, const char *layer)
554{
555 char dir[GPATH_MAX];
556 char ele[GNAME_MAX];
557
558 if (layer)
559 snprintf(ele, GNAME_MAX, "%s_%s", GV_TIMESTAMP_ELEMENT, layer);
560 else
562
563 snprintf(dir, GPATH_MAX, "%s/%s", GV_DIRECTORY, name);
564 return G_remove(dir, ele);
565}
566
567/*!
568 \brief Check if timestamp for 3D raster map exists
569
570 \param name map name
571 \param mapset mapset name
572
573 \return 1 on success
574 \return 0 no timestamp present
575 */
576int G_has_raster3d_timestamp(const char *name, const char *mapset)
577{
578 if (!G_find_file2_misc(GRID3, "timestamp", name, mapset))
579 return 0;
580
581 return 1;
582}
583
584/*!
585 \brief Read timestamp from 3D raster map
586
587 \param name map name
588 \param mapset mapset name
589 \param[out] ts TimeStamp struct to populate
590
591 \return 1 on success
592 \return 0 or negative on error
593 */
594int G_read_raster3d_timestamp(const char *name, const char *mapset,
595 struct TimeStamp *ts)
596{
597 return read_timestamp("raster3d", GRID3, name, mapset, ts);
598}
599
600/*!
601 \brief Write timestamp of 3D raster map
602
603 \param name map name
604 \param[out] ts TimeStamp struct to populate
605
606 \return 1 on success
607 \return -1 error - can't create timestamp file
608 \return -2 error - invalid datetime in ts
609
610 */
611int G_write_raster3d_timestamp(const char *name, const struct TimeStamp *ts)
612{
613 return write_timestamp("raster3d", GRID3, name, ts);
614}
615
616/*!
617 \brief Remove timestamp from 3D raster map
618
619 Only timestamp files in current mapset can be removed.
620
621 \param name map name
622
623 \return 0 if no file
624 \return 1 on success
625 \return -1 on failure
626 */
628{
629 return G_remove_misc(GRID3, "timestamp", name);
630}
#define NULL
Definition ccmath.h:32
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:40
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...
void datetime_copy(DateTime *src, const DateTime *dst)
Copies the DateTime [into/from ???] src.
void G_warning(const char *,...) __attribute__((format(printf
FILE * G_fopen_new(const char *, const char *)
Open a new database file.
Definition gis/open.c:221
char * G_file_name(char *, const char *, const char *, const char *)
Builds full path names to GIS data files.
Definition file_name.c:61
FILE * G_fopen_old(const char *, const char *, const char *)
Open a database file for reading.
Definition gis/open.c:253
int G_remove(const char *, const char *)
Remove a database file.
Definition remove.c:43
int G_remove_misc(const char *, const char *, const char *)
Remove a database misc file.
Definition remove.c:64
const char * G_find_file2_misc(const char *, const char *, const char *, const char *)
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
FILE * G_fopen_old_misc(const char *, const char *, const char *, const char *)
open a database misc file for reading
Definition open_misc.c:210
FILE * G_fopen_new_misc(const char *, const char *, const char *)
open a new database misc file
Definition open_misc.c:183
int G_debug(int, const char *,...) __attribute__((format(printf
const char * G_mapset(void)
Get current mapset name.
Definition gis/mapset.c:33
#define GV_DIRECTORY
Name of vector directory.
Definition dig_defines.h:8
#define GV_TIMESTAMP_ELEMENT
Name of the timestamp file.
Definition dig_defines.h:32
#define GPATH_MAX
Definition gis.h:199
#define GNAME_MAX
Definition gis.h:196
#define _(str)
Definition glocale.h:10
int count
const char * name
Definition named_colr.c:6
#define strcpy
Definition parson.c:66
double t
Definition r_raster.c:39
DateTime dt[2]
Definition gis.h:621
int count
Definition gis.h:622
Definition path.h:15
void G_init_timestamp(struct TimeStamp *ts)
Initialize timestamp structure.
Definition timestamp.c:95
int G_read_raster_timestamp(const char *name, const char *mapset, struct TimeStamp *ts)
Read timestamp from raster map.
Definition timestamp.c:374
int G_has_raster_timestamp(const char *name, const char *mapset)
Check if timestamp for raster map exists.
Definition timestamp.c:356
int G_has_raster3d_timestamp(const char *name, const char *mapset)
Check if timestamp for 3D raster map exists.
Definition timestamp.c:576
int G_write_timestamp(FILE *fd, const struct TimeStamp *ts)
Output TimeStamp structure to a file as a formatted string.
Definition timestamp.c:160
int G_format_timestamp(const struct TimeStamp *ts, char *buf)
Create text string from TimeStamp structure.
Definition timestamp.c:183
int G_read_raster3d_timestamp(const char *name, const char *mapset, struct TimeStamp *ts)
Read timestamp from 3D raster map.
Definition timestamp.c:594
int G_remove_raster3d_timestamp(const char *name)
Remove timestamp from 3D raster map.
Definition timestamp.c:627
int G__read_timestamp(FILE *fd, struct TimeStamp *ts)
Read timestamp.
Definition timestamp.c:136
void G_set_timestamp(struct TimeStamp *ts, const DateTime *dt)
Set timestamp (single)
Definition timestamp.c:106
int G_write_raster_timestamp(const char *name, const struct TimeStamp *ts)
Write timestamp of raster map.
Definition timestamp.c:391
int G_scan_timestamp(struct TimeStamp *ts, const char *buf)
Fill a TimeStamp structure from a datetime string.
Definition timestamp.c:217
#define GRID3
Definition timestamp.c:88
#define RAST_MISC
Definition timestamp.c:87
void G_set_timestamp_range(struct TimeStamp *ts, const DateTime *dt1, const DateTime *dt2)
Set timestamp (range)
Definition timestamp.c:118
int G_has_vector_timestamp(const char *name, const char *layer, const char *mapset)
Check if timestamp for vector map exists.
Definition timestamp.c:422
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:458
int G_write_raster3d_timestamp(const char *name, const struct TimeStamp *ts)
Write timestamp of 3D raster map.
Definition timestamp.c:611
int G_write_vector_timestamp(const char *name, const char *layer, const struct TimeStamp *ts)
Write timestamp of vector map.
Definition timestamp.c:507
int G_remove_vector_timestamp(const char *name, const char *layer)
Remove timestamp from vector map.
Definition timestamp.c:553
void G_get_timestamps(const struct TimeStamp *ts, DateTime *dt1, DateTime *dt2, int *count)
Copy TimeStamp into [two] Datetimes structs.
Definition timestamp.c:260
int G_remove_raster_timestamp(const char *name)
Remove timestamp from raster map.
Definition timestamp.c:407
#define access
Definition unistd.h:7
#define R_OK
Definition unistd.h:25