PageRenderTime 34ms CodeModel.GetById 2ms RepoModel.GetById 0ms app.codeStats 0ms

/src/rcstime.c

#
C | 170 lines | 123 code | 17 blank | 30 comment | 19 complexity | bf1ecc37d610d11ec447ac371f0e3d73 MD5 | raw file
Possible License(s): GPL-3.0
  1. /* Convert between RCS time format and POSIX and/or C formats.
  2. Copyright (C) 2010-2012 Thien-Thi Nguyen
  3. Copyright (C) 1992, 1993, 1994, 1995 Paul Eggert
  4. This file is part of GNU RCS.
  5. GNU RCS is free software: you can redistribute it and/or modify it
  6. under the terms of the GNU General Public License as published by
  7. the Free Software Foundation, either version 3 of the License, or
  8. (at your option) any later version.
  9. GNU RCS is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty
  11. of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  12. See the GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program. If not, see <http://www.gnu.org/licenses/>.
  15. */
  16. #include "base.h"
  17. #include <string.h>
  18. #include <time.h>
  19. #include <stdlib.h>
  20. #include "b-complain.h"
  21. #include "partime.h"
  22. #include "maketime.h"
  23. void
  24. time2date (time_t unixtime, char date[datesize])
  25. /* Convert Unix time to RCS format. For compatibility with older versions of
  26. RCS, dates from 1900 through 1999 are stored without the leading "19". */
  27. {
  28. register struct tm const *tm = time2tm (unixtime, BE (version) < VERSION (5));
  29. sprintf (date, "%.2d.%.2d.%.2d.%.2d.%.2d.%.2d",
  30. tm->tm_year + ((unsigned) tm->tm_year < 100 ? 0 : 1900),
  31. tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec);
  32. }
  33. static time_t
  34. str2time_checked (char const *source, time_t default_time, long default_zone)
  35. /* Like ‘str2time’, except die if an error was found. */
  36. {
  37. time_t t = str2time (source, default_time, default_zone);
  38. if (t == -1)
  39. PFATAL ("unknown date/time: %s", source);
  40. return t;
  41. }
  42. void
  43. str2date (char const *source, char target[datesize])
  44. /* Parse a free-format date in ‘source’, convert it into
  45. RCS internal format, and store the result into ‘target’. */
  46. {
  47. time2date (str2time_checked (source, BE (now),
  48. BE (zone_offset.valid)
  49. ? BE (zone_offset.seconds)
  50. : (BE (version) < VERSION (5)
  51. ? TM_LOCAL_ZONE
  52. : 0)),
  53. target);
  54. }
  55. time_t
  56. date2time (char const source[datesize])
  57. /* Convert an RCS internal format date to ‘time_t’. */
  58. {
  59. char s[datesize + zonelenmax];
  60. return str2time_checked (date2str (source, s), (time_t) 0, 0);
  61. }
  62. void
  63. zone_set (char const *s)
  64. /* Set the time zone for ‘date2str’ output. */
  65. {
  66. if ((BE (zone_offset.valid) = !!(*s)))
  67. {
  68. long zone;
  69. char const *zonetail = parzone (s, &zone);
  70. if (!zonetail || *zonetail)
  71. PERR ("%s: not a known time zone", s);
  72. else
  73. BE (zone_offset.seconds) = zone;
  74. }
  75. }
  76. char const *
  77. date2str (char const date[datesize], char datebuf[datesize + zonelenmax])
  78. /* Format a user-readable form of the RCS format ‘date’
  79. into the buffer ‘datebuf’. Return ‘datebuf’. */
  80. {
  81. register char const *p = date;
  82. while (*p++ != '.')
  83. continue;
  84. if (!BE (zone_offset.valid))
  85. sprintf (datebuf,
  86. ("19%.*s/%.2s/%.2s %.2s:%.2s:%s"
  87. + (date[2] == '.' && VERSION (5) <= BE (version) ? 0 : 2)),
  88. (int) (p - date - 1), date, p, p + 3, p + 6, p + 9, p + 12);
  89. else
  90. {
  91. char *q;
  92. struct tm t;
  93. struct tm const *z;
  94. struct tm z_stash;
  95. int non_hour, w;
  96. long zone;
  97. char c;
  98. #define MORE(field) do \
  99. { \
  100. t.field = strtol (p, &q, 10); \
  101. p = 1 + q; \
  102. } \
  103. while (0)
  104. p = date;
  105. MORE (tm_year); if ('.' != date[2])
  106. t.tm_year -= 1900;
  107. MORE (tm_mon); t.tm_mon--;
  108. MORE (tm_mday);
  109. MORE (tm_hour);
  110. MORE (tm_min);
  111. MORE (tm_sec);
  112. t.tm_wday = -1;
  113. t.tm_yday = -1;
  114. #undef MORE
  115. zone = BE (zone_offset.seconds);
  116. if (zone == TM_LOCAL_ZONE)
  117. {
  118. time_t u = tm2time (&t, false, TM_UNDEFINED), d;
  119. z = local_tm (&u, &z_stash);
  120. d = difftm (z, &t);
  121. zone = (time_t) - 1 < 0 || d < -d ? d : -(long) -d;
  122. }
  123. else
  124. {
  125. adjzone (&t, zone);
  126. z = &t;
  127. }
  128. c = '+';
  129. if (zone < 0)
  130. {
  131. zone = -zone;
  132. c = '-';
  133. }
  134. w = sprintf (datebuf, "%.2d-%.2d-%.2d %.2d:%.2d:%.2d%c%.2d",
  135. z->tm_year + 1900,
  136. z->tm_mon + 1, z->tm_mday, z->tm_hour, z->tm_min, z->tm_sec,
  137. c, (int) (zone / (60 * 60)));
  138. if ((non_hour = zone % (60 * 60)))
  139. {
  140. const char *fmt = ":%.2d";
  141. w += sprintf (datebuf + w, fmt, non_hour / 60);
  142. if ((non_hour %= 60))
  143. w += sprintf (datebuf + w, fmt, non_hour);
  144. }
  145. }
  146. return datebuf;
  147. }
  148. /* rcstime.c ends here */