1a070cf53SStephan Aßmus /*
229e8fa59SJohn Scipione * Copyright 2007-2010 Haiku, Inc. All rights reserved.
3a070cf53SStephan Aßmus * Distributed under the terms of the MIT License.
4a070cf53SStephan Aßmus *
5a070cf53SStephan Aßmus * Authors:
629e8fa59SJohn Scipione * Stephan Aßmus, superstippi@gmx.de
729e8fa59SJohn Scipione * Julun, host.haiku@gmx.de
8a070cf53SStephan Aßmus */
9a070cf53SStephan Aßmus
10a070cf53SStephan Aßmus #include "DateTime.h"
11a070cf53SStephan Aßmus
12a070cf53SStephan Aßmus
13a070cf53SStephan Aßmus #include <time.h>
14a070cf53SStephan Aßmus #include <sys/time.h>
15a070cf53SStephan Aßmus
16*ffd9d565SAdrien Destugues #include <DateFormat.h>
17*ffd9d565SAdrien Destugues #include <Locale.h>
18*ffd9d565SAdrien Destugues #include <LocaleRoster.h>
19a070cf53SStephan Aßmus #include <Message.h>
20a070cf53SStephan Aßmus
21a070cf53SStephan Aßmus
22a070cf53SStephan Aßmus namespace BPrivate {
23a070cf53SStephan Aßmus
24a070cf53SStephan Aßmus const int32 kSecondsPerMinute = 60;
25a070cf53SStephan Aßmus
26a070cf53SStephan Aßmus const int32 kHoursPerDay = 24;
27a070cf53SStephan Aßmus const int32 kMinutesPerDay = 1440;
28a070cf53SStephan Aßmus const int32 kSecondsPerDay = 86400;
29a070cf53SStephan Aßmus const int32 kMillisecondsPerDay = 86400000;
30a070cf53SStephan Aßmus
31a070cf53SStephan Aßmus const bigtime_t kMicrosecondsPerSecond = 1000000LL;
32a070cf53SStephan Aßmus const bigtime_t kMicrosecondsPerMinute = 60000000LL;
33a070cf53SStephan Aßmus const bigtime_t kMicrosecondsPerHour = 3600000000LL;
34a070cf53SStephan Aßmus const bigtime_t kMicrosecondsPerDay = 86400000000LL;
35a070cf53SStephan Aßmus
36a070cf53SStephan Aßmus
37a070cf53SStephan Aßmus /*!
38a070cf53SStephan Aßmus Constructs a new BTime object. Asked for its time representation, it will
39a070cf53SStephan Aßmus return 0 for Hour(), Minute(), Second() etc. This can represent midnight,
40a070cf53SStephan Aßmus but be aware IsValid() will return false.
41a070cf53SStephan Aßmus */
BTime()42a070cf53SStephan Aßmus BTime::BTime()
43bbba047cSStephan Aßmus :
44bbba047cSStephan Aßmus fMicroseconds(-1)
45bbba047cSStephan Aßmus {
46bbba047cSStephan Aßmus }
47bbba047cSStephan Aßmus
48bbba047cSStephan Aßmus
49bbba047cSStephan Aßmus /*!
50bbba047cSStephan Aßmus Constructs a new BTime object as a copy of \c other.
51bbba047cSStephan Aßmus */
BTime(const BTime & other)52bbba047cSStephan Aßmus BTime::BTime(const BTime& other)
53bbba047cSStephan Aßmus :
54bbba047cSStephan Aßmus fMicroseconds(other.fMicroseconds)
55a070cf53SStephan Aßmus {
56a070cf53SStephan Aßmus }
57a070cf53SStephan Aßmus
58a070cf53SStephan Aßmus
59a070cf53SStephan Aßmus /*!
60a070cf53SStephan Aßmus Constructs a BTime object with \c hour \c minute, \c second, \c microsecond.
61a070cf53SStephan Aßmus
62a070cf53SStephan Aßmus \c hour must be between 0 and 23, \c minute and \c second must be between
63a070cf53SStephan Aßmus 0 and 59 and \c microsecond should be in the range of 0 and 999999. If the
64a070cf53SStephan Aßmus specified time is invalid, the time is not set and IsValid() returns false.
65a070cf53SStephan Aßmus */
BTime(int32 hour,int32 minute,int32 second,int32 microsecond)66a070cf53SStephan Aßmus BTime::BTime(int32 hour, int32 minute, int32 second, int32 microsecond)
67bbba047cSStephan Aßmus :
68bbba047cSStephan Aßmus fMicroseconds(-1)
69a070cf53SStephan Aßmus {
70a070cf53SStephan Aßmus _SetTime(hour, minute, second, microsecond);
71a070cf53SStephan Aßmus }
72a070cf53SStephan Aßmus
73a070cf53SStephan Aßmus
74a070cf53SStephan Aßmus /*!
75a070cf53SStephan Aßmus Constructs a new BTime object from the provided BMessage archive.
76a070cf53SStephan Aßmus */
BTime(const BMessage * archive)77a070cf53SStephan Aßmus BTime::BTime(const BMessage* archive)
78bbba047cSStephan Aßmus :
79bbba047cSStephan Aßmus fMicroseconds(-1)
80a070cf53SStephan Aßmus {
81a070cf53SStephan Aßmus if (archive == NULL)
82a070cf53SStephan Aßmus return;
83daf3c505SJérôme Duval archive->FindInt64("microseconds", &fMicroseconds);
84a070cf53SStephan Aßmus }
85a070cf53SStephan Aßmus
86a070cf53SStephan Aßmus
87a070cf53SStephan Aßmus /*!
88a070cf53SStephan Aßmus Empty destructor.
89a070cf53SStephan Aßmus */
~BTime()90a070cf53SStephan Aßmus BTime::~BTime()
91a070cf53SStephan Aßmus {
92a070cf53SStephan Aßmus }
93a070cf53SStephan Aßmus
94a070cf53SStephan Aßmus
95a070cf53SStephan Aßmus /*!
96a070cf53SStephan Aßmus Archives the BTime object into the provided BMessage object.
97a070cf53SStephan Aßmus @returns \c B_OK if all went well.
98a070cf53SStephan Aßmus \c B_BAD_VALUE, if the message is \c NULL.
99a070cf53SStephan Aßmus \c other error codes, depending on failure to append
100a070cf53SStephan Aßmus fields to the message.
101a070cf53SStephan Aßmus */
102a070cf53SStephan Aßmus status_t
Archive(BMessage * into) const103a070cf53SStephan Aßmus BTime::Archive(BMessage* into) const
104a070cf53SStephan Aßmus {
105a070cf53SStephan Aßmus if (into == NULL)
106a070cf53SStephan Aßmus return B_BAD_VALUE;
107daf3c505SJérôme Duval return into->AddInt64("microseconds", fMicroseconds);
108a070cf53SStephan Aßmus }
109a070cf53SStephan Aßmus
110a070cf53SStephan Aßmus
111a070cf53SStephan Aßmus /*!
112a070cf53SStephan Aßmus Returns true if the time is valid, otherwise false. A valid time can be
113a070cf53SStephan Aßmus BTime(23, 59, 59, 999999) while BTime(24, 00, 01) would be invalid.
114a070cf53SStephan Aßmus */
115a070cf53SStephan Aßmus bool
IsValid() const116a070cf53SStephan Aßmus BTime::IsValid() const
117a070cf53SStephan Aßmus {
118a070cf53SStephan Aßmus return fMicroseconds > -1 && fMicroseconds < kMicrosecondsPerDay;
119a070cf53SStephan Aßmus }
120a070cf53SStephan Aßmus
121a070cf53SStephan Aßmus
122a070cf53SStephan Aßmus /*!
123a070cf53SStephan Aßmus This is an overloaded member function, provided for convenience.
124a070cf53SStephan Aßmus */
125daf3c505SJérôme Duval /*static*/ bool
IsValid(const BTime & time)126daf3c505SJérôme Duval BTime::IsValid(const BTime& time)
127a070cf53SStephan Aßmus {
128daf3c505SJérôme Duval return time.IsValid();
129a070cf53SStephan Aßmus }
130a070cf53SStephan Aßmus
131a070cf53SStephan Aßmus
132a070cf53SStephan Aßmus /*!
133a070cf53SStephan Aßmus This is an overloaded member function, provided for convenience.
134a070cf53SStephan Aßmus */
135daf3c505SJérôme Duval /*static*/ bool
IsValid(int32 hour,int32 minute,int32 second,int32 microsecond)136daf3c505SJérôme Duval BTime::IsValid(int32 hour, int32 minute, int32 second, int32 microsecond)
137a070cf53SStephan Aßmus {
138a070cf53SStephan Aßmus return BTime(hour, minute, second, microsecond).IsValid();
139a070cf53SStephan Aßmus }
140a070cf53SStephan Aßmus
141a070cf53SStephan Aßmus
142a070cf53SStephan Aßmus /*!
143a070cf53SStephan Aßmus Returns the current time as reported by the system depending on the given
144a070cf53SStephan Aßmus time_type \c type.
145a070cf53SStephan Aßmus */
146a070cf53SStephan Aßmus BTime
CurrentTime(time_type type)147a070cf53SStephan Aßmus BTime::CurrentTime(time_type type)
148a070cf53SStephan Aßmus {
149a070cf53SStephan Aßmus struct timeval tv;
150a070cf53SStephan Aßmus if (gettimeofday(&tv, NULL) != 0) {
151a070cf53SStephan Aßmus // gettimeofday failed?
152a070cf53SStephan Aßmus time(&tv.tv_sec);
153a070cf53SStephan Aßmus }
154a070cf53SStephan Aßmus
155a070cf53SStephan Aßmus struct tm result;
156a070cf53SStephan Aßmus struct tm* timeinfo;
157a070cf53SStephan Aßmus if (type == B_GMT_TIME)
158a070cf53SStephan Aßmus timeinfo = gmtime_r(&tv.tv_sec, &result);
159a070cf53SStephan Aßmus else
160a070cf53SStephan Aßmus timeinfo = localtime_r(&tv.tv_sec, &result);
161a070cf53SStephan Aßmus
162559cf371SOliver Tappe if (timeinfo == NULL)
163559cf371SOliver Tappe return BTime();
164559cf371SOliver Tappe
165a070cf53SStephan Aßmus int32 sec = timeinfo->tm_sec;
166a070cf53SStephan Aßmus return BTime(timeinfo->tm_hour, timeinfo->tm_min, (sec > 59) ? 59 : sec,
167a070cf53SStephan Aßmus tv.tv_usec);
168a070cf53SStephan Aßmus }
169a070cf53SStephan Aßmus
170a070cf53SStephan Aßmus
171a070cf53SStephan Aßmus /*!
172a070cf53SStephan Aßmus Returns a copy of the current BTime object.
173a070cf53SStephan Aßmus */
174a070cf53SStephan Aßmus BTime
Time() const175a070cf53SStephan Aßmus BTime::Time() const
176a070cf53SStephan Aßmus {
177a070cf53SStephan Aßmus return *this;
178a070cf53SStephan Aßmus }
179a070cf53SStephan Aßmus
180a070cf53SStephan Aßmus
181a070cf53SStephan Aßmus /*!
182a070cf53SStephan Aßmus This is an overloaded member function, provided for convenience. Set the
183a070cf53SStephan Aßmus current BTime object to the passed BTime \c time object.
184a070cf53SStephan Aßmus */
185a070cf53SStephan Aßmus bool
SetTime(const BTime & time)186a070cf53SStephan Aßmus BTime::SetTime(const BTime& time)
187a070cf53SStephan Aßmus {
188a070cf53SStephan Aßmus fMicroseconds = time.fMicroseconds;
189a070cf53SStephan Aßmus return IsValid();
190a070cf53SStephan Aßmus }
191a070cf53SStephan Aßmus
192a070cf53SStephan Aßmus
193a070cf53SStephan Aßmus /*!
194a070cf53SStephan Aßmus Set the time to \c hour \c minute, \c second and \c microsecond.
195a070cf53SStephan Aßmus
196a070cf53SStephan Aßmus \c hour must be between 0 and 23, \c minute and \c second must be between
197a070cf53SStephan Aßmus 0 and 59 and \c microsecond should be in the range of 0 and 999999. Returns
198a070cf53SStephan Aßmus true if the time is valid; otherwise false. If the specified time is
199a070cf53SStephan Aßmus invalid, the time is not set and the function returns false.
200a070cf53SStephan Aßmus */
201a070cf53SStephan Aßmus bool
SetTime(int32 hour,int32 minute,int32 second,int32 microsecond)202a070cf53SStephan Aßmus BTime::SetTime(int32 hour, int32 minute, int32 second, int32 microsecond)
203a070cf53SStephan Aßmus {
204a070cf53SStephan Aßmus return _SetTime(hour, minute, second, microsecond);
205a070cf53SStephan Aßmus }
206a070cf53SStephan Aßmus
207a070cf53SStephan Aßmus
208a070cf53SStephan Aßmus /*!
209daf3c505SJérôme Duval Adds \c hours to the current time. If the passed value is negative it
210daf3c505SJérôme Duval will become earlier. Note: The time will wrap if it passes midnight.
211a070cf53SStephan Aßmus */
212bbba047cSStephan Aßmus BTime&
AddHours(int32 hours)213a070cf53SStephan Aßmus BTime::AddHours(int32 hours)
214a070cf53SStephan Aßmus {
215bbba047cSStephan Aßmus return _AddMicroseconds(bigtime_t(hours % kHoursPerDay)
216bbba047cSStephan Aßmus * kMicrosecondsPerHour);
217a070cf53SStephan Aßmus }
218a070cf53SStephan Aßmus
219a070cf53SStephan Aßmus
220a070cf53SStephan Aßmus /*!
221daf3c505SJérôme Duval Adds \c minutes to the current time. If the passed value is negative it
222daf3c505SJérôme Duval will become earlier. Note: The time will wrap if it passes midnight.
223a070cf53SStephan Aßmus */
224bbba047cSStephan Aßmus BTime&
AddMinutes(int32 minutes)225a070cf53SStephan Aßmus BTime::AddMinutes(int32 minutes)
226a070cf53SStephan Aßmus {
227bbba047cSStephan Aßmus return _AddMicroseconds(bigtime_t(minutes % kMinutesPerDay)
228bbba047cSStephan Aßmus * kMicrosecondsPerMinute);
229a070cf53SStephan Aßmus }
230a070cf53SStephan Aßmus
231a070cf53SStephan Aßmus
232a070cf53SStephan Aßmus /*!
233daf3c505SJérôme Duval Adds \c seconds to the current time. If the passed value is negative
234daf3c505SJérôme Duval it will become earlier. Note: The time will wrap if it passes midnight.
235a070cf53SStephan Aßmus */
236bbba047cSStephan Aßmus BTime&
AddSeconds(int32 seconds)237a070cf53SStephan Aßmus BTime::AddSeconds(int32 seconds)
238a070cf53SStephan Aßmus {
239bbba047cSStephan Aßmus return _AddMicroseconds(bigtime_t(seconds % kSecondsPerDay)
240bbba047cSStephan Aßmus * kMicrosecondsPerSecond);
241a070cf53SStephan Aßmus }
242a070cf53SStephan Aßmus
243a070cf53SStephan Aßmus
244a070cf53SStephan Aßmus /*!
245daf3c505SJérôme Duval Adds \c milliseconds to the current time. If the passed value is negative
246daf3c505SJérôme Duval it will become earlier. Note: The time will wrap if it passes midnight.
247a070cf53SStephan Aßmus */
248bbba047cSStephan Aßmus BTime&
AddMilliseconds(int32 milliseconds)249a070cf53SStephan Aßmus BTime::AddMilliseconds(int32 milliseconds)
250a070cf53SStephan Aßmus {
251bbba047cSStephan Aßmus return _AddMicroseconds(bigtime_t(milliseconds % kMillisecondsPerDay)
252bbba047cSStephan Aßmus * 1000);
253a070cf53SStephan Aßmus }
254a070cf53SStephan Aßmus
255a070cf53SStephan Aßmus
256a070cf53SStephan Aßmus /*!
257daf3c505SJérôme Duval Adds \c microseconds to the current time. If the passed value is negative
258daf3c505SJérôme Duval it will become earlier. Note: The time will wrap if it passes midnight.
259a070cf53SStephan Aßmus */
260bbba047cSStephan Aßmus BTime&
AddMicroseconds(int32 microseconds)261a070cf53SStephan Aßmus BTime::AddMicroseconds(int32 microseconds)
262a070cf53SStephan Aßmus {
263bbba047cSStephan Aßmus return _AddMicroseconds(microseconds);
264a070cf53SStephan Aßmus }
265a070cf53SStephan Aßmus
266a070cf53SStephan Aßmus
267a070cf53SStephan Aßmus /*!
268a070cf53SStephan Aßmus Returns the hour fragment of the time.
269a070cf53SStephan Aßmus */
270a070cf53SStephan Aßmus int32
Hour() const271a070cf53SStephan Aßmus BTime::Hour() const
272a070cf53SStephan Aßmus {
273a070cf53SStephan Aßmus return int32(_Microseconds() / kMicrosecondsPerHour);
274a070cf53SStephan Aßmus }
275a070cf53SStephan Aßmus
276a070cf53SStephan Aßmus
277a070cf53SStephan Aßmus /*!
278a070cf53SStephan Aßmus Returns the minute fragment of the time.
279a070cf53SStephan Aßmus */
280a070cf53SStephan Aßmus int32
Minute() const281a070cf53SStephan Aßmus BTime::Minute() const
282a070cf53SStephan Aßmus {
283daf3c505SJérôme Duval return int32(((_Microseconds() % kMicrosecondsPerHour))
284daf3c505SJérôme Duval / kMicrosecondsPerMinute);
285a070cf53SStephan Aßmus }
286a070cf53SStephan Aßmus
287a070cf53SStephan Aßmus
288a070cf53SStephan Aßmus /*!
289a070cf53SStephan Aßmus Returns the second fragment of the time.
290a070cf53SStephan Aßmus */
291a070cf53SStephan Aßmus int32
Second() const292a070cf53SStephan Aßmus BTime::Second() const
293a070cf53SStephan Aßmus {
294a070cf53SStephan Aßmus return int32(_Microseconds() / kMicrosecondsPerSecond) % kSecondsPerMinute;
295a070cf53SStephan Aßmus }
296a070cf53SStephan Aßmus
297a070cf53SStephan Aßmus
298a070cf53SStephan Aßmus /*!
299a070cf53SStephan Aßmus Returns the millisecond fragment of the time.
300a070cf53SStephan Aßmus */
301a070cf53SStephan Aßmus int32
Millisecond() const302a070cf53SStephan Aßmus BTime::Millisecond() const
303a070cf53SStephan Aßmus {
304a070cf53SStephan Aßmus
305a070cf53SStephan Aßmus return Microsecond() / 1000;
306a070cf53SStephan Aßmus }
307a070cf53SStephan Aßmus
308a070cf53SStephan Aßmus
309a070cf53SStephan Aßmus /*!
310a070cf53SStephan Aßmus Returns the microsecond fragment of the time.
311a070cf53SStephan Aßmus */
312a070cf53SStephan Aßmus int32
Microsecond() const313a070cf53SStephan Aßmus BTime::Microsecond() const
314a070cf53SStephan Aßmus {
315daf3c505SJérôme Duval return int32(_Microseconds() % kMicrosecondsPerSecond);
316a070cf53SStephan Aßmus }
317a070cf53SStephan Aßmus
318a070cf53SStephan Aßmus
319a070cf53SStephan Aßmus bigtime_t
_Microseconds() const320a070cf53SStephan Aßmus BTime::_Microseconds() const
321a070cf53SStephan Aßmus {
322a070cf53SStephan Aßmus return fMicroseconds == -1 ? 0 : fMicroseconds;
323a070cf53SStephan Aßmus }
324a070cf53SStephan Aßmus
325a070cf53SStephan Aßmus
326a070cf53SStephan Aßmus /*!
327a070cf53SStephan Aßmus Returns the difference between this time and the given BTime \c time based
328a070cf53SStephan Aßmus on the passed diff_type \c type. If \c time is earlier the return value will
329a070cf53SStephan Aßmus be negativ.
330a070cf53SStephan Aßmus
331a070cf53SStephan Aßmus The return value then can be hours, minutes, seconds, milliseconds or
332a070cf53SStephan Aßmus microseconds while its range will always be between -86400000000 and
333a070cf53SStephan Aßmus 86400000000 depending on diff_type \c type.
334a070cf53SStephan Aßmus */
335a070cf53SStephan Aßmus bigtime_t
Difference(const BTime & time,diff_type type) const336a070cf53SStephan Aßmus BTime::Difference(const BTime& time, diff_type type) const
337a070cf53SStephan Aßmus {
338a070cf53SStephan Aßmus bigtime_t diff = time._Microseconds() - _Microseconds();
339a070cf53SStephan Aßmus switch (type) {
340daf3c505SJérôme Duval case B_HOURS_DIFF:
341a070cf53SStephan Aßmus diff /= kMicrosecondsPerHour;
342daf3c505SJérôme Duval break;
343daf3c505SJérôme Duval case B_MINUTES_DIFF:
344a070cf53SStephan Aßmus diff /= kMicrosecondsPerMinute;
345daf3c505SJérôme Duval break;
346daf3c505SJérôme Duval case B_SECONDS_DIFF:
347a070cf53SStephan Aßmus diff /= kMicrosecondsPerSecond;
348daf3c505SJérôme Duval break;
349daf3c505SJérôme Duval case B_MILLISECONDS_DIFF:
350a070cf53SStephan Aßmus diff /= 1000;
351daf3c505SJérôme Duval break;
352a070cf53SStephan Aßmus case B_MICROSECONDS_DIFF:
353daf3c505SJérôme Duval default:
354daf3c505SJérôme Duval break;
355a070cf53SStephan Aßmus }
356a070cf53SStephan Aßmus return diff;
357a070cf53SStephan Aßmus }
358a070cf53SStephan Aßmus
359a070cf53SStephan Aßmus
360a070cf53SStephan Aßmus /*!
361a070cf53SStephan Aßmus Returns true if this time is different from \c time, otherwise false.
362a070cf53SStephan Aßmus */
363a070cf53SStephan Aßmus bool
operator !=(const BTime & time) const364a070cf53SStephan Aßmus BTime::operator!=(const BTime& time) const
365a070cf53SStephan Aßmus {
366a070cf53SStephan Aßmus return fMicroseconds != time.fMicroseconds;
367a070cf53SStephan Aßmus }
368a070cf53SStephan Aßmus
369a070cf53SStephan Aßmus
370a070cf53SStephan Aßmus /*!
371a070cf53SStephan Aßmus Returns true if this time is equal to \c time, otherwise false.
372a070cf53SStephan Aßmus */
373a070cf53SStephan Aßmus bool
operator ==(const BTime & time) const374a070cf53SStephan Aßmus BTime::operator==(const BTime& time) const
375a070cf53SStephan Aßmus {
376a070cf53SStephan Aßmus return fMicroseconds == time.fMicroseconds;
377a070cf53SStephan Aßmus }
378a070cf53SStephan Aßmus
379a070cf53SStephan Aßmus
380a070cf53SStephan Aßmus /*!
381a070cf53SStephan Aßmus Returns true if this time is earlier than \c time, otherwise false.
382a070cf53SStephan Aßmus */
383a070cf53SStephan Aßmus bool
operator <(const BTime & time) const384a070cf53SStephan Aßmus BTime::operator<(const BTime& time) const
385a070cf53SStephan Aßmus {
386a070cf53SStephan Aßmus return fMicroseconds < time.fMicroseconds;
387a070cf53SStephan Aßmus }
388a070cf53SStephan Aßmus
389a070cf53SStephan Aßmus
390a070cf53SStephan Aßmus /*!
391a070cf53SStephan Aßmus Returns true if this time is earlier than or equal to \c time, otherwise false.
392a070cf53SStephan Aßmus */
393a070cf53SStephan Aßmus bool
operator <=(const BTime & time) const394a070cf53SStephan Aßmus BTime::operator<=(const BTime& time) const
395a070cf53SStephan Aßmus {
396a070cf53SStephan Aßmus return fMicroseconds <= time.fMicroseconds;
397a070cf53SStephan Aßmus }
398a070cf53SStephan Aßmus
399a070cf53SStephan Aßmus
400a070cf53SStephan Aßmus /*!
401a070cf53SStephan Aßmus Returns true if this time is later than \c time, otherwise false.
402a070cf53SStephan Aßmus */
403a070cf53SStephan Aßmus bool
operator >(const BTime & time) const404a070cf53SStephan Aßmus BTime::operator>(const BTime& time) const
405a070cf53SStephan Aßmus {
406a070cf53SStephan Aßmus return fMicroseconds > time.fMicroseconds;
407a070cf53SStephan Aßmus }
408a070cf53SStephan Aßmus
409a070cf53SStephan Aßmus
410a070cf53SStephan Aßmus /*!
411a070cf53SStephan Aßmus Returns true if this time is later than or equal to \c time, otherwise false.
412a070cf53SStephan Aßmus */
413a070cf53SStephan Aßmus bool
operator >=(const BTime & time) const414a070cf53SStephan Aßmus BTime::operator>=(const BTime& time) const
415a070cf53SStephan Aßmus {
416a070cf53SStephan Aßmus return fMicroseconds >= time.fMicroseconds;
417a070cf53SStephan Aßmus }
418a070cf53SStephan Aßmus
419a070cf53SStephan Aßmus
420bbba047cSStephan Aßmus BTime&
_AddMicroseconds(bigtime_t microseconds)421a070cf53SStephan Aßmus BTime::_AddMicroseconds(bigtime_t microseconds)
422a070cf53SStephan Aßmus {
423a070cf53SStephan Aßmus bigtime_t count = 0;
424a070cf53SStephan Aßmus if (microseconds < 0) {
425a070cf53SStephan Aßmus count = ((kMicrosecondsPerDay - microseconds) / kMicrosecondsPerDay) *
426a070cf53SStephan Aßmus kMicrosecondsPerDay;
427a070cf53SStephan Aßmus }
428a070cf53SStephan Aßmus fMicroseconds = (_Microseconds() + microseconds + count) % kMicrosecondsPerDay;
429bbba047cSStephan Aßmus return *this;
430a070cf53SStephan Aßmus }
431a070cf53SStephan Aßmus
432a070cf53SStephan Aßmus
433a070cf53SStephan Aßmus bool
_SetTime(bigtime_t hour,bigtime_t minute,bigtime_t second,bigtime_t microsecond)434a070cf53SStephan Aßmus BTime::_SetTime(bigtime_t hour, bigtime_t minute, bigtime_t second,
435a070cf53SStephan Aßmus bigtime_t microsecond)
436a070cf53SStephan Aßmus {
437a070cf53SStephan Aßmus fMicroseconds = hour * kMicrosecondsPerHour +
438a070cf53SStephan Aßmus minute * kMicrosecondsPerMinute +
439a070cf53SStephan Aßmus second * kMicrosecondsPerSecond +
440a070cf53SStephan Aßmus microsecond;
441a070cf53SStephan Aßmus
442a070cf53SStephan Aßmus bool isValid = IsValid();
443a070cf53SStephan Aßmus if (!isValid)
444a070cf53SStephan Aßmus fMicroseconds = -1;
445a070cf53SStephan Aßmus
446a070cf53SStephan Aßmus return isValid;
447a070cf53SStephan Aßmus }
448a070cf53SStephan Aßmus
449a070cf53SStephan Aßmus
450a070cf53SStephan Aßmus // #pragma mark - BDate
451a070cf53SStephan Aßmus
452a070cf53SStephan Aßmus
453a070cf53SStephan Aßmus /*!
454a070cf53SStephan Aßmus Constructs a new BDate object. IsValid() will return false.
455a070cf53SStephan Aßmus */
BDate()456a070cf53SStephan Aßmus BDate::BDate()
457bbba047cSStephan Aßmus :
458bbba047cSStephan Aßmus fDay(-1),
459a070cf53SStephan Aßmus fYear(0),
460a070cf53SStephan Aßmus fMonth(-1)
461a070cf53SStephan Aßmus {
462a070cf53SStephan Aßmus }
463a070cf53SStephan Aßmus
464a070cf53SStephan Aßmus
465a070cf53SStephan Aßmus /*!
466bbba047cSStephan Aßmus Constructs a new BDate object as a copy of \c other.
467bbba047cSStephan Aßmus */
BDate(const BDate & other)468bbba047cSStephan Aßmus BDate::BDate(const BDate& other)
469bbba047cSStephan Aßmus :
470bbba047cSStephan Aßmus fDay(other.fDay),
471bbba047cSStephan Aßmus fYear(other.fYear),
472bbba047cSStephan Aßmus fMonth(other.fMonth)
473bbba047cSStephan Aßmus {
474bbba047cSStephan Aßmus }
475bbba047cSStephan Aßmus
476bbba047cSStephan Aßmus
477bbba047cSStephan Aßmus /*!
478a070cf53SStephan Aßmus Constructs a BDate object with \c year \c month and \c day.
479a070cf53SStephan Aßmus
480a070cf53SStephan Aßmus Please note that a date before 1.1.4713 BC, a date with year 0 and a date
481a070cf53SStephan Aßmus between 4.10.1582 and 15.10.1582 are considered invalid. If the specified
482a070cf53SStephan Aßmus date is invalid, the date is not set and IsValid() returns false. Also note
483a070cf53SStephan Aßmus that every passed year will be interpreted as is.
484a070cf53SStephan Aßmus
485a070cf53SStephan Aßmus */
BDate(int32 year,int32 month,int32 day)486a070cf53SStephan Aßmus BDate::BDate(int32 year, int32 month, int32 day)
487a070cf53SStephan Aßmus {
488a070cf53SStephan Aßmus _SetDate(year, month, day);
489a070cf53SStephan Aßmus }
490a070cf53SStephan Aßmus
491a070cf53SStephan Aßmus
BDate(time_t time,time_type type)49219d8cb70SAxel Dörfler BDate::BDate(time_t time, time_type type)
49319d8cb70SAxel Dörfler {
49419d8cb70SAxel Dörfler struct tm result;
49519d8cb70SAxel Dörfler struct tm* timeinfo;
49619d8cb70SAxel Dörfler
49719d8cb70SAxel Dörfler if (type == B_GMT_TIME)
49819d8cb70SAxel Dörfler timeinfo = gmtime_r(&time, &result);
49919d8cb70SAxel Dörfler else
50019d8cb70SAxel Dörfler timeinfo = localtime_r(&time, &result);
50119d8cb70SAxel Dörfler
50219d8cb70SAxel Dörfler if (timeinfo != NULL) {
50319d8cb70SAxel Dörfler _SetDate(timeinfo->tm_year + 1900, timeinfo->tm_mon + 1,
50419d8cb70SAxel Dörfler timeinfo->tm_mday);
50519d8cb70SAxel Dörfler }
50619d8cb70SAxel Dörfler }
50719d8cb70SAxel Dörfler
50819d8cb70SAxel Dörfler
509a070cf53SStephan Aßmus /*!
510a070cf53SStephan Aßmus Constructs a new BDate object from the provided archive.
511a070cf53SStephan Aßmus */
BDate(const BMessage * archive)512a070cf53SStephan Aßmus BDate::BDate(const BMessage* archive)
513bbba047cSStephan Aßmus :
514bbba047cSStephan Aßmus fDay(-1),
515a070cf53SStephan Aßmus fYear(0),
516a070cf53SStephan Aßmus fMonth(-1)
517a070cf53SStephan Aßmus {
518a070cf53SStephan Aßmus if (archive == NULL)
519a070cf53SStephan Aßmus return;
520a070cf53SStephan Aßmus archive->FindInt32("day", &fDay);
521a070cf53SStephan Aßmus archive->FindInt32("year", &fYear);
522a070cf53SStephan Aßmus archive->FindInt32("month", &fMonth);
523a070cf53SStephan Aßmus }
524a070cf53SStephan Aßmus
525a070cf53SStephan Aßmus
526a070cf53SStephan Aßmus /*!
527a070cf53SStephan Aßmus Empty destructor.
528a070cf53SStephan Aßmus */
~BDate()529a070cf53SStephan Aßmus BDate::~BDate()
530a070cf53SStephan Aßmus {
531a070cf53SStephan Aßmus }
532a070cf53SStephan Aßmus
533a070cf53SStephan Aßmus
534a070cf53SStephan Aßmus /*!
535a070cf53SStephan Aßmus Archives the BDate object into the provided BMessage object.
536a070cf53SStephan Aßmus @returns \c B_OK if all went well.
537a070cf53SStephan Aßmus \c B_BAD_VALUE, if the message is \c NULL.
538a070cf53SStephan Aßmus \c other error codes, depending on failure to append
539a070cf53SStephan Aßmus fields to the message.
540a070cf53SStephan Aßmus */
541a070cf53SStephan Aßmus status_t
Archive(BMessage * into) const542a070cf53SStephan Aßmus BDate::Archive(BMessage* into) const
543a070cf53SStephan Aßmus {
544a070cf53SStephan Aßmus if (into == NULL)
545a070cf53SStephan Aßmus return B_BAD_VALUE;
546a070cf53SStephan Aßmus status_t ret = into->AddInt32("day", fDay);
547a070cf53SStephan Aßmus if (ret == B_OK)
548a070cf53SStephan Aßmus ret = into->AddInt32("year", fYear);
549a070cf53SStephan Aßmus if (ret == B_OK)
550a070cf53SStephan Aßmus ret = into->AddInt32("month", fMonth);
551a070cf53SStephan Aßmus return ret;
552a070cf53SStephan Aßmus }
553a070cf53SStephan Aßmus
554a070cf53SStephan Aßmus
555a070cf53SStephan Aßmus /*!
556a070cf53SStephan Aßmus Returns true if the date is valid, otherwise false.
557a070cf53SStephan Aßmus
558a070cf53SStephan Aßmus Please note that a date before 1.1.4713 BC, a date with year 0 and a date
559a070cf53SStephan Aßmus between 4.10.1582 and 15.10.1582 are considered invalid.
560a070cf53SStephan Aßmus */
561a070cf53SStephan Aßmus bool
IsValid() const562a070cf53SStephan Aßmus BDate::IsValid() const
563a070cf53SStephan Aßmus {
564a070cf53SStephan Aßmus return IsValid(fYear, fMonth, fDay);
565a070cf53SStephan Aßmus }
566a070cf53SStephan Aßmus
567a070cf53SStephan Aßmus
568a070cf53SStephan Aßmus /*!
569a070cf53SStephan Aßmus This is an overloaded member function, provided for convenience.
570a070cf53SStephan Aßmus */
571daf3c505SJérôme Duval /*static*/ bool
IsValid(const BDate & date)572daf3c505SJérôme Duval BDate::IsValid(const BDate& date)
573a070cf53SStephan Aßmus {
574a070cf53SStephan Aßmus return IsValid(date.fYear, date.fMonth, date.fDay);
575a070cf53SStephan Aßmus }
576a070cf53SStephan Aßmus
577a070cf53SStephan Aßmus
578a070cf53SStephan Aßmus /*!
579a070cf53SStephan Aßmus This is an overloaded member function, provided for convenience.
580a070cf53SStephan Aßmus */
581daf3c505SJérôme Duval /*static*/ bool
IsValid(int32 year,int32 month,int32 day)582daf3c505SJérôme Duval BDate::IsValid(int32 year, int32 month, int32 day)
583a070cf53SStephan Aßmus {
584a070cf53SStephan Aßmus // no year 0 in Julian and nothing before 1.1.4713 BC
585a070cf53SStephan Aßmus if (year == 0 || year < -4713)
586a070cf53SStephan Aßmus return false;
587a070cf53SStephan Aßmus
588a070cf53SStephan Aßmus if (month < 1 || month > 12)
589a070cf53SStephan Aßmus return false;
590a070cf53SStephan Aßmus
591a070cf53SStephan Aßmus if (day < 1 || day > _DaysInMonth(year, month))
592a070cf53SStephan Aßmus return false;
593a070cf53SStephan Aßmus
594a070cf53SStephan Aßmus // 'missing' days between switch julian - gregorian
595a070cf53SStephan Aßmus if (year == 1582 && month == 10 && day > 4 && day < 15)
596a070cf53SStephan Aßmus return false;
597a070cf53SStephan Aßmus
598a070cf53SStephan Aßmus return true;
599a070cf53SStephan Aßmus }
600a070cf53SStephan Aßmus
601a070cf53SStephan Aßmus
602a070cf53SStephan Aßmus /*!
603a070cf53SStephan Aßmus Returns the current date as reported by the system depending on the given
604a070cf53SStephan Aßmus time_type \c type.
605a070cf53SStephan Aßmus */
606a070cf53SStephan Aßmus BDate
CurrentDate(time_type type)607a070cf53SStephan Aßmus BDate::CurrentDate(time_type type)
608a070cf53SStephan Aßmus {
60919d8cb70SAxel Dörfler return BDate(time(NULL), type);
610a070cf53SStephan Aßmus }
611a070cf53SStephan Aßmus
612a070cf53SStephan Aßmus
613a070cf53SStephan Aßmus /*!
614a070cf53SStephan Aßmus Returns a copy of the current BTime object.
615a070cf53SStephan Aßmus */
616a070cf53SStephan Aßmus BDate
Date() const617a070cf53SStephan Aßmus BDate::Date() const
618a070cf53SStephan Aßmus {
619a070cf53SStephan Aßmus return *this;
620a070cf53SStephan Aßmus }
621a070cf53SStephan Aßmus
622a070cf53SStephan Aßmus
623a070cf53SStephan Aßmus /*!
624a070cf53SStephan Aßmus This is an overloaded member function, provided for convenience.
625a070cf53SStephan Aßmus */
626a070cf53SStephan Aßmus bool
SetDate(const BDate & date)627a070cf53SStephan Aßmus BDate::SetDate(const BDate& date)
628a070cf53SStephan Aßmus {
629a070cf53SStephan Aßmus return _SetDate(date.fYear, date.fMonth, date.fDay);
630a070cf53SStephan Aßmus }
631a070cf53SStephan Aßmus
632a070cf53SStephan Aßmus
633a070cf53SStephan Aßmus /*!
634a070cf53SStephan Aßmus Set the date to \c year \c month and \c day.
635a070cf53SStephan Aßmus
636a070cf53SStephan Aßmus Returns true if the date is valid; otherwise false. If the specified date is
637a070cf53SStephan Aßmus invalid, the date is not set and the function returns false.
638a070cf53SStephan Aßmus */
639a070cf53SStephan Aßmus bool
SetDate(int32 year,int32 month,int32 day)640a070cf53SStephan Aßmus BDate::SetDate(int32 year, int32 month, int32 day)
641a070cf53SStephan Aßmus {
642a070cf53SStephan Aßmus return _SetDate(year, month, day);
643a070cf53SStephan Aßmus }
644a070cf53SStephan Aßmus
645a070cf53SStephan Aßmus
646a070cf53SStephan Aßmus /*!
647a070cf53SStephan Aßmus This function sets the given \c year, \c month and \c day to the
648a070cf53SStephan Aßmus representative values of this date. The pointers can be NULL. If the date is
649a070cf53SStephan Aßmus invalid, the values will be set to -1 for \c month and \c day, the \c year
650a070cf53SStephan Aßmus will be set to 0.
651a070cf53SStephan Aßmus */
652a070cf53SStephan Aßmus void
GetDate(int32 * year,int32 * month,int32 * day) const653daf3c505SJérôme Duval BDate::GetDate(int32* year, int32* month, int32* day) const
654a070cf53SStephan Aßmus {
655a070cf53SStephan Aßmus if (year)
656a070cf53SStephan Aßmus *year = fYear;
657a070cf53SStephan Aßmus
658a070cf53SStephan Aßmus if (month)
659a070cf53SStephan Aßmus *month = fMonth;
660a070cf53SStephan Aßmus
661a070cf53SStephan Aßmus if (day)
662a070cf53SStephan Aßmus *day = fDay;
663a070cf53SStephan Aßmus }
664a070cf53SStephan Aßmus
665a070cf53SStephan Aßmus
666a070cf53SStephan Aßmus /*!
6677407e36aSAndrew Lindesay Adds \c days to the current date. If the passed value is negative it will
668a070cf53SStephan Aßmus become earlier. If the current date is invalid, the \c days are not added.
669a070cf53SStephan Aßmus */
670a070cf53SStephan Aßmus void
AddDays(int32 days)671a070cf53SStephan Aßmus BDate::AddDays(int32 days)
672a070cf53SStephan Aßmus {
673a070cf53SStephan Aßmus if (IsValid())
674a070cf53SStephan Aßmus *this = JulianDayToDate(DateToJulianDay() + days);
675a070cf53SStephan Aßmus }
676a070cf53SStephan Aßmus
677a070cf53SStephan Aßmus
678a070cf53SStephan Aßmus /*!
679a070cf53SStephan Aßmus Adds \c years to the current date. If the passed value is negativ it will
680a070cf53SStephan Aßmus become earlier. If the current date is invalid, the \c years are not added.
681a070cf53SStephan Aßmus The day/ month combination will be adjusted if it does not exist in the
682a070cf53SStephan Aßmus resulting year, so this function will then return the latest valid date.
683a070cf53SStephan Aßmus */
684a070cf53SStephan Aßmus void
AddYears(int32 years)685a070cf53SStephan Aßmus BDate::AddYears(int32 years)
686a070cf53SStephan Aßmus {
687a070cf53SStephan Aßmus if (IsValid()) {
688a070cf53SStephan Aßmus const int32 tmp = fYear;
689a070cf53SStephan Aßmus fYear += years;
690a070cf53SStephan Aßmus
691a070cf53SStephan Aßmus if ((tmp > 0 && fYear <= 0) || (tmp < 0 && fYear >= 0))
692a070cf53SStephan Aßmus fYear += (years > 0) ? +1 : -1;
693a070cf53SStephan Aßmus
694a070cf53SStephan Aßmus fDay = min_c(fDay, _DaysInMonth(fYear, fMonth));
695a070cf53SStephan Aßmus }
696a070cf53SStephan Aßmus }
697a070cf53SStephan Aßmus
698a070cf53SStephan Aßmus
699a070cf53SStephan Aßmus /*!
700a070cf53SStephan Aßmus Adds \c months to the current date. If the passed value is negativ it will
701a070cf53SStephan Aßmus become earlier. If the current date is invalid, the \c months are not added.
702a070cf53SStephan Aßmus The day/ month combination will be adjusted if it does not exist in the
703a070cf53SStephan Aßmus resulting year, so this function will then return the latest valid date.
704a070cf53SStephan Aßmus */
705a070cf53SStephan Aßmus void
AddMonths(int32 months)706a070cf53SStephan Aßmus BDate::AddMonths(int32 months)
707a070cf53SStephan Aßmus {
708a070cf53SStephan Aßmus if (IsValid()) {
709a070cf53SStephan Aßmus const int32 tmp = fYear;
710a070cf53SStephan Aßmus fYear += months / 12;
711a070cf53SStephan Aßmus fMonth += months % 12;
712a070cf53SStephan Aßmus
713a070cf53SStephan Aßmus if (fMonth > 12) {
714a070cf53SStephan Aßmus fYear++;
715a070cf53SStephan Aßmus fMonth -= 12;
716a070cf53SStephan Aßmus } else if (fMonth < 1) {
717a070cf53SStephan Aßmus fYear--;
718a070cf53SStephan Aßmus fMonth += 12;
719a070cf53SStephan Aßmus }
720a070cf53SStephan Aßmus
721a070cf53SStephan Aßmus if ((tmp > 0 && fYear <= 0) || (tmp < 0 && fYear >= 0))
722a070cf53SStephan Aßmus fYear += (months > 0) ? +1 : -1;
723a070cf53SStephan Aßmus
724a070cf53SStephan Aßmus // 'missing' days between switch julian - gregorian
725a070cf53SStephan Aßmus if (fYear == 1582 && fMonth == 10 && fDay > 4 && fDay < 15)
726a070cf53SStephan Aßmus fDay = (months > 0) ? 15 : 4;
727a070cf53SStephan Aßmus
728aac8a4c3SOliver Tappe fDay = min_c(fDay, _DaysInMonth(fYear, fMonth));
729a070cf53SStephan Aßmus }
730a070cf53SStephan Aßmus }
731a070cf53SStephan Aßmus
732a070cf53SStephan Aßmus
733a070cf53SStephan Aßmus /*!
734a070cf53SStephan Aßmus Returns the day fragment of the date. The return value will be in the range
735a070cf53SStephan Aßmus of 1 to 31, in case the date is invalid it will be -1.
736a070cf53SStephan Aßmus */
737a070cf53SStephan Aßmus int32
Day() const738a070cf53SStephan Aßmus BDate::Day() const
739a070cf53SStephan Aßmus {
740a070cf53SStephan Aßmus return fDay;
741a070cf53SStephan Aßmus }
742a070cf53SStephan Aßmus
743a070cf53SStephan Aßmus
744a070cf53SStephan Aßmus /*!
745a070cf53SStephan Aßmus Returns the year fragment of the date. If the date is invalid, the function
746a070cf53SStephan Aßmus returns 0.
747a070cf53SStephan Aßmus */
748a070cf53SStephan Aßmus int32
Year() const749a070cf53SStephan Aßmus BDate::Year() const
750a070cf53SStephan Aßmus {
751a070cf53SStephan Aßmus return fYear;
752a070cf53SStephan Aßmus }
753a070cf53SStephan Aßmus
754a070cf53SStephan Aßmus
755a070cf53SStephan Aßmus /*!
756a070cf53SStephan Aßmus Returns the month fragment of the date. The return value will be in the
757a070cf53SStephan Aßmus range of 1 to 12, in case the date is invalid it will be -1.
758a070cf53SStephan Aßmus */
759a070cf53SStephan Aßmus int32
Month() const760a070cf53SStephan Aßmus BDate::Month() const
761a070cf53SStephan Aßmus {
762a070cf53SStephan Aßmus return fMonth;
763a070cf53SStephan Aßmus }
764a070cf53SStephan Aßmus
765a070cf53SStephan Aßmus
766a070cf53SStephan Aßmus /*!
767a070cf53SStephan Aßmus Returns the difference in days between this date and the given BDate \c date.
768a070cf53SStephan Aßmus If \c date is earlier the return value will be negativ. If the calculation
769a070cf53SStephan Aßmus is done with an invalid date, the result is undefined.
770a070cf53SStephan Aßmus */
771a070cf53SStephan Aßmus int32
Difference(const BDate & date) const772a070cf53SStephan Aßmus BDate::Difference(const BDate& date) const
773a070cf53SStephan Aßmus {
774a070cf53SStephan Aßmus return date.DateToJulianDay() - DateToJulianDay();
775a070cf53SStephan Aßmus }
776a070cf53SStephan Aßmus
777a070cf53SStephan Aßmus
778afd5ec11SAdrien Destugues void
SetDay(int32 day)779afd5ec11SAdrien Destugues BDate::SetDay(int32 day)
780afd5ec11SAdrien Destugues {
781afd5ec11SAdrien Destugues fDay = day;
782afd5ec11SAdrien Destugues }
783afd5ec11SAdrien Destugues
784afd5ec11SAdrien Destugues
785afd5ec11SAdrien Destugues void
SetMonth(int32 month)786afd5ec11SAdrien Destugues BDate::SetMonth(int32 month)
787afd5ec11SAdrien Destugues {
788afd5ec11SAdrien Destugues fMonth = month;
789afd5ec11SAdrien Destugues }
790afd5ec11SAdrien Destugues
791afd5ec11SAdrien Destugues
792afd5ec11SAdrien Destugues void
SetYear(int32 year)793afd5ec11SAdrien Destugues BDate::SetYear(int32 year)
794afd5ec11SAdrien Destugues {
795afd5ec11SAdrien Destugues fYear = year;
796afd5ec11SAdrien Destugues }
797afd5ec11SAdrien Destugues
798afd5ec11SAdrien Destugues
799a070cf53SStephan Aßmus /*!
800a070cf53SStephan Aßmus Returns the week number of the date, if the date is invalid it will return
801a070cf53SStephan Aßmus B_ERROR. Please note that this function does only work within the Gregorian
802a070cf53SStephan Aßmus calendar, thus a date before 15.10.1582 will return B_ERROR.
803a070cf53SStephan Aßmus */
804a070cf53SStephan Aßmus int32
WeekNumber() const805a070cf53SStephan Aßmus BDate::WeekNumber() const
806a070cf53SStephan Aßmus {
807a070cf53SStephan Aßmus /*
808a070cf53SStephan Aßmus This algorithm is taken from:
809a070cf53SStephan Aßmus Frequently Asked Questions about Calendars
810a070cf53SStephan Aßmus Version 2.8 Claus Tøndering 15 December 2005
811a070cf53SStephan Aßmus
812a070cf53SStephan Aßmus Note: it will work only within the Gregorian Calendar
813a070cf53SStephan Aßmus */
814a070cf53SStephan Aßmus
815a070cf53SStephan Aßmus if (!IsValid() || fYear < 1582
816a070cf53SStephan Aßmus || (fYear == 1582 && fMonth < 10)
817a070cf53SStephan Aßmus || (fYear == 1582 && fMonth == 10 && fDay < 15))
818a070cf53SStephan Aßmus return int32(B_ERROR);
819a070cf53SStephan Aßmus
820a070cf53SStephan Aßmus int32 a;
821a070cf53SStephan Aßmus int32 b;
822a070cf53SStephan Aßmus int32 s;
823a070cf53SStephan Aßmus int32 e;
824a070cf53SStephan Aßmus int32 f;
825a070cf53SStephan Aßmus
826a070cf53SStephan Aßmus if (fMonth > 0 && fMonth < 3) {
827a070cf53SStephan Aßmus a = fYear - 1;
828a070cf53SStephan Aßmus b = (a / 4) - (a / 100) + (a / 400);
829a070cf53SStephan Aßmus int32 c = ((a - 1) / 4) - ((a - 1) / 100) + ((a -1) / 400);
830a070cf53SStephan Aßmus s = b - c;
831a070cf53SStephan Aßmus e = 0;
832a070cf53SStephan Aßmus f = fDay - 1 + 31 * (fMonth - 1);
833a070cf53SStephan Aßmus } else if (fMonth >= 3 && fMonth <= 12) {
834a070cf53SStephan Aßmus a = fYear;
835a070cf53SStephan Aßmus b = (a / 4) - (a / 100) + (a / 400);
836a070cf53SStephan Aßmus int32 c = ((a - 1) / 4) - ((a - 1) / 100) + ((a -1) / 400);
837a070cf53SStephan Aßmus s = b - c;
838a070cf53SStephan Aßmus e = s + 1;
839a070cf53SStephan Aßmus f = fDay + ((153 * (fMonth - 3) + 2) / 5) + 58 + s;
840a070cf53SStephan Aßmus } else
841a070cf53SStephan Aßmus return int32(B_ERROR);
842a070cf53SStephan Aßmus
843a070cf53SStephan Aßmus int32 g = (a + b) % 7;
844a070cf53SStephan Aßmus int32 d = (f + g - e) % 7;
845a070cf53SStephan Aßmus int32 n = f + 3 - d;
846a070cf53SStephan Aßmus
847a070cf53SStephan Aßmus int32 weekNumber;
848a070cf53SStephan Aßmus if (n < 0)
849a070cf53SStephan Aßmus weekNumber = 53 - (g -s) / 5;
850a070cf53SStephan Aßmus else if (n > 364 + s)
851a070cf53SStephan Aßmus weekNumber = 1;
852a070cf53SStephan Aßmus else
853a070cf53SStephan Aßmus weekNumber = n / 7 + 1;
854a070cf53SStephan Aßmus
855a070cf53SStephan Aßmus return weekNumber;
856a070cf53SStephan Aßmus }
857a070cf53SStephan Aßmus
858a070cf53SStephan Aßmus
859a070cf53SStephan Aßmus /*!
860a070cf53SStephan Aßmus Returns the day of the week in the range of 1 to 7, while 1 stands for
861a070cf53SStephan Aßmus monday. If the date is invalid, the function will return B_ERROR.
862a070cf53SStephan Aßmus */
863a070cf53SStephan Aßmus int32
DayOfWeek() const864a070cf53SStephan Aßmus BDate::DayOfWeek() const
865a070cf53SStephan Aßmus {
866a070cf53SStephan Aßmus // http://en.wikipedia.org/wiki/Julian_day#Calculation
867a070cf53SStephan Aßmus return IsValid() ? (DateToJulianDay() % 7) + 1 : int32(B_ERROR);
868a070cf53SStephan Aßmus }
869a070cf53SStephan Aßmus
870a070cf53SStephan Aßmus
871a070cf53SStephan Aßmus /*!
872a070cf53SStephan Aßmus Returns the day of the year in the range of 1 to 365 (366 in leap years). If
873a070cf53SStephan Aßmus the date is invalid, the function will return B_ERROR.
874a070cf53SStephan Aßmus */
875a070cf53SStephan Aßmus int32
DayOfYear() const876a070cf53SStephan Aßmus BDate::DayOfYear() const
877a070cf53SStephan Aßmus {
878a070cf53SStephan Aßmus if (!IsValid())
879a070cf53SStephan Aßmus return int32(B_ERROR);
880a070cf53SStephan Aßmus
881a070cf53SStephan Aßmus return DateToJulianDay() - _DateToJulianDay(fYear, 1, 1) + 1;
882a070cf53SStephan Aßmus }
883a070cf53SStephan Aßmus
884a070cf53SStephan Aßmus
885a070cf53SStephan Aßmus /*!
886daf3c505SJérôme Duval Returns true if the year of this object is a leap year, otherwise false. If
887daf3c505SJérôme Duval the \c year passed is before 4713 BC, the result is undefined.
888daf3c505SJérôme Duval */
889daf3c505SJérôme Duval bool
IsLeapYear() const890daf3c505SJérôme Duval BDate::IsLeapYear() const
891daf3c505SJérôme Duval {
892daf3c505SJérôme Duval return IsLeapYear(fYear);
893daf3c505SJérôme Duval }
894daf3c505SJérôme Duval
895daf3c505SJérôme Duval
896daf3c505SJérôme Duval /*!
897a070cf53SStephan Aßmus Returns true if the passed \c year is a leap year, otherwise false. If the
898a070cf53SStephan Aßmus \c year passed is before 4713 BC, the result is undefined.
899a070cf53SStephan Aßmus */
900daf3c505SJérôme Duval /*static*/ bool
IsLeapYear(int32 year)901daf3c505SJérôme Duval BDate::IsLeapYear(int32 year)
902a070cf53SStephan Aßmus {
903a070cf53SStephan Aßmus if (year < 1582) {
904a070cf53SStephan Aßmus if (year < 0)
905a070cf53SStephan Aßmus year++;
906a070cf53SStephan Aßmus return (year % 4) == 0;
907a070cf53SStephan Aßmus }
908a070cf53SStephan Aßmus return (year % 400 == 0) || (year % 4 == 0 && year % 100 != 0);
909a070cf53SStephan Aßmus }
910a070cf53SStephan Aßmus
911a070cf53SStephan Aßmus
912a070cf53SStephan Aßmus /*!
913a070cf53SStephan Aßmus Returns the number of days in the year of the current date. If the date is
914a070cf53SStephan Aßmus valid it will return 365 or 366, otherwise B_ERROR;
915a070cf53SStephan Aßmus */
916a070cf53SStephan Aßmus int32
DaysInYear() const917a070cf53SStephan Aßmus BDate::DaysInYear() const
918a070cf53SStephan Aßmus {
919a070cf53SStephan Aßmus if (!IsValid())
920a070cf53SStephan Aßmus return int32(B_ERROR);
921a070cf53SStephan Aßmus
922a070cf53SStephan Aßmus return IsLeapYear(fYear) ? 366 : 365;
923a070cf53SStephan Aßmus }
924a070cf53SStephan Aßmus
925a070cf53SStephan Aßmus
926a070cf53SStephan Aßmus /*!
927a070cf53SStephan Aßmus Returns the number of days in the month of the current date. If the date is
928a070cf53SStephan Aßmus valid it will return 28 up to 31, otherwise B_ERROR;
929a070cf53SStephan Aßmus */
930a070cf53SStephan Aßmus int32
DaysInMonth() const931a070cf53SStephan Aßmus BDate::DaysInMonth() const
932a070cf53SStephan Aßmus {
933a070cf53SStephan Aßmus if (!IsValid())
934a070cf53SStephan Aßmus return int32(B_ERROR);
935a070cf53SStephan Aßmus
936a070cf53SStephan Aßmus return _DaysInMonth(fYear, fMonth);
937a070cf53SStephan Aßmus }
938a070cf53SStephan Aßmus
939a070cf53SStephan Aßmus
940a070cf53SStephan Aßmus /*!
941bbba047cSStephan Aßmus Returns the short day name of this object.
942bbba047cSStephan Aßmus */
943bbba047cSStephan Aßmus BString
ShortDayName() const944bbba047cSStephan Aßmus BDate::ShortDayName() const
945bbba047cSStephan Aßmus {
946bbba047cSStephan Aßmus return ShortDayName(DayOfWeek());
947bbba047cSStephan Aßmus }
948bbba047cSStephan Aßmus
949bbba047cSStephan Aßmus
950bbba047cSStephan Aßmus /*!
951a070cf53SStephan Aßmus Returns the short day name in case of an valid day, otherwise an empty
952a070cf53SStephan Aßmus string. The passed \c day must be in the range of 1 to 7 while 1 stands for
953a070cf53SStephan Aßmus monday.
954a070cf53SStephan Aßmus */
955bbba047cSStephan Aßmus /*static*/ BString
ShortDayName(int32 day)956bbba047cSStephan Aßmus BDate::ShortDayName(int32 day)
957a070cf53SStephan Aßmus {
958a070cf53SStephan Aßmus if (day < 1 || day > 7)
959a070cf53SStephan Aßmus return BString();
960a070cf53SStephan Aßmus
961a070cf53SStephan Aßmus tm tm_struct;
962a070cf53SStephan Aßmus memset(&tm_struct, 0, sizeof(tm));
963a070cf53SStephan Aßmus tm_struct.tm_wday = day == 7 ? 0 : day;
964a070cf53SStephan Aßmus
965a070cf53SStephan Aßmus char buffer[256];
966a070cf53SStephan Aßmus strftime(buffer, sizeof(buffer), "%a", &tm_struct);
967a070cf53SStephan Aßmus
968a070cf53SStephan Aßmus return BString(buffer);
969a070cf53SStephan Aßmus }
970a070cf53SStephan Aßmus
971a070cf53SStephan Aßmus
972a070cf53SStephan Aßmus /*!
973bbba047cSStephan Aßmus Returns the short month name of this object.
974bbba047cSStephan Aßmus */
975bbba047cSStephan Aßmus BString
ShortMonthName() const976bbba047cSStephan Aßmus BDate::ShortMonthName() const
977bbba047cSStephan Aßmus {
978bbba047cSStephan Aßmus return ShortMonthName(Month());
979bbba047cSStephan Aßmus }
980bbba047cSStephan Aßmus
981bbba047cSStephan Aßmus
982bbba047cSStephan Aßmus /*!
983a070cf53SStephan Aßmus Returns the short month name in case of an valid month, otherwise an empty
984a070cf53SStephan Aßmus string. The passed \c month must be in the range of 1 to 12.
985a070cf53SStephan Aßmus */
986bbba047cSStephan Aßmus /*static*/ BString
ShortMonthName(int32 month)987bbba047cSStephan Aßmus BDate::ShortMonthName(int32 month)
988a070cf53SStephan Aßmus {
989a070cf53SStephan Aßmus if (month < 1 || month > 12)
990a070cf53SStephan Aßmus return BString();
991a070cf53SStephan Aßmus
992a070cf53SStephan Aßmus tm tm_struct;
993a070cf53SStephan Aßmus memset(&tm_struct, 0, sizeof(tm));
994a070cf53SStephan Aßmus tm_struct.tm_mon = month - 1;
995a070cf53SStephan Aßmus
996a070cf53SStephan Aßmus char buffer[256];
997a070cf53SStephan Aßmus strftime(buffer, sizeof(buffer), "%b", &tm_struct);
998a070cf53SStephan Aßmus
999a070cf53SStephan Aßmus return BString(buffer);
1000a070cf53SStephan Aßmus }
1001a070cf53SStephan Aßmus
1002a070cf53SStephan Aßmus
1003a070cf53SStephan Aßmus /*!
1004bbba047cSStephan Aßmus Returns the long day name of this object's week day.
1005bbba047cSStephan Aßmus */
1006bbba047cSStephan Aßmus BString
LongDayName() const1007bbba047cSStephan Aßmus BDate::LongDayName() const
1008bbba047cSStephan Aßmus {
1009bbba047cSStephan Aßmus return LongDayName(DayOfWeek());
1010bbba047cSStephan Aßmus }
1011bbba047cSStephan Aßmus
1012bbba047cSStephan Aßmus
1013bbba047cSStephan Aßmus /*!
1014a070cf53SStephan Aßmus Returns the long day name in case of an valid day, otherwise an empty
1015a070cf53SStephan Aßmus string. The passed \c day must be in the range of 1 to 7 while 1 stands for
1016a070cf53SStephan Aßmus monday.
1017a070cf53SStephan Aßmus */
1018bbba047cSStephan Aßmus /*static*/ BString
LongDayName(int32 day)1019bbba047cSStephan Aßmus BDate::LongDayName(int32 day)
1020a070cf53SStephan Aßmus {
1021a070cf53SStephan Aßmus if (day < 1 || day > 7)
1022a070cf53SStephan Aßmus return BString();
1023a070cf53SStephan Aßmus
1024*ffd9d565SAdrien Destugues const BLocale* locale = BLocaleRoster::Default()->GetDefaultLocale();
1025*ffd9d565SAdrien Destugues BDateFormat format(locale);
1026*ffd9d565SAdrien Destugues BString out;
1027*ffd9d565SAdrien Destugues if (format.GetDayName(day, out, B_LONG_DATE_FORMAT) != B_OK)
1028*ffd9d565SAdrien Destugues return BString();
1029a070cf53SStephan Aßmus
1030*ffd9d565SAdrien Destugues return out;
1031a070cf53SStephan Aßmus }
1032a070cf53SStephan Aßmus
1033a070cf53SStephan Aßmus
1034a070cf53SStephan Aßmus /*!
1035bbba047cSStephan Aßmus Returns the long month name of this object's month.
1036bbba047cSStephan Aßmus */
1037bbba047cSStephan Aßmus BString
LongMonthName() const1038bbba047cSStephan Aßmus BDate::LongMonthName() const
1039bbba047cSStephan Aßmus {
1040bbba047cSStephan Aßmus return LongMonthName(Month());
1041bbba047cSStephan Aßmus }
1042bbba047cSStephan Aßmus
1043bbba047cSStephan Aßmus
1044bbba047cSStephan Aßmus /*!
1045a070cf53SStephan Aßmus Returns the long month name in case of an valid month, otherwise an empty
1046a070cf53SStephan Aßmus string. The passed \c month must be in the range of 1 to 12.
1047a070cf53SStephan Aßmus */
1048bbba047cSStephan Aßmus /*static*/ BString
LongMonthName(int32 month)1049bbba047cSStephan Aßmus BDate::LongMonthName(int32 month)
1050a070cf53SStephan Aßmus {
1051a070cf53SStephan Aßmus if (month < 1 || month > 12)
1052a070cf53SStephan Aßmus return BString();
1053a070cf53SStephan Aßmus
1054*ffd9d565SAdrien Destugues const BLocale* locale = BLocaleRoster::Default()->GetDefaultLocale();
1055*ffd9d565SAdrien Destugues BDateFormat format(locale);
1056*ffd9d565SAdrien Destugues BString out;
1057*ffd9d565SAdrien Destugues if (format.GetMonthName(month, out, B_LONG_DATE_FORMAT) != B_OK)
1058*ffd9d565SAdrien Destugues return BString();
1059a070cf53SStephan Aßmus
1060*ffd9d565SAdrien Destugues return out;
1061a070cf53SStephan Aßmus }
1062a070cf53SStephan Aßmus
1063a070cf53SStephan Aßmus
1064a070cf53SStephan Aßmus /*!
1065a070cf53SStephan Aßmus Converts the date to Julian day. If your date is invalid, the function will
1066a070cf53SStephan Aßmus return B_ERROR.
1067a070cf53SStephan Aßmus */
1068a070cf53SStephan Aßmus int32
DateToJulianDay() const1069a070cf53SStephan Aßmus BDate::DateToJulianDay() const
1070a070cf53SStephan Aßmus {
1071a070cf53SStephan Aßmus return _DateToJulianDay(fYear, fMonth, fDay);
1072a070cf53SStephan Aßmus }
1073a070cf53SStephan Aßmus
1074a070cf53SStephan Aßmus
1075daf3c505SJérôme Duval /*!
1076a070cf53SStephan Aßmus Converts the passed \c julianDay to an BDate. If the \c julianDay is negativ,
1077a070cf53SStephan Aßmus the function will return an invalid date. Because of the switch from Julian
1078a070cf53SStephan Aßmus calendar to Gregorian calendar the 4.10.1582 is followed by the 15.10.1582.
1079a070cf53SStephan Aßmus */
1080daf3c505SJérôme Duval /*static*/ BDate
JulianDayToDate(int32 julianDay)1081a070cf53SStephan Aßmus BDate::JulianDayToDate(int32 julianDay)
1082a070cf53SStephan Aßmus {
1083a070cf53SStephan Aßmus BDate date;
1084a070cf53SStephan Aßmus const int32 kGregorianCalendarStart = 2299161;
1085a070cf53SStephan Aßmus if (julianDay >= kGregorianCalendarStart) {
1086a070cf53SStephan Aßmus // http://en.wikipedia.org/wiki/Julian_day#Gregorian_calendar_from_Julian_day_number
1087a070cf53SStephan Aßmus int32 j = julianDay + 32044;
1088a070cf53SStephan Aßmus int32 dg = j % 146097;
1089a070cf53SStephan Aßmus int32 c = (dg / 36524 + 1) * 3 / 4;
1090a070cf53SStephan Aßmus int32 dc = dg - c * 36524;
1091a070cf53SStephan Aßmus int32 db = dc % 1461;
1092a070cf53SStephan Aßmus int32 a = (db / 365 + 1) * 3 / 4;
1093a070cf53SStephan Aßmus int32 da = db - a * 365;
1094a070cf53SStephan Aßmus int32 m = (da * 5 + 308) / 153 - 2;
1095daf3c505SJérôme Duval date.fYear = ((j / 146097) * 400 + c * 100 + (dc / 1461) * 4 + a)
1096daf3c505SJérôme Duval - 4800 + (m + 2) / 12;
1097a070cf53SStephan Aßmus date.fMonth = (m + 2) % 12 + 1;
1098a070cf53SStephan Aßmus date.fDay = int32((da - (m + 4) * 153 / 5 + 122) + 1.5);
1099a070cf53SStephan Aßmus } else if (julianDay >= 0) {
1100a070cf53SStephan Aßmus // http://en.wikipedia.org/wiki/Julian_day#Calculation
1101a070cf53SStephan Aßmus julianDay += 32082;
1102a070cf53SStephan Aßmus int32 d = (4 * julianDay + 3) / 1461;
1103a070cf53SStephan Aßmus int32 e = julianDay - (1461 * d) / 4;
1104a070cf53SStephan Aßmus int32 m = ((5 * e) + 2) / 153;
1105a070cf53SStephan Aßmus date.fDay = e - (153 * m + 2) / 5 + 1;
1106a070cf53SStephan Aßmus date.fMonth = m + 3 - 12 * (m / 10);
1107a070cf53SStephan Aßmus int32 year = d - 4800 + (m / 10);
1108a070cf53SStephan Aßmus if (year <= 0)
1109a070cf53SStephan Aßmus year--;
1110a070cf53SStephan Aßmus date.fYear = year;
1111a070cf53SStephan Aßmus }
1112a070cf53SStephan Aßmus return date;
1113a070cf53SStephan Aßmus }
1114a070cf53SStephan Aßmus
1115a070cf53SStephan Aßmus
1116a070cf53SStephan Aßmus /*!
1117a070cf53SStephan Aßmus Returns true if this date is different from \c date, otherwise false.
1118a070cf53SStephan Aßmus */
1119a070cf53SStephan Aßmus bool
operator !=(const BDate & date) const1120a070cf53SStephan Aßmus BDate::operator!=(const BDate& date) const
1121a070cf53SStephan Aßmus {
1122a070cf53SStephan Aßmus return DateToJulianDay() != date.DateToJulianDay();
1123a070cf53SStephan Aßmus }
1124a070cf53SStephan Aßmus
1125a070cf53SStephan Aßmus
1126a070cf53SStephan Aßmus /*!
1127a070cf53SStephan Aßmus Returns true if this date is equal to \c date, otherwise false.
1128a070cf53SStephan Aßmus */
1129a070cf53SStephan Aßmus bool
operator ==(const BDate & date) const1130a070cf53SStephan Aßmus BDate::operator==(const BDate& date) const
1131a070cf53SStephan Aßmus {
1132a070cf53SStephan Aßmus return DateToJulianDay() == date.DateToJulianDay();
1133a070cf53SStephan Aßmus }
1134a070cf53SStephan Aßmus
1135a070cf53SStephan Aßmus
1136a070cf53SStephan Aßmus /*!
1137a070cf53SStephan Aßmus Returns true if this date is earlier than \c date, otherwise false.
1138a070cf53SStephan Aßmus */
1139a070cf53SStephan Aßmus bool
operator <(const BDate & date) const1140a070cf53SStephan Aßmus BDate::operator<(const BDate& date) const
1141a070cf53SStephan Aßmus {
1142a070cf53SStephan Aßmus return DateToJulianDay() < date.DateToJulianDay();
1143a070cf53SStephan Aßmus }
1144a070cf53SStephan Aßmus
1145a070cf53SStephan Aßmus
1146a070cf53SStephan Aßmus /*!
1147daf3c505SJérôme Duval Returns true if this date is earlier than or equal to \c date, otherwise
1148daf3c505SJérôme Duval false.
1149a070cf53SStephan Aßmus */
1150a070cf53SStephan Aßmus bool
operator <=(const BDate & date) const1151a070cf53SStephan Aßmus BDate::operator<=(const BDate& date) const
1152a070cf53SStephan Aßmus {
1153a070cf53SStephan Aßmus return DateToJulianDay() <= date.DateToJulianDay();
1154a070cf53SStephan Aßmus }
1155a070cf53SStephan Aßmus
1156a070cf53SStephan Aßmus
1157a070cf53SStephan Aßmus /*!
1158a070cf53SStephan Aßmus Returns true if this date is later than \c date, otherwise false.
1159a070cf53SStephan Aßmus */
1160a070cf53SStephan Aßmus bool
operator >(const BDate & date) const1161a070cf53SStephan Aßmus BDate::operator>(const BDate& date) const
1162a070cf53SStephan Aßmus {
1163a070cf53SStephan Aßmus return DateToJulianDay() > date.DateToJulianDay();
1164a070cf53SStephan Aßmus }
1165a070cf53SStephan Aßmus
1166a070cf53SStephan Aßmus
1167a070cf53SStephan Aßmus /*!
1168daf3c505SJérôme Duval Returns true if this date is later than or equal to \c date, otherwise
1169daf3c505SJérôme Duval false.
1170a070cf53SStephan Aßmus */
1171a070cf53SStephan Aßmus bool
operator >=(const BDate & date) const1172a070cf53SStephan Aßmus BDate::operator>=(const BDate& date) const
1173a070cf53SStephan Aßmus {
1174a070cf53SStephan Aßmus return DateToJulianDay() >= date.DateToJulianDay();
1175a070cf53SStephan Aßmus }
1176a070cf53SStephan Aßmus
1177a070cf53SStephan Aßmus
1178a070cf53SStephan Aßmus bool
_SetDate(int32 year,int32 month,int32 day)1179a070cf53SStephan Aßmus BDate::_SetDate(int32 year, int32 month, int32 day)
1180a070cf53SStephan Aßmus {
1181a070cf53SStephan Aßmus fDay = -1;
1182a070cf53SStephan Aßmus fYear = 0;
1183a070cf53SStephan Aßmus fMonth = -1;
1184a070cf53SStephan Aßmus
1185a070cf53SStephan Aßmus bool valid = IsValid(year, month, day);
1186a070cf53SStephan Aßmus if (valid) {
1187a070cf53SStephan Aßmus fDay = day;
1188a070cf53SStephan Aßmus fYear = year;
1189a070cf53SStephan Aßmus fMonth = month;
1190a070cf53SStephan Aßmus }
1191a070cf53SStephan Aßmus
1192a070cf53SStephan Aßmus return valid;
1193a070cf53SStephan Aßmus }
1194a070cf53SStephan Aßmus
1195a070cf53SStephan Aßmus
1196a070cf53SStephan Aßmus int32
_DaysInMonth(int32 year,int32 month)1197daf3c505SJérôme Duval BDate::_DaysInMonth(int32 year, int32 month)
1198a070cf53SStephan Aßmus {
1199a070cf53SStephan Aßmus if (month == 2 && IsLeapYear(year))
1200a070cf53SStephan Aßmus return 29;
1201a070cf53SStephan Aßmus
1202a070cf53SStephan Aßmus const int32 daysInMonth[12] =
1203a070cf53SStephan Aßmus {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
1204a070cf53SStephan Aßmus
1205a070cf53SStephan Aßmus return daysInMonth[month -1];
1206a070cf53SStephan Aßmus }
1207a070cf53SStephan Aßmus
1208a070cf53SStephan Aßmus
1209a070cf53SStephan Aßmus int32
_DateToJulianDay(int32 _year,int32 month,int32 day)1210daf3c505SJérôme Duval BDate::_DateToJulianDay(int32 _year, int32 month, int32 day)
1211a070cf53SStephan Aßmus {
1212a070cf53SStephan Aßmus if (IsValid(_year, month, day)) {
1213a070cf53SStephan Aßmus int32 year = _year;
1214a070cf53SStephan Aßmus if (year < 0) year++;
1215a070cf53SStephan Aßmus
1216a070cf53SStephan Aßmus int32 a = (14 - month) / 12;
1217a070cf53SStephan Aßmus int32 y = year + 4800 - a;
1218a070cf53SStephan Aßmus int32 m = month + (12 * a) - 3;
1219a070cf53SStephan Aßmus
1220a070cf53SStephan Aßmus // http://en.wikipedia.org/wiki/Julian_day#Calculation
1221a070cf53SStephan Aßmus if (year > 1582
1222a070cf53SStephan Aßmus || (year == 1582 && month > 10)
1223a070cf53SStephan Aßmus || (year == 1582 && month == 10 && day >= 15)) {
1224a070cf53SStephan Aßmus return day + (((153 * m) + 2) / 5) + (365 * y) + (y / 4) -
1225a070cf53SStephan Aßmus (y / 100) + (y / 400) - 32045;
1226a070cf53SStephan Aßmus } else if (year < 1582
1227a070cf53SStephan Aßmus || (year == 1582 && month < 10)
1228a070cf53SStephan Aßmus || (year == 1582 && month == 10 && day <= 4)) {
1229a070cf53SStephan Aßmus return day + (((153 * m) + 2) / 5) + (365 * y) + (y / 4) - 32083;
1230a070cf53SStephan Aßmus }
1231a070cf53SStephan Aßmus }
1232a070cf53SStephan Aßmus
1233a070cf53SStephan Aßmus // http://en.wikipedia.org/wiki/Gregorian_calendar:
1234a070cf53SStephan Aßmus // The last day of the Julian calendar was Thursday October 4, 1582
1235a070cf53SStephan Aßmus // and this was followed by the first day of the Gregorian calendar,
1236a070cf53SStephan Aßmus // Friday October 15, 1582 (the cycle of weekdays was not affected).
1237a070cf53SStephan Aßmus return int32(B_ERROR);
1238a070cf53SStephan Aßmus }
1239a070cf53SStephan Aßmus
1240a070cf53SStephan Aßmus
1241a070cf53SStephan Aßmus // #pragma mark - BDateTime
1242a070cf53SStephan Aßmus
1243a070cf53SStephan Aßmus
1244a070cf53SStephan Aßmus /*!
1245a070cf53SStephan Aßmus Constructs a new BDateTime object. IsValid() will return false.
1246a070cf53SStephan Aßmus */
BDateTime()1247a070cf53SStephan Aßmus BDateTime::BDateTime()
1248a070cf53SStephan Aßmus : fDate(),
1249a070cf53SStephan Aßmus fTime()
1250a070cf53SStephan Aßmus {
1251a070cf53SStephan Aßmus }
1252a070cf53SStephan Aßmus
1253a070cf53SStephan Aßmus
1254a070cf53SStephan Aßmus /*!
1255a070cf53SStephan Aßmus Constructs a BDateTime object with \c date and \c time. The return value
1256a070cf53SStephan Aßmus of IsValid() depends on the validity of the passed objects.
1257a070cf53SStephan Aßmus */
BDateTime(const BDate & date,const BTime & time)1258a070cf53SStephan Aßmus BDateTime::BDateTime(const BDate& date, const BTime& time)
1259a070cf53SStephan Aßmus : fDate(date),
1260a070cf53SStephan Aßmus fTime(time)
1261a070cf53SStephan Aßmus {
1262a070cf53SStephan Aßmus }
1263a070cf53SStephan Aßmus
1264a070cf53SStephan Aßmus
1265a070cf53SStephan Aßmus /*!
1266a070cf53SStephan Aßmus Constructs a new BDateTime object. IsValid() will return false.
1267a070cf53SStephan Aßmus */
BDateTime(const BMessage * archive)1268a070cf53SStephan Aßmus BDateTime::BDateTime(const BMessage* archive)
1269a070cf53SStephan Aßmus : fDate(archive),
1270a070cf53SStephan Aßmus fTime(archive)
1271a070cf53SStephan Aßmus {
1272a070cf53SStephan Aßmus }
1273a070cf53SStephan Aßmus
1274a070cf53SStephan Aßmus
1275a070cf53SStephan Aßmus /*!
1276a070cf53SStephan Aßmus Empty destructor.
1277a070cf53SStephan Aßmus */
~BDateTime()1278a070cf53SStephan Aßmus BDateTime::~BDateTime()
1279a070cf53SStephan Aßmus {
1280a070cf53SStephan Aßmus }
1281a070cf53SStephan Aßmus
1282a070cf53SStephan Aßmus
1283a070cf53SStephan Aßmus /*!
1284a070cf53SStephan Aßmus Archives the BDateTime object into the provided BMessage object.
1285a070cf53SStephan Aßmus @returns \c B_OK if all went well.
1286a070cf53SStephan Aßmus \c B_BAD_VALUE, if the message is \c NULL.
1287a070cf53SStephan Aßmus \c other error codes, depending on failure to append
1288a070cf53SStephan Aßmus fields to the message.
1289a070cf53SStephan Aßmus */
1290a070cf53SStephan Aßmus status_t
Archive(BMessage * into) const1291a070cf53SStephan Aßmus BDateTime::Archive(BMessage* into) const
1292a070cf53SStephan Aßmus {
1293a070cf53SStephan Aßmus status_t ret = fDate.Archive(into);
1294a070cf53SStephan Aßmus if (ret == B_OK)
1295a070cf53SStephan Aßmus ret = fTime.Archive(into);
1296a070cf53SStephan Aßmus return ret;
1297a070cf53SStephan Aßmus }
1298a070cf53SStephan Aßmus
1299a070cf53SStephan Aßmus
1300a070cf53SStephan Aßmus /*!
1301a070cf53SStephan Aßmus Returns true if the date time is valid, otherwise false.
1302a070cf53SStephan Aßmus */
1303a070cf53SStephan Aßmus bool
IsValid() const1304a070cf53SStephan Aßmus BDateTime::IsValid() const
1305a070cf53SStephan Aßmus {
1306a070cf53SStephan Aßmus return fDate.IsValid() && fTime.IsValid();
1307a070cf53SStephan Aßmus }
1308a070cf53SStephan Aßmus
1309a070cf53SStephan Aßmus
1310a070cf53SStephan Aßmus /*!
1311a070cf53SStephan Aßmus Returns the current date and time as reported by the system depending on the
1312a070cf53SStephan Aßmus given time_type \c type.
1313a070cf53SStephan Aßmus */
1314a070cf53SStephan Aßmus BDateTime
CurrentDateTime(time_type type)1315a070cf53SStephan Aßmus BDateTime::CurrentDateTime(time_type type)
1316a070cf53SStephan Aßmus {
1317a070cf53SStephan Aßmus return BDateTime(BDate::CurrentDate(type), BTime::CurrentTime(type));
1318a070cf53SStephan Aßmus }
1319a070cf53SStephan Aßmus
1320a070cf53SStephan Aßmus
1321a070cf53SStephan Aßmus /*!
1322a070cf53SStephan Aßmus Sets the current date and time of this object to \c date and \c time.
1323a070cf53SStephan Aßmus */
1324a070cf53SStephan Aßmus void
SetDateTime(const BDate & date,const BTime & time)1325a070cf53SStephan Aßmus BDateTime::SetDateTime(const BDate& date, const BTime& time)
1326a070cf53SStephan Aßmus {
1327a070cf53SStephan Aßmus fDate = date;
1328a070cf53SStephan Aßmus fTime = time;
1329a070cf53SStephan Aßmus }
1330a070cf53SStephan Aßmus
1331a070cf53SStephan Aßmus
1332a070cf53SStephan Aßmus /*!
1333a070cf53SStephan Aßmus Returns the current date of this object.
1334a070cf53SStephan Aßmus */
1335bbba047cSStephan Aßmus BDate&
Date()1336bbba047cSStephan Aßmus BDateTime::Date()
1337bbba047cSStephan Aßmus {
1338bbba047cSStephan Aßmus return fDate;
1339bbba047cSStephan Aßmus }
1340bbba047cSStephan Aßmus
1341bbba047cSStephan Aßmus
1342bbba047cSStephan Aßmus /*!
1343bbba047cSStephan Aßmus Returns the current date of this object.
1344bbba047cSStephan Aßmus */
1345bbba047cSStephan Aßmus const BDate&
Date() const1346a070cf53SStephan Aßmus BDateTime::Date() const
1347a070cf53SStephan Aßmus {
1348a070cf53SStephan Aßmus return fDate;
1349a070cf53SStephan Aßmus }
1350a070cf53SStephan Aßmus
1351a070cf53SStephan Aßmus
1352a070cf53SStephan Aßmus /*!
1353a070cf53SStephan Aßmus Set the current date of this object to \c date.
1354a070cf53SStephan Aßmus */
1355a070cf53SStephan Aßmus void
SetDate(const BDate & date)1356a070cf53SStephan Aßmus BDateTime::SetDate(const BDate& date)
1357a070cf53SStephan Aßmus {
1358a070cf53SStephan Aßmus fDate = date;
1359a070cf53SStephan Aßmus }
1360a070cf53SStephan Aßmus
1361a070cf53SStephan Aßmus
1362a070cf53SStephan Aßmus /*!
1363a070cf53SStephan Aßmus Returns the current time of this object.
1364a070cf53SStephan Aßmus */
1365bbba047cSStephan Aßmus BTime&
Time()1366bbba047cSStephan Aßmus BDateTime::Time()
1367bbba047cSStephan Aßmus {
1368bbba047cSStephan Aßmus return fTime;
1369bbba047cSStephan Aßmus }
1370bbba047cSStephan Aßmus
1371bbba047cSStephan Aßmus
1372bbba047cSStephan Aßmus /*!
1373bbba047cSStephan Aßmus Returns the current time of this object.
1374bbba047cSStephan Aßmus */
1375bbba047cSStephan Aßmus const BTime&
Time() const1376a070cf53SStephan Aßmus BDateTime::Time() const
1377a070cf53SStephan Aßmus {
1378a070cf53SStephan Aßmus return fTime;
1379a070cf53SStephan Aßmus }
1380a070cf53SStephan Aßmus
1381a070cf53SStephan Aßmus
1382a070cf53SStephan Aßmus /*!
1383a070cf53SStephan Aßmus Sets the current time of this object to \c time.
1384a070cf53SStephan Aßmus */
1385a070cf53SStephan Aßmus void
SetTime(const BTime & time)1386a070cf53SStephan Aßmus BDateTime::SetTime(const BTime& time)
1387a070cf53SStephan Aßmus {
1388a070cf53SStephan Aßmus fTime = time;
1389a070cf53SStephan Aßmus }
1390a070cf53SStephan Aßmus
1391a070cf53SStephan Aßmus
1392a070cf53SStephan Aßmus /*!
1393a070cf53SStephan Aßmus Returns the current date and time converted to seconds since
1394a070cf53SStephan Aßmus 1.1.1970 - 00:00:00. If the current date is before 1.1.1970 the function
1395a070cf53SStephan Aßmus returns -1;
1396a070cf53SStephan Aßmus */
1397d05f9e2dSAdrien Destugues time_t
Time_t() const1398a070cf53SStephan Aßmus BDateTime::Time_t() const
1399a070cf53SStephan Aßmus {
1400a070cf53SStephan Aßmus BDate date(1970, 1, 1);
1401a070cf53SStephan Aßmus if (date.Difference(fDate) < 0)
1402a070cf53SStephan Aßmus return -1;
1403a070cf53SStephan Aßmus
1404a070cf53SStephan Aßmus tm tm_struct;
1405a070cf53SStephan Aßmus
1406a070cf53SStephan Aßmus tm_struct.tm_hour = fTime.Hour();
1407a070cf53SStephan Aßmus tm_struct.tm_min = fTime.Minute();
1408a070cf53SStephan Aßmus tm_struct.tm_sec = fTime.Second();
1409a070cf53SStephan Aßmus
1410a070cf53SStephan Aßmus tm_struct.tm_year = fDate.Year() - 1900;
1411a070cf53SStephan Aßmus tm_struct.tm_mon = fDate.Month() - 1;
1412a070cf53SStephan Aßmus tm_struct.tm_mday = fDate.Day();
1413a070cf53SStephan Aßmus
1414daf3c505SJérôme Duval // set less 0 as we won't use it
1415a070cf53SStephan Aßmus tm_struct.tm_isdst = -1;
1416a070cf53SStephan Aßmus
1417a070cf53SStephan Aßmus // return secs_since_jan1_1970 or -1 on error
1418d05f9e2dSAdrien Destugues return mktime(&tm_struct);
1419a070cf53SStephan Aßmus }
1420a070cf53SStephan Aßmus
1421a070cf53SStephan Aßmus
1422a070cf53SStephan Aßmus /*!
1423a070cf53SStephan Aßmus Sets the current date and time converted from seconds since
1424a070cf53SStephan Aßmus 1.1.1970 - 00:00:00.
1425a070cf53SStephan Aßmus */
1426a070cf53SStephan Aßmus void
SetTime_t(time_t seconds)1427d05f9e2dSAdrien Destugues BDateTime::SetTime_t(time_t seconds)
1428a070cf53SStephan Aßmus {
1429d05f9e2dSAdrien Destugues time_t timePart = seconds % kSecondsPerDay;
1430d05f9e2dSAdrien Destugues if (timePart < 0) {
1431d05f9e2dSAdrien Destugues timePart += kSecondsPerDay;
1432d05f9e2dSAdrien Destugues seconds -= kSecondsPerDay;
1433d05f9e2dSAdrien Destugues }
1434d05f9e2dSAdrien Destugues
1435a070cf53SStephan Aßmus BTime time;
1436dbd4f8c4SAdrien Destugues time.AddSeconds(timePart);
1437a070cf53SStephan Aßmus fTime.SetTime(time);
1438a070cf53SStephan Aßmus
1439a070cf53SStephan Aßmus BDate date(1970, 1, 1);
1440a070cf53SStephan Aßmus date.AddDays(seconds / kSecondsPerDay);
1441a070cf53SStephan Aßmus fDate.SetDate(date);
1442a070cf53SStephan Aßmus }
1443a070cf53SStephan Aßmus
1444a070cf53SStephan Aßmus
1445a070cf53SStephan Aßmus /*!
1446a070cf53SStephan Aßmus Returns true if this datetime is different from \c dateTime, otherwise false.
1447a070cf53SStephan Aßmus */
1448a070cf53SStephan Aßmus bool
operator !=(const BDateTime & dateTime) const1449a070cf53SStephan Aßmus BDateTime::operator!=(const BDateTime& dateTime) const
1450a070cf53SStephan Aßmus {
1451a070cf53SStephan Aßmus return fTime != dateTime.fTime && fDate != dateTime.fDate;
1452a070cf53SStephan Aßmus }
1453a070cf53SStephan Aßmus
1454a070cf53SStephan Aßmus
1455a070cf53SStephan Aßmus /*!
1456a070cf53SStephan Aßmus Returns true if this datetime is equal to \c dateTime, otherwise false.
1457a070cf53SStephan Aßmus */
1458a070cf53SStephan Aßmus bool
operator ==(const BDateTime & dateTime) const1459a070cf53SStephan Aßmus BDateTime::operator==(const BDateTime& dateTime) const
1460a070cf53SStephan Aßmus {
1461a070cf53SStephan Aßmus return fTime == dateTime.fTime && fDate == dateTime.fDate;
1462a070cf53SStephan Aßmus }
1463a070cf53SStephan Aßmus
1464a070cf53SStephan Aßmus
1465a070cf53SStephan Aßmus /*!
1466a070cf53SStephan Aßmus Returns true if this datetime is earlier than \c dateTime, otherwise false.
1467a070cf53SStephan Aßmus */
1468a070cf53SStephan Aßmus bool
operator <(const BDateTime & dateTime) const1469a070cf53SStephan Aßmus BDateTime::operator<(const BDateTime& dateTime) const
1470a070cf53SStephan Aßmus {
1471bbba047cSStephan Aßmus if (fDate < dateTime.fDate)
1472bbba047cSStephan Aßmus return true;
1473bbba047cSStephan Aßmus if (fDate == dateTime.fDate)
1474bbba047cSStephan Aßmus return fTime < dateTime.fTime;
1475bbba047cSStephan Aßmus return false;
1476a070cf53SStephan Aßmus }
1477a070cf53SStephan Aßmus
1478a070cf53SStephan Aßmus
1479a070cf53SStephan Aßmus /*!
1480a070cf53SStephan Aßmus Returns true if this datetime is earlier than or equal to \c dateTime,
1481a070cf53SStephan Aßmus otherwise false.
1482a070cf53SStephan Aßmus */
1483a070cf53SStephan Aßmus bool
operator <=(const BDateTime & dateTime) const1484a070cf53SStephan Aßmus BDateTime::operator<=(const BDateTime& dateTime) const
1485a070cf53SStephan Aßmus {
1486bbba047cSStephan Aßmus if (fDate < dateTime.fDate)
1487bbba047cSStephan Aßmus return true;
1488bbba047cSStephan Aßmus if (fDate == dateTime.fDate)
1489bbba047cSStephan Aßmus return fTime <= dateTime.fTime;
1490bbba047cSStephan Aßmus return false;
1491a070cf53SStephan Aßmus }
1492a070cf53SStephan Aßmus
1493a070cf53SStephan Aßmus
1494a070cf53SStephan Aßmus /*!
1495a070cf53SStephan Aßmus Returns true if this datetime is later than \c dateTime, otherwise false.
1496a070cf53SStephan Aßmus */
1497a070cf53SStephan Aßmus bool
operator >(const BDateTime & dateTime) const1498a070cf53SStephan Aßmus BDateTime::operator>(const BDateTime& dateTime) const
1499a070cf53SStephan Aßmus {
1500bbba047cSStephan Aßmus if (fDate > dateTime.fDate)
1501bbba047cSStephan Aßmus return true;
1502bbba047cSStephan Aßmus if (fDate == dateTime.fDate)
1503bbba047cSStephan Aßmus return fTime > dateTime.fTime;
1504bbba047cSStephan Aßmus return false;
1505a070cf53SStephan Aßmus }
1506a070cf53SStephan Aßmus
1507a070cf53SStephan Aßmus
1508a070cf53SStephan Aßmus /*!
1509a070cf53SStephan Aßmus Returns true if this datetime is later than or equal to \c dateTime,
1510a070cf53SStephan Aßmus otherwise false.
1511a070cf53SStephan Aßmus */
1512a070cf53SStephan Aßmus bool
operator >=(const BDateTime & dateTime) const1513a070cf53SStephan Aßmus BDateTime::operator>=(const BDateTime& dateTime) const
1514a070cf53SStephan Aßmus {
1515bbba047cSStephan Aßmus if (fDate > dateTime.fDate)
1516bbba047cSStephan Aßmus return true;
1517bbba047cSStephan Aßmus if (fDate == dateTime.fDate)
1518bbba047cSStephan Aßmus return fTime >= dateTime.fTime;
1519bbba047cSStephan Aßmus return false;
1520a070cf53SStephan Aßmus }
1521a070cf53SStephan Aßmus
152229e8fa59SJohn Scipione } /* namespace BPrivate */
1523