4
Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
7
Author: Mircea Oancea <mircea@jupiter.elcom.pub.ro>
9
This file is part of libFoundation.
11
Permission to use, copy, modify, and distribute this software and its
12
documentation for any purpose and without fee is hereby granted, provided
13
that the above copyright notice appear in all copies and that both that
14
copyright notice and this permission notice appear in supporting
17
We disclaim all warranties with regard to this software, including all
18
implied warranties of merchantability and fitness, in no event shall
19
we be liable for any special, indirect or consequential damages or any
20
damages whatsoever resulting from loss of use, data or profits, whether in
21
an action of contract, negligence or other tortious action, arising out of
22
or in connection with the use or performance of this software.
28
# include <sys/time.h>
42
#include <Foundation/NSString.h>
43
#include <Foundation/NSDate.h>
44
#include <Foundation/NSCoder.h>
45
#include <Foundation/NSUtilities.h>
47
#include "NSConcreteDate.h"
48
#include "NSCalendarDate.h"
50
#if HAVE_GETLOCALTIME || defined(__MINGW32__)
51
static void Date2Long(int theMonth, int theDay, int theYear, long *theDate);
52
#define DATE_OFFSET 730486 /* Number of days from January 1, 1
56
@implementation NSDate
58
static NSDate *distantFuture = nil, *distantPast = nil;
66
+ (id)allocWithZone:(NSZone *)zone
68
return NSAllocateObject( (self == [NSDate class]) ?
69
[NSConcreteDate class] : self, 0, zone);
74
return AUTORELEASE([[self alloc] init]);
77
+ (NSDate *)dateWithTimeIntervalSinceNow:(NSTimeInterval)secs
79
return AUTORELEASE([[self alloc] initWithTimeIntervalSinceNow:secs]);
82
+ (NSDate *)dateWithTimeIntervalSinceReferenceDate:(NSTimeInterval)secs
84
return AUTORELEASE([[self alloc]
85
initWithTimeIntervalSinceReferenceDate:secs]);
88
+ (NSDate *)dateWithTimeIntervalSince1970:(NSTimeInterval)seconds
90
return AUTORELEASE([[self alloc] initWithTimeIntervalSince1970:seconds]);
93
+ (NSDate *)distantFuture
95
if (distantFuture == nil) {
96
distantFuture = [[self alloc]
97
initWithTimeIntervalSinceReferenceDate:DISTANT_FUTURE];
102
+ (NSDate *)distantPast
104
if (distantPast == nil) {
105
distantPast = [[self alloc]
106
initWithTimeIntervalSinceReferenceDate:DISTANT_PAST];
116
- (id)initWithTimeIntervalSinceReferenceDate:(NSTimeInterval)secsToBeAdded
118
[self subclassResponsibility:_cmd];
122
- (id)initWithString:(NSString *)description
124
id cal = [[NSCalendarDate alloc] initWithString:description];
125
[self initWithTimeIntervalSinceReferenceDate:
126
[cal timeIntervalSinceReferenceDate]];
127
RELEASE(cal); cal = nil;
131
- (NSDate *)initWithTimeInterval:(NSTimeInterval)secsToBeAdded
132
sinceDate:(NSDate *)anotherDate
134
return [self initWithTimeIntervalSinceReferenceDate:
135
(secsToBeAdded + [anotherDate timeIntervalSinceReferenceDate])];
138
- (NSDate *)initWithTimeIntervalSinceNow:(NSTimeInterval)secsToBeAddedToNow
140
[self initWithTimeIntervalSinceReferenceDate:
141
(secsToBeAddedToNow + [NSDate timeIntervalSinceReferenceDate])];
145
- (id)initWithTimeIntervalSince1970:(NSTimeInterval)seconds
147
[self initWithTimeIntervalSinceReferenceDate: seconds + UNIX_OFFSET];
153
- (id)copyWithZone:(NSZone *)zone
155
if (NSShouldRetainWithZone(self, zone))
158
return [[[self class] alloc] initWithTimeIntervalSinceReferenceDate:
159
[self timeIntervalSinceReferenceDate]];
162
/* Representing Dates */
164
- (NSString *)propertyListStringWithLocale:(NSDictionary *)_locale
165
indent:(unsigned int)_indent
167
return [[self descriptionWithLocale:_locale] stringRepresentation];
170
- (NSString *)stringRepresentation {
171
return [[self description] stringRepresentation];
174
- (NSString *)description
176
return [[NSCalendarDate dateWithTimeIntervalSinceReferenceDate:
177
[self timeIntervalSinceReferenceDate]] description];
180
- (NSString *)descriptionWithCalendarFormat:(NSString *)formatString
181
timeZone:(NSTimeZone *)aTimeZone
182
locale:(NSDictionary *)locale
184
id calendar = [NSCalendarDate dateWithTimeIntervalSinceReferenceDate:
185
[self timeIntervalSinceReferenceDate]];
186
[calendar setTimeZone:aTimeZone];
187
return [calendar descriptionWithCalendarFormat:formatString
188
timeZone:aTimeZone locale:locale];
191
- (NSString *)descriptionWithLocale:(NSDictionary *)locale
193
id calendar = [NSCalendarDate dateWithTimeIntervalSinceReferenceDate:
194
[self timeIntervalSinceReferenceDate]];
195
return [calendar descriptionWithLocale:locale];
198
/* Adding and Getting Intervals */
200
+ (NSTimeInterval)timeIntervalSinceReferenceDate
202
#if HAVE_GETTIMEOFDAY
203
/* eg: used on SuSE Linux */
204
NSTimeInterval theTime = UNIX_OFFSET;
206
struct timezone tzp = { 0, 0 };
208
gettimeofday(&tp, &tzp);
210
/* theTime contains 1970 (Unix ref time) and gets added seconds and micros */
211
theTime += tp.tv_sec;
212
theTime += (double)tp.tv_usec / 1000000.0;
214
#if 0 && defined(__svr4__)
216
extern time_t timezone, altzone;
217
theTime -= (double)altzone;
220
# if !defined(__linux__)
221
/* this is not to be used on Linux, see 'gettimeofday' man page */
222
theTime -= tzp.tz_minuteswest * 60 + (tzp.tz_dsttime ? 3600 : 0);
228
#elif HAVE_GETLOCALTIME
230
NSTimeInterval theTime = 0;
235
Date2Long(tp.wMonth, tp.wDay, tp.wYear, &date);
237
theTime = ((NSTimeInterval)date - DATE_OFFSET) * 86400 +
238
tp.wHour * 3600 + tp.wMinute * 60 + tp.wSecond +
239
tp.wMilliseconds / 1000.0 ;
242
#elif defined(__MINGW32__)
243
NSTimeInterval theTime = 0;
248
Date2Long(tp.wMonth, tp.wDay, tp.wYear, &date);
250
theTime = ((NSTimeInterval)date - DATE_OFFSET) * 86400 +
251
tp.wHour * 3600 + tp.wMinute * 60 + tp.wSecond +
252
tp.wMilliseconds / 1000.0 ;
255
#error no time function
259
- (NSTimeInterval)timeIntervalSinceReferenceDate
261
[self subclassResponsibility:_cmd];
265
- (NSTimeInterval)timeIntervalSinceDate:(NSDate *)anotherDate;
267
return [self timeIntervalSinceReferenceDate] -
268
[anotherDate timeIntervalSinceReferenceDate];
271
- (NSTimeInterval)timeIntervalSinceNow
273
return [self timeIntervalSinceReferenceDate] -
274
[NSDate timeIntervalSinceReferenceDate];
277
- (id)addTimeInterval:(NSTimeInterval)seconds
279
return AUTORELEASE([[[self class] alloc]
280
initWithTimeInterval:seconds sinceDate:self]);
283
- (NSTimeInterval)timeIntervalSince1970
285
return [self timeIntervalSinceReferenceDate] - UNIX_OFFSET;
288
/* Comparing Dates */
290
- (NSDate *)earlierDate:(NSDate *)anotherDate
292
if (!anotherDate) return self;
294
return [self compare:anotherDate] == NSOrderedAscending?
298
- (NSDate *)laterDate:(NSDate *)anotherDate
300
if (!anotherDate) return self;
302
return [self compare:anotherDate] == NSOrderedAscending ?
306
- (NSComparisonResult)compare:(NSDate *)other
308
[self subclassResponsibility:_cmd];
309
return NSOrderedSame;
312
- (BOOL)isEqual:other
314
return [other isKindOfClass:[NSDate class]] &&
315
[self isEqualToDate:other];
318
- (BOOL)isEqualToDate:other
320
return [self compare:other] == NSOrderedSame;
323
/* Converting to an NSCalendar Object */
324
- (NSCalendarDate *)dateWithCalendarFormat:(NSString *)aFormatString
325
timeZone:(NSTimeZone *)aTimeZone
327
id new = AUTORELEASE([[NSCalendarDate alloc]
328
initWithTimeIntervalSinceReferenceDate:
329
[self timeIntervalSinceReferenceDate]]);
330
[new setCalendarFormat:aFormatString];
331
[new setTimeZone:aTimeZone];
336
+ (id)dateWithNaturalLanguageString:(NSString *)_string
338
return [self dateWithNaturalLanguageString:_string
342
+ (id)dateWithNaturalLanguageString:(NSString *)_string
343
locale:(NSDictionary *)_locale
345
return [self notImplemented:_cmd];
349
- (Class)classForCoder
351
return [NSDate class];
354
- (void)encodeWithCoder:(NSCoder *)aCoder
356
NSTimeInterval timeDiff = [self timeIntervalSinceReferenceDate];
358
[aCoder encodeValueOfObjCType:@encode(NSTimeInterval) at:&timeDiff];
361
- (id)initWithCoder:(NSCoder *)aDecoder
363
NSTimeInterval timeDiff;
365
[aDecoder decodeValueOfObjCType:@encode(NSTimeInterval) at:&timeDiff];
366
[self initWithTimeIntervalSinceReferenceDate:timeDiff];
372
#if HAVE_GETLOCALTIME || defined(__MINGW32__)
374
static int nDays[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
375
#define bisect(a) ((a) % 4 == 0 && ((a) % 400 == 0 || (a) % 100 ))
376
#define nr_bisect(a) ((a - 1) / 4 - nr_nebisect(a - 1))
378
static int nr_nebisect(int a)
383
for(i = 100; i <= a; i += 100)
384
ret += (i % 400 != 0);
388
static void Date2Long(int theMonth, int theDay, int theYear, long *theDate)
390
long base, offset = 0;
393
base = ((long)theYear - 1) * 365 + nr_bisect(theYear);
394
for (i = 1; i < theMonth; i++)
395
offset += nDays[i - 1];
397
if (theMonth > 2 && bisect(theYear))
399
*theDate = base + offset;