timestamp.c 11 KB

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