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