source: trunk/lib/Date.cc @ 503

Last change on this file since 503 was 503, checked in by Peter Johansson, 14 years ago

Fixes bug in Date class related to Daylight saving time. Also fixes ticket #282 (catch exception 'directory already exists' in main)

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 4.9 KB
RevLine 
[235]1// $Id: Date.cc 503 2007-11-27 00:56:57Z peter $
2
3/*
4  Copyright (C) 2007 Peter Johansson
5
[439]6  This file is part of svndigest, http://trac.thep.lu.se/trac/svndigest
[235]7
8  svndigest is free software; you can redistribute it and/or modify it
9  under the terms of the GNU General Public License as published by
10  the Free Software Foundation; either version 2 of the License, or
11  (at your option) any later version.
12
13  svndigest is distributed in the hope that it will be useful, but
14  WITHOUT ANY WARRANTY; without even the implied warranty of
15  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16  General Public License for more details.
17
18  You should have received a copy of the GNU General Public License
19  along with this program; if not, write to the Free Software
20  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
21  02111-1307, USA.
22*/
23
24#include "Date.h"
25
26#include <algorithm>
27#include <sstream>
28#include <string>
29
30namespace theplu {
31namespace svndigest {
32
33  static const char* wdays_[7] = {
[298]34    "Sunday","Monday", "Tuesday", "Wednesday", "Thursday", "Friday", 
35    "Saturday" 
[235]36  };
37
38   
39  static const char* month_[12] = {
40    "January", "February", "March", "April", "May", "June", "July", "August", 
41    "September", "October", "November", "December"
42  }; 
43
44
45  Date::Date(void)
46  {
47    std::time(&time_);
48  }
49
50
51  Date::Date(const Date& other)
52    : time_(other.time_)
53  {
54  }
55
56
57  Date::Date(std::string str)
58  {
59    std::time(&time_);
60    svntime(str);
61  }
62
63
64  std::string Date::difftime(const Date& other) const
65  {
66    std::stringstream ss;
67    time_t t0 = std::min(seconds(), other.seconds());
68    time_t t1 = std::max(seconds(), other.seconds());
69    struct tm* last = std::gmtime(&t1);
70
71    u_int year=0;
72    while (t0<=t1) {
73      ++year;
74      --last->tm_year;
75      t1=mktime(last);
76    }
77    --year;
78    ++last->tm_year;
79    t1=mktime(last);
80    if (year) {
81      ss << year << " year";
82      if (year>1)
83        ss << "s";
84      ss << " ";
85    }
86
87    u_int month=0;
88    while (t0<=t1) {
89      ++month;
90      --last->tm_mon;
91      t1=mktime(last);
92    }
93    --month;
94    ++last->tm_mon;
95    t1=mktime(last);
96    if (month || year) {
97      ss << month << " month";
98      if (month>1 || (year && !month))
99        ss << "s";
100      ss << " and ";
101    }
102   
103
104    u_int day = (t1-t0)/24/60/60;
105    ss << day << " day";
106    if (day!=1)
107      ss << "s";
108    ss << " ";
109
110    return ss.str();
111  }
112
113
114  void Date::svntime(std::string str)
115  {
116    std::stringstream sstream(str);
[396]117    struct tm* timeinfo = std::localtime(&time_);
[503]118    size_t timezone_correction = timeinfo->tm_gmtoff;
[235]119
120    u_int year, month, day, hour, minute, second;
121    std::string tmp;
122    std::getline(sstream,tmp,'-');
123    year=atoi(tmp.c_str());
124    timeinfo->tm_year = year - 1900;
125
126    std::getline(sstream,tmp,'-');
127    month=atoi(tmp.c_str());
128    timeinfo->tm_mon = month - 1;
129
130    std::getline(sstream,tmp,'T');
131    day=atoi(tmp.c_str());
132    timeinfo->tm_mday = day;
133
134    std::getline(sstream,tmp,':');
135    hour=atoi(tmp.c_str());
136    timeinfo->tm_hour = hour;
137
138    std::getline(sstream,tmp,':');
139    minute=atoi(tmp.c_str());
140    timeinfo->tm_min = minute;
141
142    std::getline(sstream,tmp,'.');
143    second=atoi(tmp.c_str());
144    timeinfo->tm_sec = second;
145
146    time_ = mktime(timeinfo);
[503]147    time_ += timezone_correction;
[235]148  }
149
150
151  std::string Date::operator()(std::string format) const
152  {
153    std::stringstream ss;
154    struct tm* timeinfo = std::gmtime(&time_);
155    for (std::string::iterator i=format.begin(); i!=format.end(); ++i) {
156      if (*i == '%' && ++i !=format.end()) {
157        if (*i == 'a')
158          ss << std::string(wdays_[timeinfo->tm_wday]).substr(0,3);
159        else if (*i == 'A')
160          ss << wdays_[timeinfo->tm_wday];
161        else if (*i == 'b')
162          ss << std::string(month_[timeinfo->tm_mon]).substr(0,3);
163        else if (*i == 'B')
164          ss << month_[timeinfo->tm_mon];
165        else if (*i == 'd')
166          ss << timeinfo->tm_mday;
167        else if (*i == 'e') {
168          if (timeinfo->tm_mday<10)
169            ss << "0";
170          ss << timeinfo->tm_mday;
171        }
172        else if (*i == 'H') {
173          if (timeinfo->tm_hour<10)
174            ss << "0";
175          ss << timeinfo->tm_hour;
176        }
177        else if (*i == 'I') {
178          int tmp = (timeinfo->tm_hour + 11) % 12 + 1;
179          if (tmp<10)
180            ss << "0";
181          ss << tmp;
182        }
183        else if (*i == 'j')
184          ss << timeinfo->tm_yday+1;
185        else if (*i == 'm') {
[366]186          if (timeinfo->tm_mon<9)
[235]187            ss << "0";
188          ss << timeinfo->tm_mon+1;
189        }
190        else if (*i == 'M') {
191          if (timeinfo->tm_min<10)
192            ss << "0";
193          ss << timeinfo->tm_min;
194        }
195        else if (*i == 'P')
196          if (timeinfo->tm_hour<12)
197            ss << "AM";
198          else
199            ss << "PM";
200        else if (*i == 'S') {
201          if (timeinfo->tm_sec<10)
202            ss << "0";
203          ss << timeinfo->tm_sec;
204        }
205        else if (*i == 'w')
206          if (timeinfo->tm_wday==0)
207            ss << "7";
208          else
209            ss << timeinfo->tm_wday;
[274]210        else if (*i == 'y') {
211          int y(timeinfo->tm_year % 100);
212          if (y<10)
213            ss << "0";
214          ss << y;
215        }
[235]216        else if (*i == 'Y')
217          ss << timeinfo->tm_year+1900;
218        else if (*i == 'Z')
219          ss << timeinfo->tm_zone;
220        else {
221          ss << '%';
222          --i;
223        }
224      }
225      else
226        ss << *i;
227    }
228
229    return ss.str();
230  }
231
232
233  const Date& Date::operator=(const Date& rhs) 
234  {
235    time_ = rhs.time_;
236    return *this;
237  }
238
239
240}}
Note: See TracBrowser for help on using the repository browser.