mirror of
https://github.com/gnustep/libs-base.git
synced 2025-05-11 08:40:44 +00:00
New file.
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@1884 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
parent
b2d55b6c2c
commit
aead21cd6d
2 changed files with 879 additions and 0 deletions
753
Source/NSCalendarDate.m
Normal file
753
Source/NSCalendarDate.m
Normal file
|
@ -0,0 +1,753 @@
|
|||
/* Implementation for NSCalendarDate for GNUstep
|
||||
Copyright (C) 1996 Free Software Foundation, Inc.
|
||||
|
||||
Author: Scott Christley <scottc@net-community.com>
|
||||
Date: October 1996
|
||||
|
||||
This file is part of the GNUstep Base Library.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the Free
|
||||
Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include <gnustep/base/NSDate.h>
|
||||
#include <gnustep/base/NSString.h>
|
||||
#include <gnustep/base/NSException.h>
|
||||
|
||||
#ifndef __WIN32__
|
||||
#include <time.h>
|
||||
#endif /* !__WIN32__ */
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#ifndef __WIN32__
|
||||
#include <sys/time.h>
|
||||
#endif /* !__WIN32__ */
|
||||
|
||||
// Absolute Gregorian date for NSDate reference date Jan 01 2001
|
||||
//
|
||||
// N = 1; // day of month
|
||||
// N = N + 0; // days in prior months for year
|
||||
// N = N + // days this year
|
||||
// + 365 * (year - 1) // days in previous years ignoring leap days
|
||||
// + (year - 1)/4 // Julian leap days before this year...
|
||||
// - (year - 1)/100 // ...minus prior century years...
|
||||
// + (year - 1)/400 // ...plus prior years divisible by 400
|
||||
|
||||
#define GREGORIAN_REFERENCE 730486
|
||||
|
||||
@implementation NSCalendarDate
|
||||
|
||||
|
||||
//
|
||||
// Getting an NSCalendar Date
|
||||
//
|
||||
+ (NSCalendarDate *)calendarDate
|
||||
{
|
||||
return [[[self alloc] init] autorelease];
|
||||
}
|
||||
|
||||
+ (NSCalendarDate *)dateWithString:(NSString *)description
|
||||
calendarFormat:(NSString *)format
|
||||
{
|
||||
NSCalendarDate *d = [[NSCalendarDate alloc] initWithString: description
|
||||
calendarFormat: format];
|
||||
return [d autorelease];
|
||||
}
|
||||
|
||||
+ (NSCalendarDate *)dateWithString:(NSString *)description
|
||||
calendarFormat:(NSString *)format
|
||||
locale:(NSDictionary *)dictionary
|
||||
{
|
||||
NSCalendarDate *d = [[NSCalendarDate alloc] initWithString: description
|
||||
calendarFormat: format
|
||||
locale: dictionary];
|
||||
return [d autorelease];
|
||||
}
|
||||
|
||||
+ (NSCalendarDate *)dateWithYear:(int)year
|
||||
month:(unsigned int)month
|
||||
day:(unsigned int)day
|
||||
hour:(unsigned int)hour
|
||||
minute:(unsigned int)minute
|
||||
second:(unsigned int)second
|
||||
timeZone:(NSTimeZone *)aTimeZone
|
||||
{
|
||||
NSCalendarDate *d = [[NSCalendarDate alloc] initWithYear: year
|
||||
month: month
|
||||
day: day
|
||||
hour: hour
|
||||
minute: minute
|
||||
second: second
|
||||
timeZone: aTimeZone];
|
||||
return [d autorelease];
|
||||
}
|
||||
|
||||
// Initializing an NSCalendar Date
|
||||
- (id)initWithString:(NSString *)description
|
||||
{
|
||||
// +++ What is the locale?
|
||||
return [self initWithString: description
|
||||
calendarFormat: @"%Y-%m-%d %H:%M:%S %Z"
|
||||
locale: nil];
|
||||
}
|
||||
|
||||
- (id)initWithString:(NSString *)description
|
||||
calendarFormat:(NSString *)format
|
||||
{
|
||||
// ++ What is the locale?
|
||||
return [self initWithString: description
|
||||
calendarFormat: format
|
||||
locale: nil];
|
||||
}
|
||||
|
||||
//
|
||||
// This function could possibly be written better
|
||||
// but it works ok; currently ignores locale
|
||||
// information and some specifiers.
|
||||
//
|
||||
- (id)initWithString:(NSString *)description
|
||||
calendarFormat:(NSString *)format
|
||||
locale:(NSDictionary *)dictionary
|
||||
{
|
||||
const char *d = [description cString];
|
||||
const char *f = [format cString];
|
||||
char *newf;
|
||||
int lf = strlen(f);
|
||||
BOOL mtag = NO, dtag = NO, ycent = NO;
|
||||
char ms[80] = "", ds[80] = "";
|
||||
int yd = 0, md = 0, dd = 0, hd = 0, mnd = 0, sd = 0;
|
||||
void *pntr[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
|
||||
int order;
|
||||
int yord = 0, mord = 0, dord = 0, hord = 0, mnord = 0, sord = 0;
|
||||
int i;
|
||||
|
||||
// If either the string or format is nil then raise exception
|
||||
if (!description)
|
||||
[NSException raise: NSInvalidArgumentException
|
||||
format: @"NSCalendar date description is nil"];
|
||||
if (!format)
|
||||
[NSException raise: NSInvalidArgumentException
|
||||
format: @"NSCalendar date format is nil"];
|
||||
|
||||
// The strftime specifiers
|
||||
// %a abbreviated weekday name according to locale
|
||||
// %A full weekday name according to locale
|
||||
// %b abbreviated month name according to locale
|
||||
// %B full month name according to locale
|
||||
// %d day of month as decimal number
|
||||
// %H hour as a decimal number using 24-hour clock
|
||||
// %I hour as a decimal number using 12-hour clock
|
||||
// %j day of year as a decimal number
|
||||
// %m month as decimal number
|
||||
// %M minute as decimal number
|
||||
// %p 'am' or 'pm'
|
||||
// %S second as decimal number
|
||||
// %U week of the current year as decimal number (Sunday first day)
|
||||
// %W week of the current year as decimal number (Monday first day)
|
||||
// %w day of the week as decimal number (Sunday = 0)
|
||||
// %y year as a decimal number without century
|
||||
// %Y year as a decimal number with century
|
||||
// %Z time zone
|
||||
// %% literal % character
|
||||
|
||||
// Find the order of date elements
|
||||
// and translate format string into scanf ready string
|
||||
order = 1;
|
||||
newf = malloc(lf+1);
|
||||
for (i = 0;i < lf; ++i)
|
||||
{
|
||||
newf[i] = f[i];
|
||||
|
||||
// Only care about a format specifier
|
||||
if (f[i] == '%')
|
||||
{
|
||||
// check the character that comes after
|
||||
switch (f[i+1])
|
||||
{
|
||||
// skip literal %
|
||||
case '%':
|
||||
++i;
|
||||
newf[i] = f[i];
|
||||
break;
|
||||
|
||||
// is it the year
|
||||
case 'Y':
|
||||
ycent = YES;
|
||||
case 'y':
|
||||
yord = order;
|
||||
++order;
|
||||
++i;
|
||||
newf[i] = 'd';
|
||||
pntr[yord] = (void *)&yd;
|
||||
break;
|
||||
|
||||
// is it the month
|
||||
case 'b':
|
||||
case 'B':
|
||||
mtag = YES; // Month is character string
|
||||
case 'm':
|
||||
mord = order;
|
||||
++order;
|
||||
++i;
|
||||
if (mtag)
|
||||
{
|
||||
newf[i] = 's';
|
||||
pntr[mord] = (void *)ms;
|
||||
}
|
||||
else
|
||||
{
|
||||
newf[i] = 'd';
|
||||
pntr[mord] = (void *)&md;
|
||||
}
|
||||
break;
|
||||
|
||||
// is it the day
|
||||
case 'a':
|
||||
case 'A':
|
||||
dtag = YES; // Day is character string
|
||||
case 'd':
|
||||
case 'j':
|
||||
case 'w':
|
||||
dord = order;
|
||||
++order;
|
||||
++i;
|
||||
if (dtag)
|
||||
{
|
||||
newf[i] = 's';
|
||||
pntr[dord] = (void *)ds;
|
||||
}
|
||||
else
|
||||
{
|
||||
newf[i] = 'd';
|
||||
pntr[dord] = (void *)ⅆ
|
||||
}
|
||||
break;
|
||||
|
||||
// is it the hour
|
||||
case 'H':
|
||||
case 'I':
|
||||
hord = order;
|
||||
++order;
|
||||
++i;
|
||||
newf[i] = 'd';
|
||||
pntr[hord] = (void *)&hd;
|
||||
break;
|
||||
|
||||
// is it the minute
|
||||
case 'M':
|
||||
mnord = order;
|
||||
++order;
|
||||
++i;
|
||||
newf[i] = 'd';
|
||||
pntr[mnord] = (void *)&mnd;
|
||||
break;
|
||||
|
||||
// is it the second
|
||||
case 'S':
|
||||
sord = order;
|
||||
++order;
|
||||
++i;
|
||||
newf[i] = 'd';
|
||||
pntr[sord] = (void *)&sd;
|
||||
break;
|
||||
|
||||
// Anything else is an invalid format
|
||||
default:
|
||||
free(newf);
|
||||
[NSException raise: NSInvalidArgumentException
|
||||
format: @"Invalid NSCalendar date, specifier %c not recognized in format %s", f[i+1], f];
|
||||
}
|
||||
}
|
||||
}
|
||||
newf[lf] = '\0';
|
||||
|
||||
// Have sscanf parse and retrieve the values for us
|
||||
if (order != 1)
|
||||
sscanf(d, newf, pntr[1], pntr[2], pntr[3], pntr[4], pntr[5], pntr[6],
|
||||
pntr[7], pntr[8], pntr[9]);
|
||||
else
|
||||
// nothing in the string?
|
||||
;
|
||||
|
||||
// Put century on year if need be
|
||||
// +++ How do we be year 2000 compliant?
|
||||
if (!ycent)
|
||||
yd += 1900;
|
||||
|
||||
// Possibly convert month from string to decimal number
|
||||
// +++ how do we take locale into account?
|
||||
if (mtag)
|
||||
{
|
||||
}
|
||||
|
||||
// Possibly convert day from string to decimal number
|
||||
// +++ how do we take locale into account?
|
||||
if (dtag)
|
||||
{
|
||||
}
|
||||
|
||||
// +++ We need to take 'am' and 'pm' into account
|
||||
|
||||
// +++ then there is the time zone
|
||||
|
||||
free(newf);
|
||||
|
||||
return [self initWithYear: yd month: md day: dd hour: hd
|
||||
minute: mnd second: sd
|
||||
timeZone: [NSTimeZone defaultTimeZone]];
|
||||
}
|
||||
|
||||
- (id)initWithYear:(int)year
|
||||
month:(unsigned int)month
|
||||
day:(unsigned int)day
|
||||
hour:(unsigned int)hour
|
||||
minute:(unsigned int)minute
|
||||
second:(unsigned int)second
|
||||
timeZone:(NSTimeZone *)aTimeZone
|
||||
{
|
||||
int a;
|
||||
NSTimeInterval s;
|
||||
|
||||
a = [self absoluteGregorianDay: day month: month year: year];
|
||||
|
||||
a -= GREGORIAN_REFERENCE;
|
||||
s = (double)a * 86400;
|
||||
s += hour * 3600;
|
||||
s += minute * 60;
|
||||
s += second;
|
||||
|
||||
// +++ adjust for time zone
|
||||
time_zone = (NSTimeZoneDetail *)aTimeZone;
|
||||
|
||||
return [self initWithTimeIntervalSinceReferenceDate: s];
|
||||
}
|
||||
|
||||
// Defalut initializer
|
||||
- (id)initWithTimeIntervalSinceReferenceDate:(NSTimeInterval)seconds
|
||||
{
|
||||
[super initWithTimeIntervalSinceReferenceDate: seconds];
|
||||
if (!calendar_format)
|
||||
calendar_format = @"%Y-%m-%d %H:%M:%S %Z";
|
||||
if (!time_zone)
|
||||
time_zone = [NSTimeZone defaultTimeZone];
|
||||
return self;
|
||||
}
|
||||
|
||||
// Retreiving Date Elements
|
||||
- (void)getYear:(int *)year month:(int *)month day:(int *)day
|
||||
hour:(int *)hour minute:(int *)minute second:(int *)second
|
||||
{
|
||||
int h, m;
|
||||
double a, b, c, d = [self dayOfCommonEra];
|
||||
|
||||
// Calculate year, month, and day
|
||||
[self gregorianDateFromAbsolute: d day: day month: month year: year];
|
||||
|
||||
// Calculate hour, minute, and seconds
|
||||
d -= GREGORIAN_REFERENCE;
|
||||
d *= 86400;
|
||||
a = abs(d - seconds_since_ref);
|
||||
b = a / 3600;
|
||||
*hour = (int)b;
|
||||
h = *hour;
|
||||
h = h * 3600;
|
||||
b = a - h;
|
||||
b = b / 60;
|
||||
*minute = (int)b;
|
||||
m = *minute;
|
||||
m = m * 60;
|
||||
c = a - h - m;
|
||||
*second = (int)c;
|
||||
}
|
||||
|
||||
- (int)dayOfCommonEra
|
||||
{
|
||||
double a;
|
||||
int r;
|
||||
|
||||
// Get reference date in terms of days
|
||||
a = seconds_since_ref / 86400.0;
|
||||
// Offset by Gregorian reference
|
||||
a += GREGORIAN_REFERENCE;
|
||||
r = (int)a;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
- (int)dayOfMonth
|
||||
{
|
||||
int m, d, y;
|
||||
|
||||
[self gregorianDateFromAbsolute: [self dayOfCommonEra]
|
||||
day: &d month: &m year: &y];
|
||||
|
||||
return d;
|
||||
}
|
||||
|
||||
- (int)dayOfWeek
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
- (int)dayOfYear
|
||||
{
|
||||
int m, d, y, days, i;
|
||||
|
||||
[self gregorianDateFromAbsolute: [self dayOfCommonEra]
|
||||
day: &d month: &m year: &y];
|
||||
days = d;
|
||||
for (i = m - 1; i > 0; i--) // days in prior months this year
|
||||
days = days + [self lastDayOfGregorianMonth: i year: y];
|
||||
|
||||
return days;
|
||||
}
|
||||
|
||||
- (int)hourOfDay
|
||||
{
|
||||
int h;
|
||||
double a, d = [self dayOfCommonEra];
|
||||
d -= GREGORIAN_REFERENCE;
|
||||
d *= 86400;
|
||||
a = abs(d - seconds_since_ref);
|
||||
a = a / 3600;
|
||||
h = (int)a;
|
||||
|
||||
// There is a small chance of getting
|
||||
// it right at the stroke of midnight
|
||||
if (h == 24)
|
||||
h = 0;
|
||||
|
||||
return h;
|
||||
}
|
||||
|
||||
- (int)minuteOfHour
|
||||
{
|
||||
int h, m;
|
||||
double a, b, d = [self dayOfCommonEra];
|
||||
d -= GREGORIAN_REFERENCE;
|
||||
d *= 86400;
|
||||
a = abs(d - seconds_since_ref);
|
||||
b = a / 3600;
|
||||
h = (int)b;
|
||||
h = h * 3600;
|
||||
b = a - h;
|
||||
b = b / 60;
|
||||
m = (int)b;
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
- (int)monthOfYear
|
||||
{
|
||||
int m, d, y;
|
||||
|
||||
[self gregorianDateFromAbsolute: [self dayOfCommonEra]
|
||||
day: &d month: &m year: &y];
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
- (int)secondOfMinute
|
||||
{
|
||||
int h, m, s;
|
||||
double a, b, c, d = [self dayOfCommonEra];
|
||||
d -= GREGORIAN_REFERENCE;
|
||||
d *= 86400;
|
||||
a = abs(d - seconds_since_ref);
|
||||
b = a / 3600;
|
||||
h = (int)b;
|
||||
h = h * 3600;
|
||||
b = a - h;
|
||||
b = b / 60;
|
||||
m = (int)b;
|
||||
m = m * 60;
|
||||
c = a - h - m;
|
||||
s = (int)c;
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
- (int)yearOfCommonEra
|
||||
{
|
||||
int m, d, y;
|
||||
int a;
|
||||
|
||||
// Get reference date in terms of days
|
||||
a = seconds_since_ref / 86400;
|
||||
// Offset by Gregorian reference
|
||||
a += GREGORIAN_REFERENCE;
|
||||
[self gregorianDateFromAbsolute: a day: &d month: &m year: &y];
|
||||
|
||||
return y;
|
||||
}
|
||||
|
||||
// Providing Adjusted Dates
|
||||
- (NSCalendarDate *)addYear:(int)year
|
||||
month:(unsigned int)month
|
||||
day:(unsigned int)day
|
||||
hour:(unsigned int)hour
|
||||
minute:(unsigned int)minute
|
||||
second:(unsigned int)second
|
||||
{
|
||||
return self;
|
||||
}
|
||||
|
||||
// Getting String Descriptions of Dates
|
||||
- (NSString *)description
|
||||
{
|
||||
return [self descriptionWithCalendarFormat: calendar_format
|
||||
locale: nil];
|
||||
}
|
||||
|
||||
- (NSString *)descriptionWithCalendarFormat:(NSString *)format
|
||||
{
|
||||
return [self descriptionWithCalendarFormat: format
|
||||
locale: nil];
|
||||
}
|
||||
|
||||
#define UNIX_REFERENCE_INTERVAL -978307200.0
|
||||
- (NSString *)descriptionWithCalendarFormat:(NSString *)format
|
||||
locale:(NSDictionary *)locale
|
||||
{
|
||||
char buf[1024];
|
||||
const char *f = [format cString];
|
||||
int lf = strlen(f);
|
||||
BOOL mtag = NO, dtag = NO, ycent = NO;
|
||||
char ms[80] = "", ds[80] = "";
|
||||
int yd = 0, md = 0, dd = 0, hd = 0, mnd = 0, sd = 0;
|
||||
int i, j, k;
|
||||
|
||||
// If the format is nil then return an empty string
|
||||
if (!format)
|
||||
return @"";
|
||||
|
||||
[self getYear: &yd month: &md day: &dd hour: &hd minute: &mnd second: &sd];
|
||||
|
||||
// The strftime specifiers
|
||||
// %a abbreviated weekday name according to locale
|
||||
// %A full weekday name according to locale
|
||||
// %b abbreviated month name according to locale
|
||||
// %B full month name according to locale
|
||||
// %d day of month as decimal number
|
||||
// %H hour as a decimal number using 24-hour clock
|
||||
// %I hour as a decimal number using 12-hour clock
|
||||
// %j day of year as a decimal number
|
||||
// %m month as decimal number
|
||||
// %M minute as decimal number
|
||||
// %p 'am' or 'pm'
|
||||
// %S second as decimal number
|
||||
// %U week of the current year as decimal number (Sunday first day)
|
||||
// %W week of the current year as decimal number (Monday first day)
|
||||
// %w day of the week as decimal number (Sunday = 0)
|
||||
// %y year as a decimal number without century
|
||||
// %Y year as a decimal number with century
|
||||
// %Z time zone
|
||||
// %% literal % character
|
||||
|
||||
// Find the order of date elements
|
||||
// and translate format string into printf ready string
|
||||
j = 0;
|
||||
for (i = 0;i < lf; ++i)
|
||||
{
|
||||
// Only care about a format specifier
|
||||
if (f[i] == '%')
|
||||
{
|
||||
// check the character that comes after
|
||||
switch (f[i+1])
|
||||
{
|
||||
// literal %
|
||||
case '%':
|
||||
++i;
|
||||
buf[j] = f[i];
|
||||
++j;
|
||||
break;
|
||||
|
||||
// is it the year
|
||||
case 'Y':
|
||||
ycent = YES;
|
||||
case 'y':
|
||||
++i;
|
||||
if (ycent)
|
||||
k = sprintf(&(buf[j]), "%04d", yd);
|
||||
else
|
||||
k = sprintf(&(buf[j]), "%02d", (yd - 1900));
|
||||
j += k;
|
||||
break;
|
||||
|
||||
// is it the month
|
||||
case 'b':
|
||||
case 'B':
|
||||
mtag = YES; // Month is character string
|
||||
case 'm':
|
||||
++i;
|
||||
if (mtag)
|
||||
// +++ Translate to locale character string
|
||||
k = sprintf(&(buf[j]), "");
|
||||
else
|
||||
k = sprintf(&(buf[j]), "%02d", md);
|
||||
j += k;
|
||||
break;
|
||||
|
||||
// is it the day
|
||||
case 'a':
|
||||
case 'A':
|
||||
dtag = YES; // Day is character string
|
||||
case 'd':
|
||||
case 'j':
|
||||
case 'w':
|
||||
++i;
|
||||
if (dtag)
|
||||
// +++ Translate to locale character string
|
||||
k = sprintf(&(buf[j]), "");
|
||||
else
|
||||
k = sprintf(&(buf[j]), "%02d", dd);
|
||||
j += k;
|
||||
break;
|
||||
|
||||
// is it the hour
|
||||
case 'H':
|
||||
case 'I':
|
||||
++i;
|
||||
k = sprintf(&(buf[j]), "%02d", hd);
|
||||
j += k;
|
||||
break;
|
||||
|
||||
// is it the minute
|
||||
case 'M':
|
||||
++i;
|
||||
k = sprintf(&(buf[j]), "%02d", mnd);
|
||||
j += k;
|
||||
break;
|
||||
|
||||
// is it the second
|
||||
case 'S':
|
||||
++i;
|
||||
k = sprintf(&(buf[j]), "%02d", sd);
|
||||
j += k;
|
||||
break;
|
||||
|
||||
// Anything else is unknown so just copy
|
||||
default:
|
||||
buf[j] = f[i];
|
||||
++i;
|
||||
++j;
|
||||
buf[j] = f[i];
|
||||
++i;
|
||||
++j;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
buf[j] = f[i];
|
||||
++j;
|
||||
}
|
||||
}
|
||||
buf[j] = '\0';
|
||||
|
||||
return [NSString stringWithCString: buf];
|
||||
}
|
||||
|
||||
- (NSString *)descriptionWithLocale:(NSDictionary *)locale
|
||||
{
|
||||
return [self descriptionWithCalendarFormat: calendar_format
|
||||
locale: locale];
|
||||
}
|
||||
|
||||
// Getting and Setting Calendar Formats
|
||||
- (NSString *)calendarFormat
|
||||
{
|
||||
return calendar_format;
|
||||
}
|
||||
|
||||
- (void)setCalendarFormat:(NSString *)format
|
||||
{
|
||||
calendar_format = format;
|
||||
}
|
||||
|
||||
// Getting and Setting Time Zones
|
||||
- (void)setTimeZone:(NSTimeZone *)aTimeZone
|
||||
{
|
||||
time_zone = (NSTimeZoneDetail *)aTimeZone;
|
||||
}
|
||||
|
||||
- (NSTimeZoneDetail *)timeZoneDetail
|
||||
{
|
||||
return time_zone;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
//
|
||||
// Routines for manipulating Gregorian dates
|
||||
//
|
||||
// The following code is based upon the source code in
|
||||
// ``Calendrical Calculations'' by Nachum Dershowitz and Edward M. Reingold,
|
||||
// Software---Practice & Experience, vol. 20, no. 9 (September, 1990),
|
||||
// pp. 899--928.
|
||||
//
|
||||
|
||||
@implementation NSCalendarDate (GregorianDate)
|
||||
|
||||
- (int)lastDayOfGregorianMonth:(int)month year:(int)year
|
||||
{
|
||||
switch (month) {
|
||||
case 2:
|
||||
if ((((year % 4) == 0) && ((year % 100) != 0))
|
||||
|| ((year % 400) == 0))
|
||||
return 29;
|
||||
else
|
||||
return 28;
|
||||
case 4:
|
||||
case 6:
|
||||
case 9:
|
||||
case 11: return 30;
|
||||
default: return 31;
|
||||
}
|
||||
}
|
||||
|
||||
- (int)absoluteGregorianDay:(int)day month:(int)month year:(int)year
|
||||
{
|
||||
int m, N;
|
||||
|
||||
N = day; // day of month
|
||||
for (m = month - 1; m > 0; m--) // days in prior months this year
|
||||
N = N + [self lastDayOfGregorianMonth: m year: year];
|
||||
return
|
||||
(N // days this year
|
||||
+ 365 * (year - 1) // days in previous years ignoring leap days
|
||||
+ (year - 1)/4 // Julian leap days before this year...
|
||||
- (year - 1)/100 // ...minus prior century years...
|
||||
+ (year - 1)/400); // ...plus prior years divisible by 400
|
||||
}
|
||||
|
||||
- (void)gregorianDateFromAbsolute:(int)d
|
||||
day:(int *)day
|
||||
month:(int *)month
|
||||
year:(int *)year
|
||||
{
|
||||
// Search forward year by year from approximate year
|
||||
*year = d/366;
|
||||
while (d >= [self absoluteGregorianDay: 1 month: 1 year: (*year)+1])
|
||||
(*year)++;
|
||||
// Search forward month by month from January
|
||||
(*month) = 1;
|
||||
while (d > [self absoluteGregorianDay:
|
||||
[self lastDayOfGregorianMonth: *month year: *year]
|
||||
month: *month year: *year])
|
||||
(*month)++;
|
||||
*day = d - [self absoluteGregorianDay: 1 month: *month year: *year] + 1;
|
||||
}
|
||||
|
||||
@end
|
126
Testing/nsdate.m
Normal file
126
Testing/nsdate.m
Normal file
|
@ -0,0 +1,126 @@
|
|||
#include <Foundation/NSDate.h>
|
||||
#include <Foundation/NSAutoreleasePool.h>
|
||||
#include <Foundation/NSString.h>
|
||||
|
||||
#ifdef __MS_WIN32__
|
||||
int _MB_init_runtime()
|
||||
{
|
||||
libobjc_init_runtime();
|
||||
gnustep_base_init_runtime();
|
||||
nsdate_init_runtime();
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
int
|
||||
main()
|
||||
{
|
||||
id a, b, c, e; /* dates */
|
||||
id pool;
|
||||
|
||||
behavior_set_debug(0);
|
||||
|
||||
pool = [[NSAutoreleasePool alloc] init];
|
||||
|
||||
// NSDate tests
|
||||
printf("NSDate tests\n");
|
||||
{
|
||||
// Create NSDate instances
|
||||
a = [NSDate date];
|
||||
printf("+[date] -- %s\n", [[a description] cString]);
|
||||
b = [NSDate dateWithTimeIntervalSinceNow: 0];
|
||||
printf("+[dateWithTimeIntervalSinceNow: 0] -- %s\n",
|
||||
[[b description] cString]);
|
||||
b = [NSDate dateWithTimeIntervalSinceNow: 600];
|
||||
printf("+[dateWithTimeIntervalSinceNow: 600] -- %s\n",
|
||||
[[b description] cString]);
|
||||
b = [NSDate dateWithTimeIntervalSince1970: 0];
|
||||
printf("+[dateWithTimeIntervalSince1970: 0] -- %s\n",
|
||||
[[b description] cString]);
|
||||
b = [NSDate dateWithTimeIntervalSince1970: -600];
|
||||
printf("+[dateWithTimeIntervalSince1970: -600] -- %s\n",
|
||||
[[b description] cString]);
|
||||
b = [NSDate dateWithTimeIntervalSinceReferenceDate: 0];
|
||||
printf("+[dateWithTimeIntervalSinceReferenceDate: 0] -- %s\n",
|
||||
[[b description] cString]);
|
||||
b = [NSDate dateWithTimeIntervalSinceReferenceDate: 300];
|
||||
printf("+[dateWithTimeIntervalSinceReferenceDate: 300] -- %s\n",
|
||||
[[b description] cString]);
|
||||
|
||||
// Comparisons
|
||||
|
||||
if ([a compare: [NSDate distantFuture]] == NSOrderedAscending)
|
||||
printf("Current date is before distantFuture\n");
|
||||
else
|
||||
printf("ERROR: Current date is *not* before distantFuture\n");
|
||||
|
||||
if ([a compare: [NSDate distantPast]] == NSOrderedDescending)
|
||||
printf("Current date is after distantPast\n");
|
||||
else
|
||||
printf("ERROR: Current date is *not* after distantPast\n");
|
||||
|
||||
c = [a earlierDate: b];
|
||||
if (c == a)
|
||||
printf("%s is earlier than %s\n", [[a description] cString],
|
||||
[[b description] cString]);
|
||||
else
|
||||
printf("ERROR: %s is not earlier than %s\n", [[a description] cString],
|
||||
[[b description] cString]);
|
||||
|
||||
c = [a laterDate: b];
|
||||
if (c == b)
|
||||
printf("%s is later than %s\n", [[b description] cString],
|
||||
[[a description] cString]);
|
||||
else
|
||||
printf("ERROR: %s is not later than %s\n", [[b description] cString],
|
||||
[[a description] cString]);
|
||||
}
|
||||
|
||||
// NSCalendarDate tests
|
||||
printf("NSCalendarDate tests\n");
|
||||
{
|
||||
int m, y, d, a;
|
||||
|
||||
// Create an NSCalendarDate with current date and time
|
||||
c = [NSCalendarDate calendarDate];
|
||||
printf("+[calendarDate] -- %s\n", [[c description] cString]);
|
||||
printf("-[dayOfMonth] %d\n", [c dayOfMonth]);
|
||||
printf("-[monthOfYear] %d\n", [c monthOfYear]);
|
||||
printf("-[yearOfCommonEra] %d\n", [c yearOfCommonEra]);
|
||||
|
||||
a = [c absoluteGregorianDay: 9 month: 10 year: 1996];
|
||||
printf("%d-%d-%d is Gregorian absolute %d\n", 9, 10, 1996, a);
|
||||
printf("-[dayOfCommonEra] %d\n", [c dayOfCommonEra]);
|
||||
printf("-[timeIntervalSinceReferenceDate] %f\n",
|
||||
[c timeIntervalSinceReferenceDate]);
|
||||
|
||||
a = [c absoluteGregorianDay: 1 month: 1 year: 2001];
|
||||
printf("%d-%d-%d is Gregorian absolute %d\n", 1, 1, 2001, a);
|
||||
[c gregorianDateFromAbsolute: a day: &d month: &m year: &y];
|
||||
printf("Gregorian absolute %d is %d-%d-%d\n", a, d, m, y);
|
||||
|
||||
c = [NSCalendarDate dateWithString: @"1996-10-09 0:00:01"
|
||||
calendarFormat: @"%Y-%m-%d %H:%M:%S"];
|
||||
printf("calendar date %s\n", [[c description] cString]);
|
||||
printf("-[dayOfCommonEra] %d\n", [c dayOfCommonEra]);
|
||||
printf("-[dayOfMonth] %d\n", [c dayOfMonth]);
|
||||
printf("-[dayOfWeek] %d\n", [c dayOfWeek]);
|
||||
printf("-[dayOfYear] %d\n", [c dayOfYear]);
|
||||
printf("-[hourOfDay] %d\n", [c hourOfDay]);
|
||||
printf("-[minuteOfHour] %d\n", [c minuteOfHour]);
|
||||
printf("-[monthOfYear] %d\n", [c monthOfYear]);
|
||||
printf("-[secondOfMinute] %d\n", [c secondOfMinute]);
|
||||
printf("-[yearOfCommonEra] %d\n", [c yearOfCommonEra]);
|
||||
printf("-[timeIntervalSinceReferenceDate] %f\n",
|
||||
[c timeIntervalSinceReferenceDate]);
|
||||
e = [NSCalendarDate dateWithString: @"1996-10-09 0:00:0"
|
||||
calendarFormat: @"%Y-%m-%d %H:%M:%S"];
|
||||
printf("calendar date %s\n", [[e description] cString]);
|
||||
printf("-[timeIntervalSinceReferenceDate] %f\n",
|
||||
[e timeIntervalSinceReferenceDate]);
|
||||
}
|
||||
|
||||
[pool release];
|
||||
|
||||
exit(0);
|
||||
}
|
Loading…
Reference in a new issue