grass  7.8.6
About: GRASS (Geographic Resources Analysis Support System) is a raster- and vector-based GIS, image processing system, graphics production system and spatial modeling system.
  Fossies Dox: grass-7.8.6.tar.gz  ("unofficial" and yet experimental doxygen-generated source code documentation)  

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 convience, 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*/
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*/
117 const DateTime * dt1, 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,
259 DateTime * dt1, DateTime * dt2, 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>"),
302 maptype, 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>"),
341 maptype, name, 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, const char *mapset)
421{
422 char dir[GPATH_MAX];
423 char path[GPATH_MAX + GNAME_MAX];
424 char ele[GNAME_MAX];
425
426 if(layer != NULL)
427 G_snprintf(ele, GNAME_MAX, "%s_%s", GV_TIMESTAMP_ELEMENT, layer);
428 else
430
431 G_snprintf(dir, GPATH_MAX, "%s/%s", GV_DIRECTORY, name);
432 G_file_name(path, dir, ele, mapset);
433
434 G_debug(1, "Check for timestamp <%s>", path);
435
436 if (access(path, R_OK) != 0)
437 return 0;
438
439 return 1;
440}
441
442/*!
443 \brief Read timestamp from vector map
444
445 \param name map name
446 \param layer The layer names, in case of NULL, layer one is assumed
447 \param mapset mapset name
448 \param[out] ts TimeStamp struct to populate
449
450 \return 1 on success
451 \return 0 no timestamp present
452 \return -1 Unable to open file
453 \return -2 invalid time stamp
454*/
455int G_read_vector_timestamp(const char *name, const char *layer,
456 const char *mapset, struct TimeStamp *ts)
457{
458 FILE *fd;
459 int stat;
460 char dir[GPATH_MAX];
461 char ele[GNAME_MAX];
462
463 /* In case no timestamp file is present return 0 */
464 if (G_has_vector_timestamp(name, layer, mapset) != 1)
465 return 0;
466
467 if(layer != NULL)
468 G_snprintf(ele, GNAME_MAX, "%s_%s", GV_TIMESTAMP_ELEMENT, layer);
469 else
471
472 G_snprintf(dir, GPATH_MAX, "%s/%s", GV_DIRECTORY, name);
473
474 G_debug(1, "Read timestamp <%s/%s>", dir, ele);
475
476 fd = G_fopen_old(dir, ele, mapset);
477
478 if (fd == NULL) {
479 G_warning(_("Unable to open timestamp file for vector map <%s@%s>"),
480 name, G_mapset());
481 return -1;
482 }
483
484 stat = G__read_timestamp(fd, ts);
485 fclose(fd);
486 if (stat == 0)
487 return 1;
488 G_warning(_("Invalid timestamp file for vector map <%s@%s>"),
489 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, const struct TimeStamp *ts)
506{
507 FILE *fd;
508 int stat;
509 char dir[GPATH_MAX];
510 char ele[GNAME_MAX];
511
512 if(layer != NULL)
513 G_snprintf(ele, GNAME_MAX, "%s_%s", GV_TIMESTAMP_ELEMENT, layer);
514 else
516
517 G_snprintf(dir, GPATH_MAX, "%s/%s", GV_DIRECTORY, name);
518
519 G_debug(1, "Write timestamp <%s/%s>", dir, ele);
520
521 fd = G_fopen_new(dir, ele);
522
523 if (fd == NULL) {
524 G_warning(_("Unable to create timestamp file for vector map <%s@%s>"),
525 name, G_mapset());
526 return -1;
527 }
528
529 stat = G_write_timestamp(fd, ts);
530 fclose(fd);
531 if (stat == 0)
532 return 1;
533 G_warning(_("Invalid timestamp specified for vector map <%s@%s>"),
534 name, G_mapset());
535 return -2;
536}
537
538/*!
539 \brief Remove timestamp from vector map
540
541 Only timestamp files in current mapset can be removed.
542
543 \param name map name
544 \param layer The layer names, in case of NULL, layer one is assumed
545
546 \return 0 if no file
547 \return 1 on success
548 \return -1 on failure
549*/
550int G_remove_vector_timestamp(const char *name, const char *layer)
551{
552 char dir[GPATH_MAX];
553 char ele[GNAME_MAX];
554
555 if(layer)
556 G_snprintf(ele, GNAME_MAX, "%s_%s", GV_TIMESTAMP_ELEMENT, layer);
557 else
559
560 G_snprintf(dir, GPATH_MAX, "%s/%s", GV_DIRECTORY, name);
561 return G_remove(dir, ele);
562}
563
564/*!
565 \brief Check if timestamp for 3D raster map exists
566
567 \param name map name
568 \param mapset mapset name
569
570 \return 1 on success
571 \return 0 no timestamp present
572*/
573int G_has_raster3d_timestamp(const char *name, const char *mapset)
574{
575 if (!G_find_file2_misc(GRID3, "timestamp", name, mapset))
576 return 0;
577
578 return 1;
579}
580
581/*!
582 \brief Read timestamp from 3D raster map
583
584 \param name map name
585 \param mapset mapset name
586 \param[out] ts TimeStamp struct to populate
587
588 \return 1 on success
589 \return 0 or negative on error
590*/
591int G_read_raster3d_timestamp(const char *name, const char *mapset,
592 struct TimeStamp *ts)
593{
594 return read_timestamp("raster3d", GRID3, name, mapset, ts);
595}
596
597/*!
598 \brief Write timestamp of 3D raster map
599
600 \param name map name
601 \param[out] ts TimeStamp struct to populate
602
603 \return 1 on success
604 \return -1 error - can't create timestamp file
605 \return -2 error - invalid datetime in ts
606
607 */
608int G_write_raster3d_timestamp(const char *name, const struct TimeStamp *ts)
609{
610 return write_timestamp("raster3d", GRID3, name, ts);
611}
612
613/*!
614 \brief Remove timestamp from 3D raster map
615
616 Only timestamp files in current mapset can be removed.
617
618 \param name map name
619
620 \return 0 if no file
621 \return 1 on success
622 \return -1 on failure
623*/
625{
626 return G_remove_misc(GRID3, "timestamp", name);
627}
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...
Definition: format.c:28
static char ts
Definition: datetime.c:20
int G_debug(int level, const char *msg,...)
Print debugging message.
Definition: debug.c:65
#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 R_OK
Definition: dirent.c:20
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:38
const char * G_find_file2_misc(const char *dir, const char *element, const char *name, const char *mapset)
Searches for a file from the mapset search list or in a specified mapset. (look but don't touch)
Definition: find_file.c:267
void G_warning(const char *msg,...)
Print a warning message to stderr.
Definition: error.c:204
const char * G_mapset(void)
Get current mapset name.
Definition: mapset.c:33
FILE * G_fopen_old(const char *element, const char *name, const char *mapset)
Open a database file for reading.
Definition: open.c:253
FILE * G_fopen_new(const char *element, const char *name)
Open a new database file.
Definition: open.c:220
#define GPATH_MAX
Definition: gis.h:170
#define GNAME_MAX
Definition: gis.h:167
#define _(str)
Definition: glocale.h:13
int count
const char * name
Definition: named_colr.c:7
FILE * G_fopen_old_misc(const char *dir, const char *element, const char *name, const char *mapset)
open a database file for reading
Definition: open_misc.c:210
FILE * G_fopen_new_misc(const char *dir, const char *element, const char *name)
open a new database file
Definition: open_misc.c:182
double t
Definition: r_raster.c:39
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:43
int G_snprintf(char *str, size_t size, const char *fmt,...)
snprintf() clone.
Definition: snprintf.c:43
Definition: gis.h:589
Definition: path.h:16
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:573
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:591
int G_remove_raster3d_timestamp(const char *name)
Remove timestamp from 3D raster map.
Definition: timestamp.c:624
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
static int write_timestamp(const char *maptype, const char *dir, const char *name, const struct TimeStamp *ts)
Write timestamp file.
Definition: timestamp.c:284
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:455
static int read_timestamp(const char *maptype, const char *dir, const char *name, const char *mapset, struct TimeStamp *ts)
Read timestamp file.
Definition: timestamp.c:320
int G_write_raster3d_timestamp(const char *name, const struct TimeStamp *ts)
Write timestamp of 3D raster map.
Definition: timestamp.c:608
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:550
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