timestamp.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491
  1. /*!
  2. * \file 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 grid3 functions by Michael Pelizzari, LMCO
  76. */
  77. #include <string.h>
  78. #include <grass/gis.h>
  79. #include <grass/glocale.h>
  80. #define RAST_MISC "cell_misc"
  81. #define VECT_MISC "dig_misc"
  82. #define GRID3 "grid3"
  83. /*!
  84. \brief Initialize timestamp structure
  85. \param ts pointer to TimeStamp structure
  86. */
  87. void G_init_timestamp(struct TimeStamp *ts)
  88. {
  89. ts->count = 0;
  90. }
  91. /*!
  92. \brief Set timestamp (single)
  93. \param ts pointer to TimeStamp structure
  94. \param dt pointer to DateTime structure (date/time to be set)
  95. */
  96. void G_set_timestamp(struct TimeStamp *ts, const DateTime * dt)
  97. {
  98. datetime_copy(&ts->dt[0], dt);
  99. ts->count = 1;
  100. }
  101. /*!
  102. \brief Set timestamp (range)
  103. \param ts pointer to TimeStamp structure
  104. \param dt1,dt2 pointer to DateTime structures
  105. */
  106. void G_set_timestamp_range(struct TimeStamp *ts,
  107. const DateTime * dt1, const DateTime * dt2)
  108. {
  109. datetime_copy(&ts->dt[0], dt1);
  110. datetime_copy(&ts->dt[1], dt2);
  111. ts->count = 2;
  112. }
  113. /*!
  114. \brief Read timestamp
  115. \param fd file descriptor
  116. \param[out] ts pointer to TimeStamp structure
  117. \return -2 EOF
  118. \return -1 on error
  119. \return 0 on success
  120. */
  121. int G__read_timestamp(FILE * fd, struct TimeStamp *ts)
  122. {
  123. char buf[1024];
  124. char comment[2];
  125. while (fgets(buf, sizeof(buf), fd)) {
  126. if (sscanf(buf, "%1s", comment) != 1 || *comment == '#')
  127. continue;
  128. return (G_scan_timestamp(ts, buf) > 0 ? 0 : -1);
  129. }
  130. return -2; /* nothing in the file */
  131. }
  132. /*!
  133. \brief Output TimeStamp structure to a file as a formatted string
  134. A handy fd might be "stdout".
  135. \param[in,out] fd file descriptor
  136. \param ts pointer to TimeStamp structure
  137. \return 0 on success
  138. \return -1 on error
  139. */
  140. int G__write_timestamp(FILE * fd, const struct TimeStamp *ts)
  141. {
  142. char buf[1024];
  143. if (G_format_timestamp(ts, buf) < 0)
  144. return -1;
  145. fprintf(fd, "%s\n", buf);
  146. return 0;
  147. }
  148. /*!
  149. \brief Create text string from TimeStamp structure
  150. Fills string *buf with info from TimeStamp structure *ts in a
  151. pretty way. The TimeStamp struct is defined in gis.h and populated
  152. with e.g. G_read_raster_timestamp().
  153. \param ts TimeStamp structure containing time info
  154. \param buf string to receive formatted timestamp
  155. \return 1 on success
  156. \return -1 error
  157. */
  158. int G_format_timestamp(const struct TimeStamp *ts, char *buf)
  159. {
  160. char temp1[128], temp2[128];
  161. *buf = 0;
  162. if (ts->count > 0) {
  163. if (datetime_format(&ts->dt[0], temp1) != 0)
  164. return -1;
  165. }
  166. if (ts->count > 1) {
  167. if (datetime_format(&ts->dt[1], temp2) != 0)
  168. return -1;
  169. }
  170. if (ts->count == 1)
  171. strcpy(buf, temp1);
  172. else if (ts->count == 2)
  173. sprintf(buf, "%s / %s", temp1, temp2);
  174. return 1;
  175. }
  176. /*!
  177. \brief Fill a TimeStamp structure from a datetime string
  178. Populate a TimeStamp structure (defined in gis.h) from a text
  179. string. Checks to make sure text string is in valid GRASS datetime
  180. format.
  181. \param ts TimeStamp structure to be populated
  182. \param buf string containing formatted time info
  183. \return 1 on success
  184. \return -1 error
  185. */
  186. int G_scan_timestamp(struct TimeStamp *ts, const char *buf)
  187. {
  188. char temp[1024], *t;
  189. const char *slash;
  190. DateTime dt1, dt2;
  191. G_init_timestamp(ts);
  192. for (slash = buf; *slash; slash++)
  193. if (*slash == '/')
  194. break;
  195. if (*slash) {
  196. t = temp;
  197. while (buf != slash)
  198. *t++ = *buf++;
  199. *t = 0;
  200. buf++;
  201. if (datetime_scan(&dt1, temp) != 0 || datetime_scan(&dt2, buf) != 0)
  202. return -1;
  203. G_set_timestamp_range(ts, &dt1, &dt2);
  204. }
  205. else {
  206. if (datetime_scan(&dt2, buf) != 0)
  207. return -1;
  208. G_set_timestamp(ts, &dt2);
  209. }
  210. return 1;
  211. }
  212. /*!
  213. \brief Copy TimeStamp into [two] Datetimes structs
  214. Use to copy the TimeStamp information into Datetimes, as the members
  215. of struct TimeStamp shouldn't be accessed directly.
  216. - count=0 means no datetimes were copied
  217. - count=1 means 1 datetime was copied into dt1
  218. - count=2 means 2 datetimes were copied
  219. \param ts source TimeStamp structure
  220. \param[out] dt1 first DateTime struct to be filled
  221. \param[out] dt2 second DateTime struct to be filled
  222. \param[out] count return code
  223. */
  224. void G_get_timestamps(const struct TimeStamp *ts,
  225. DateTime * dt1, DateTime * dt2, int *count)
  226. {
  227. *count = 0;
  228. if (ts->count > 0) {
  229. datetime_copy(dt1, &ts->dt[0]);
  230. *count = 1;
  231. }
  232. if (ts->count > 1) {
  233. datetime_copy(dt2, &ts->dt[1]);
  234. *count = 2;
  235. }
  236. }
  237. /*!
  238. \brief Write timestamp file
  239. \param maptype map type
  240. \param dir directory
  241. \param name map name
  242. \param ts pointer to TimeStamp
  243. \return 1 on success
  244. \return -1 error - can't create timestamp file
  245. \return -2 error - invalid datetime in ts
  246. */
  247. static int write_timestamp(const char *maptype, const char *dir,
  248. const char *name, const struct TimeStamp *ts)
  249. {
  250. FILE *fd;
  251. int stat;
  252. fd = G_fopen_new_misc(dir, "timestamp", name);
  253. if (fd == NULL) {
  254. G_warning(_("Unable to create timestamp file for %s map <%s@%s>"),
  255. maptype, name, G_mapset());
  256. return -1;
  257. }
  258. stat = G__write_timestamp(fd, ts);
  259. fclose(fd);
  260. if (stat == 0)
  261. return 1;
  262. G_warning(_("Invalid timestamp specified for %s map <%s@%s>"),
  263. maptype, name, G_mapset());
  264. return -2;
  265. }
  266. /*!
  267. \brief Read timestamp file
  268. \param maptype map type
  269. \param dir directory
  270. \param name map name
  271. \param mapset mapset name
  272. \param ts pointer to TimeStamp
  273. \return 0 no timestamp file
  274. \return 1 on success
  275. \return -1 error - can't open timestamp file
  276. \return -2 error - invalid datetime values in timestamp file
  277. */
  278. static int read_timestamp(const char *maptype, const char *dir,
  279. const char *name, const char *mapset,
  280. struct TimeStamp *ts)
  281. {
  282. FILE *fd;
  283. int stat;
  284. if (!G_find_file2_misc(dir, "timestamp", name, mapset))
  285. return 0;
  286. fd = G_fopen_old_misc(dir, "timestamp", name, mapset);
  287. if (fd == NULL) {
  288. G_warning(_("Unable to open timestamp file for %s map <%s@%s>"),
  289. maptype, name, mapset);
  290. return -1;
  291. }
  292. stat = G__read_timestamp(fd, ts);
  293. fclose(fd);
  294. if (stat == 0)
  295. return 1;
  296. G_warning(_("Invalid timestamp file for %s map <%s@%s>"),
  297. maptype, name, mapset);
  298. return -2;
  299. }
  300. /*!
  301. \brief Read timestamp from raster map
  302. \param name map name
  303. \param mapset mapset the map lives in
  304. \param[out] ts TimeStamp struct to populate
  305. \return 1 on success
  306. \return 0 or negative on error
  307. */
  308. int G_read_raster_timestamp(const char *name, const char *mapset,
  309. struct TimeStamp *ts)
  310. {
  311. return read_timestamp("raster", RAST_MISC, name, mapset, ts);
  312. }
  313. /*!
  314. \brief Remove timestamp from raster map
  315. Only timestamp files in current mapset can be removed.
  316. \param name map name
  317. \return 0 if no file
  318. \return 1 on success
  319. \return -1 on error
  320. */
  321. int G_remove_raster_timestamp(const char *name)
  322. {
  323. return G_remove_misc(RAST_MISC, "timestamp", name);
  324. }
  325. /*!
  326. \brief Read timestamp from vector map
  327. Is this used anymore with the new GRASS 6 vector engine???
  328. \param name map name
  329. \param mapset mapset name
  330. \param[out] ts TimeStamp struct to populate
  331. \return 1 on success
  332. \return 0 or negative on error
  333. */
  334. int G_read_vector_timestamp(const char *name, const char *mapset,
  335. struct TimeStamp *ts)
  336. {
  337. return read_timestamp("vector", VECT_MISC, name, mapset, ts);
  338. }
  339. /*!
  340. \brief Remove timestamp from vector map
  341. Is this used anymore with the new GRASS 6 vector engine???
  342. Only timestamp files in current mapset can be removed.
  343. \param name map name
  344. \return 0 if no file
  345. \return 1 on success
  346. \return -1 on failure
  347. */
  348. int G_remove_vector_timestamp(const char *name)
  349. {
  350. return G_remove_misc(VECT_MISC, "timestamp", name);
  351. }
  352. /*!
  353. \brief Read timestamp from 3D raster map
  354. \param name map name
  355. \param mapset mapset name
  356. \param[out] ts TimeStamp struct to populate
  357. \return 1 on success
  358. \return 0 or negative on error
  359. */
  360. int G_read_grid3_timestamp(const char *name, const char *mapset,
  361. struct TimeStamp *ts)
  362. {
  363. return read_timestamp("grid3", GRID3, name, mapset, ts);
  364. }
  365. /*!
  366. \brief Remove timestamp from 3D raster map
  367. Only timestamp files in current mapset can be removed.
  368. \param name map name
  369. \return 0 if no file
  370. \return 1 on success
  371. \return -1 on failure
  372. */
  373. int G_remove_grid3_timestamp(const char *name)
  374. {
  375. return G_remove_misc(GRID3, "timestamp", name);
  376. }
  377. /*!
  378. \brief Write timestamp of raster map
  379. \param name map name
  380. \param[out] ts TimeStamp struct to populate
  381. \return 1 on success
  382. \return -1 error - can't create timestamp file
  383. \return -2 error - invalid datetime in ts
  384. */
  385. int G_write_raster_timestamp(const char *name, const struct TimeStamp *ts)
  386. {
  387. return write_timestamp("raster", RAST_MISC, name, ts);
  388. }
  389. /*!
  390. \brief Write timestamp of vector map
  391. \param name map name
  392. \param[out] ts TimeStamp struct to populate
  393. \return 1 on success
  394. \return -1 error - can't create timestamp file
  395. \return -2 error - invalid datetime in ts
  396. */
  397. int G_write_vector_timestamp(const char *name, const struct TimeStamp *ts)
  398. {
  399. return write_timestamp("vector", VECT_MISC, name, ts);
  400. }
  401. /*!
  402. \brief Write timestamp of 3D raster map
  403. \param name map name
  404. \param[out] ts TimeStamp struct to populate
  405. \return 1 on success
  406. \return -1 error - can't create timestamp file
  407. \return -2 error - invalid datetime in ts
  408. */
  409. int G_write_grid3_timestamp(const char *name, const struct TimeStamp *ts)
  410. {
  411. return write_timestamp("grid3", GRID3, name, ts);
  412. }