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