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