GRASS Programmer's Manual  6.4.3(2013)-r
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Macros Pages
timestamp.c
Go to the documentation of this file.
1 /*
2  *
3  * provides DateTime functions for timestamp management:
4  *
5  * Authors: Michael Shapiro & Bill Brown, CERL
6  * grid3 functions by Michael Pelizzari, LMCO
7  *
8  * G_init_timestamp()
9  * G_set_timestamp()
10  * G_set_timestamp_range()
11  * G_format_timestamp()
12  * G_scan_timestamp()
13  * G_get_timestamps()
14  * G_read_raster_timestamp()
15  * G_remove_raster_timestamp()
16  * G_read_vector_timestamp()
17  * G_remove_vector_timestamp()
18  * G_read_grid3_timestamp()
19  * G_remove_grid3_timestamp()
20  * G_write_raster_timestamp()
21  * G_write_vector_timestamp()
22  * G_write_grid3_timestamp()
23  *
24  * COPYRIGHT: (C) 2000 by the GRASS Development Team
25  *
26  * This program is free software under the GNU General Public
27  * License (>=v2). Read the file COPYING that comes with GRASS
28  * for details.
29  *
30  *
31  * The timestamp values must use the format as described in the GRASS
32  * datetime library. The source tree for this library should have a
33  * description of the format. For convience, the formats as of Feb, 1996
34  * are reproduced here:
35  *
36  * There are two types of datetime values: absolute and relative. Absolute
37  * values specify exact dates and/or times. Relative values specify a span
38  * of time. Some examples will help clarify:
39  *
40  * Absolute
41  *
42  * The general format for absolute values is:
43  *
44  * day month year [bc] hour:minute:seconds timezone
45  *
46  * day is 1-31
47  * month is jan,feb,...,dec
48  * year is 4 digit year
49  * [bc] if present, indicates dates is BC
50  * hour is 0-23 (24 hour clock)
51  * mintue is 0-59
52  * second is 0-59.9999 (fractions of second allowed)
53  * timezone is +hhmm or -hhmm (eg, -0600)
54  *
55  * parts can be missing
56  *
57  * 1994 [bc]
58  * Jan 1994 [bc]
59  * 15 jan 1000 [bc]
60  * 15 jan 1994 [bc] 10 [+0000]
61  * 15 jan 1994 [bc] 10:00 [+0100]
62  * 15 jan 1994 [bc] 10:00:23.34 [-0500]
63  *
64  * Relative
65  *
66  * There are two types of relative datetime values, year- month and day-second.
67  *
68  * The formats are:
69  *
70  * [-] # years # months
71  * [-] # days # hours # minutes # seconds
72  *
73  * The words years, months, days, hours, minutes, seconds are literal words,
74  * and the # are the numeric values.
75  *
76  * Examples:
77  *
78  * 2 years
79  * 5 months
80  * 2 years 5 months
81  * 100 days
82  * 15 hours 25 minutes 35.34 seconds
83  * 100 days 25 minutes
84  * 1000 hours 35.34 seconds
85  *
86  * The following are illegal because it mixes year-month and day-second
87  * (because the number of days in a month or in a year vary):
88  *
89  * 3 months 15 days
90  * 3 years 10 days
91  *
92  *
93  */
94 
95 #include <string.h>
96 #include <grass/gis.h>
97 #include <grass/glocale.h>
98 
99 void G_init_timestamp(struct TimeStamp *ts)
100 {
101  ts->count = 0;
102 }
103 
104 void G_set_timestamp(struct TimeStamp *ts, const DateTime * dt)
105 {
106  datetime_copy(&ts->dt[0], dt);
107  ts->count = 1;
108 }
109 
110 void G_set_timestamp_range(struct TimeStamp *ts,
111  const DateTime * dt1, const DateTime * dt2)
112 {
113  datetime_copy(&ts->dt[0], dt1);
114  datetime_copy(&ts->dt[1], dt2);
115  ts->count = 2;
116 }
117 
118 int G__read_timestamp(FILE * fd, struct TimeStamp *ts)
119 {
120  char buf[1024];
121  char comment[2];
122 
123  while (fgets(buf, sizeof(buf), fd)) {
124  if (sscanf(buf, "%1s", comment) != 1 || *comment == '#')
125  continue;
126  return (G_scan_timestamp(ts, buf) > 0 ? 0 : -1);
127  }
128  return -2; /* nothing in the file */
129 }
130 
131 
145 int G__write_timestamp(FILE * fd, const struct TimeStamp *ts)
146 {
147  char buf[1024];
148 
149  if (G_format_timestamp(ts, buf) < 0)
150  return -1;
151  fprintf(fd, "%s\n", buf);
152  return 0;
153 }
154 
155 
171 int G_format_timestamp(const struct TimeStamp *ts, char *buf)
172 {
173  char temp1[128], temp2[128];
174 
175  *buf = 0;
176  if (ts->count > 0) {
177  if (datetime_format(&ts->dt[0], temp1) != 0)
178  return -1;
179  }
180  if (ts->count > 1) {
181  if (datetime_format(&ts->dt[1], temp2) != 0)
182  return -1;
183  }
184  if (ts->count == 1)
185  strcpy(buf, temp1);
186  else if (ts->count == 2)
187  sprintf(buf, "%s / %s", temp1, temp2);
188 
189  return 1;
190 }
191 
192 
207 int G_scan_timestamp(struct TimeStamp *ts, const char *buf)
208 {
209  char temp[1024], *t;
210  const char *slash;
211  DateTime dt1, dt2;
212 
213  G_init_timestamp(ts);
214  for (slash = buf; *slash; slash++)
215  if (*slash == '/')
216  break;
217  if (*slash) {
218  t = temp;
219  while (buf != slash)
220  *t++ = *buf++;
221  *t = 0;
222  buf++;
223  if (datetime_scan(&dt1, temp) != 0 || datetime_scan(&dt2, buf) != 0)
224  return -1;
225  G_set_timestamp_range(ts, &dt1, &dt2);
226  }
227  else {
228  if (datetime_scan(&dt2, buf) != 0)
229  return -1;
230  G_set_timestamp(ts, &dt2);
231  }
232  return 1;
233 }
234 
235 
252 int G_get_timestamps(const struct TimeStamp *ts,
253  DateTime * dt1, DateTime * dt2, int *count)
254 {
255  *count = 0;
256  if (ts->count > 0) {
257  datetime_copy(dt1, &ts->dt[0]);
258  *count = 1;
259  }
260  if (ts->count > 1) {
261  datetime_copy(dt2, &ts->dt[1]);
262  *count = 2;
263  }
264 
265  return 0;
266 }
267 
268 
269 /* write timestamp file
270  * 1 ok
271  * -1 error - can't create timestamp file
272  * -2 error - invalid datetime in ts
273  */
274 static int write_timestamp(const char *maptype, const char *dir,
275  const char *name, const struct TimeStamp *ts)
276 {
277  FILE *fd;
278  int stat;
279 
280  fd = G_fopen_new_misc(dir, "timestamp", name);
281  if (fd == NULL) {
282  G_warning(_("Can't create timestamp file for %s map %s in mapset %s"),
283  maptype, name, G_mapset());
284  return -1;
285  }
286 
287  stat = G__write_timestamp(fd, ts);
288  fclose(fd);
289  if (stat == 0)
290  return 1;
291  G_warning(_("Invalid timestamp specified for %s map %s in mapset %s"),
292  maptype, name, G_mapset());
293  return -2;
294 }
295 
296 /* read timestamp file
297  * 0 no timestamp file
298  * 1 ok
299  * -1 error - can't open timestamp file
300  * -2 error - invalid datetime values in timestamp file
301  */
302 static int read_timestamp(const char *maptype, const char *dir,
303  const char *name, const char *mapset,
304  struct TimeStamp *ts)
305 {
306  FILE *fd;
307  int stat;
308 
309  if (!G_find_file2_misc(dir, "timestamp", name, mapset))
310  return 0;
311  fd = G_fopen_old_misc(dir, "timestamp", name, mapset);
312  if (fd == NULL) {
313  G_warning(_("Can't open timestamp file for %s map %s in mapset %s"),
314  maptype, name, mapset);
315  return -1;
316  }
317 
318  stat = G__read_timestamp(fd, ts);
319  fclose(fd);
320  if (stat == 0)
321  return 1;
322  G_warning(_("Invalid timestamp file for %s map %s in mapset %s"),
323  maptype, name, mapset);
324  return -2;
325 }
326 
327 #define RAST_MISC "cell_misc"
328 #define VECT_MISC "dig_misc"
329 #define GRID3 "grid3"
330 
331 
344 int G_read_raster_timestamp(const char *name, const char *mapset,
345  struct TimeStamp *ts)
346 {
347  return read_timestamp("raster", RAST_MISC, name, mapset, ts);
348 }
349 
350 
363 int G_remove_raster_timestamp(const char *name)
364 {
365  return G_remove_misc(RAST_MISC, "timestamp", name);
366 }
367 
368 
369 
382 int G_read_vector_timestamp(const char *name, const char *mapset,
383  struct TimeStamp *ts)
384 {
385  return read_timestamp("vector", VECT_MISC, name, mapset, ts);
386 }
387 
388 
389 
404 int G_remove_vector_timestamp(const char *name)
405 {
406  return G_remove_misc(VECT_MISC, "timestamp", name);
407 }
408 
409 
421 int G_read_grid3_timestamp(const char *name, const char *mapset,
422  struct TimeStamp *ts)
423 {
424  return read_timestamp("grid3", GRID3, name, mapset, ts);
425 }
426 
427 
440 int G_remove_grid3_timestamp(const char *name)
441 {
442  return G_remove_misc(GRID3, "timestamp", name);
443 }
444 
445 
446 
459 int G_write_raster_timestamp(const char *name, const struct TimeStamp *ts)
460 {
461  return write_timestamp("raster", RAST_MISC, name, ts);
462 }
463 
464 
465 
478 int G_write_vector_timestamp(const char *name, const struct TimeStamp *ts)
479 {
480  return write_timestamp("vector", VECT_MISC, name, ts);
481 }
482 
483 
496 int G_write_grid3_timestamp(const char *name, const struct TimeStamp *ts)
497 {
498  return write_timestamp("grid3", GRID3, name, ts);
499 }