home *** CD-ROM | disk | FTP | other *** search
- //
- // MiscTime.m -- a generic class to simplify manipulation of times
- // Written by Don Yacktman (c) 1993 by Don Yacktman.
- // Version 1.0. All rights reserved.
- //
- // This notice may not be removed from this source code.
- //
- // This is a free object! Contact the author for the latest version.
- // Don Yacktman, 4279 N. Ivy Lane, Provo, UT, 84604
- // e-mail: Don_Yacktman@byu.edu
- //
- // This object is included in the MiscKit by permission from the author
- // and its use is governed by the MiscKit license, found in the file
- // "LICENSE.rtf" in the MiscKit distribution. Please refer to that file
- // for a list of all applicable permissions and restrictions.
- //
-
- // ***** denotes an unfinished/unimplemented method.
-
- #import <misckit/MiscTime.h>
- #import <sys/time.h>
-
- // a few functions to handle date wierdnesses
-
- static int isLeapYear(int year)
- {
- // *****
- return 0;
- }
-
- static int Misc_daysUpTo(int month, int year)
- {
- int array[12] = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 };
- if (month < 2) return array[month];
- return (array[month] + isLeapYear(year));
- }
-
- static int Misc_daysIn(int month, int year)
- {
- int array[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
- if (month != 1) return array[month];
- return (array[month] + isLeapYear(year));
- }
-
- @implementation MiscTime
-
- - init
- {
- id ret;
- if (!_initted) ret = [super init];
- else ret = self;
- _initted = YES;
- dow = MISC_TIME_UNKNOWN_DOW;
- if (!myStringValue) myStringValue = (char *)malloc(256);
- year = 0; day = 0; month = 0; hour = 0;
- minute = 0; second = 0; microsecond = 0;
- isRelative = NO;
- return ret;
- }
-
- - initWithCurrentTime
- {
- struct timeval tp;
- struct timezone tzp;
- struct tm *tv;
-
- id ret = [self init];
-
- gettimeofday(&tp, &tzp);
- tv = localtime(&tp.tv_sec);
-
- microsecond = tp.tv_usec;
- second = tv->tm_sec;
- minute = tv->tm_min;
- hour = tv->tm_hour;
- day = tv->tm_mday - 1;
- dow = tv->tm_wday;
- month = tv->tm_mon;
- year = tv->tm_year;
- return ret;
- }
-
- - calcDayOfWeek
- {
- // *****
- return self;
- }
-
- - setYear:(int)t { year = t; dow = MISC_TIME_UNKNOWN_DOW; return self; }
- - setMonth:(int)t { month = t; dow = MISC_TIME_UNKNOWN_DOW; return self; }
- - setDayOfWeek:(int)t { dow = t; return self; }
- - setDay:(int)t { day = t; dow = MISC_TIME_UNKNOWN_DOW; return self; }
- - setHour:(int)t { hour = t; return self; }
- - setMinute:(int)t { minute = t; return self; }
- - setSecond:(int)t { second = t; return self; }
- - setMicrosecond:(int)t { microsecond = t; return self; }
- - setRelative:(BOOL)t { isRelative = t; return self; }
-
- - (int)_nintValue // ignores usecs.
- { // ***** Not quite right; ignores leap years
- return ((((((year - 1970) * MISC_TIME_MAX_DAYS
- + Misc_daysUpTo(month, year) + day)
- * MISC_TIME_MAX_HOURS) + hour)
- * MISC_TIME_MAX_MINUTES + minute)
- * MISC_TIME_MAX_SECONDS + second);
- }
-
- - (int)intValue // # seconds since Jan 1, 1970
- { // rounds usec. and add in...
- return ([self _nintValue] +
- ((microsecond < MISC_TIME_MAX_MICROSECONDS / 2) ? 0 : 1));
- }
-
- - (double)doubleValue
- {
- // *****
- return 0.0;
- }
-
- - (float)floatValue
- {
- // *****
- return 0.0;
- }
-
- - (const char *)stringValue
- { // Need to allow the user to set the time and/or date format! *****
- // Don't free this! that's why it's a const!
- if (!myStringValue) myStringValue = (char *)malloc(256);
- sprintf(myStringValue, "%ld : %ld : %ld", hour, minute, second);
- return myStringValue;
- }
-
- - free
- {
- free(myStringValue);
- return [super free];
- }
-
- - (int)dayOfWeek
- {
- if (dow < 0) [self calcDayOfWeek];
- return dow;
- }
-
- - (int)year { return year; }
- - (int)month { return month; }
- - (int)day { return day; }
- - (int)hour { return hour; }
- - (int)minute { return minute; }
- - (int)second { return second; }
- - (int)microsecond { return microsecond; }
- - (BOOL)isRelative { return isRelative; }
-
-
- - addTime:aTime
- {
- if (![aTime isKindOf:[MiscTime class]]) return nil;
- [self addMicroseconds:[aTime microsecond]];
- [self addSeconds:[aTime second]];
- [self addMinutes:[aTime minute]];
- [self addHours:[aTime hour]];
- [self addDays:[aTime day]];
- [self addMonths:[aTime month]];
- [self addYears:[aTime year]];
- return self;
- }
-
- - subtractTime:aTime
- {
- if (![aTime isKindOf:[MiscTime class]]) return nil;
- [self subtractMicroseconds:[aTime microsecond]];
- [self subtractSeconds:[aTime second]];
- [self subtractMinutes:[aTime minute]];
- [self subtractHours:[aTime hour]];
- [self subtractDays:[aTime day]];
- [self subtractMonths:[aTime month]];
- [self subtractYears:[aTime year]];
- return self;
- }
-
- - addMicroseconds:(long)t
- {
- long x = [self microsecond] + t;
- if (!t) return self;
- [self setMicrosecond:(x % MISC_TIME_MAX_MICROSECONDS)];
- [self addSeconds:(x / MISC_TIME_MAX_MICROSECONDS)];
- return self;
- }
-
- - addSeconds:(long)t
- {
- long x = [self second] + t;
- if (!t) return self;
- [self setSecond:(x % MISC_TIME_MAX_SECONDS)];
- [self addMinutes:(x / MISC_TIME_MAX_SECONDS)];
- return self;
- }
-
- - addMinutes:(long)t
- {
- long x = [self minute] + t;
- if (!t) return self;
- [self setMinute:(x % MISC_TIME_MAX_MINUTES)];
- [self addHours:(x / MISC_TIME_MAX_MINUTES)];
- return self;
- }
-
- - addHours:(long)t
- {
- long x = [self hour] + t;
- if (!t) return self;
- [self setHour:(x % MISC_TIME_MAX_HOURS)];
- [self addDays:(x / MISC_TIME_MAX_HOURS)];
- return self;
- }
-
- - addDays:(long)t
- {
- long x = [self day] + t; int k;
- if (!t) return self;
-
- k = Misc_daysIn(month, year);
- while (x >= k) { // This is slow, but it works.
- [self addMonths:1];
- x -= k; k = Misc_daysIn(month, year);
- }
- [self setDay:(x % MISC_TIME_MAX_DAYS)];
- return self;
- }
-
- - addWeeks:(long)t
- {
- return [self addDays:(t * 7)];
- }
-
- - addMonths:(long)t
- {
- long x = [self month] + t;
- if (!t) return self;
- [self setMonth:(x % MISC_TIME_MAX_MONTHS)];
- [self addYears:(x / MISC_TIME_MAX_MONTHS)];
- return self;
- }
-
- - addYears:(long)t
- {
- if (t) [self setYear:([self year] + t)];
- return self;
- }
-
- - (BOOL)isAfter:aTime
- { // returns YES if we are "older" than time passed in
- int si = [self _nintValue];
- int oi = [aTime _nintValue];
- if (si > oi) return YES;
- if ((si == oi) && ([self microsecond] > [aTime microsecond])) return YES;
- return NO;
- }
-
- - (BOOL)isEqual:aTime
- { // returns YES if we are "same" as time passed in
- if (([self _nintValue] == [aTime _nintValue]) &&
- ([self microsecond] == [aTime microsecond])) return YES;
- return NO;
- }
-
- - subtractMicroseconds:(long)t
- {
- long us = t % MISC_TIME_MAX_MICROSECONDS;
- long s = t / MISC_TIME_MAX_MICROSECONDS;
- long sus = [self microsecond];
- if (us > sus) { s++; sus += MISC_TIME_MAX_MICROSECONDS; }
- [self subtractSeconds:s];
- [self setMicrosecond:(sus - us)];
- return self;
- }
-
- - subtractSeconds:(long)t
- {
- long s = t % MISC_TIME_MAX_SECONDS;
- long m = t / MISC_TIME_MAX_SECONDS;
- long ss = [self second];
- if (s > ss) { m++; ss += MISC_TIME_MAX_SECONDS; }
- [self subtractMinutes:m];
- [self setSecond:(ss - s)];
- return self;
- }
-
- - subtractMinutes:(long)t
- {
- long m = t % MISC_TIME_MAX_MINUTES;
- long h = t / MISC_TIME_MAX_MINUTES;
- long sm = [self minute];
- if (m > sm) { h++; sm += MISC_TIME_MAX_MINUTES; }
- [self subtractHours:h];
- [self setMinute:(sm - m)];
- return self;
- }
-
- - subtractHours:(long)t
- {
- long h = t % MISC_TIME_MAX_HOURS;
- long d = t / MISC_TIME_MAX_HOURS;
- long sh = [self hour];
- if (h > sh) { d++; sh += MISC_TIME_MAX_HOURS; }
- [self subtractDays:d];
- [self setHour:(sh - h)];
- return self;
- }
-
- - subtractDays:(long)t
- {
- long sd = [self day];
- while (t > sd) { // this is slow, but it works.
- sd += Misc_daysIn(month, year);
- [self subtractMonths:1];
- }
- [self setDay:(sd - t)];
- return self;
- }
-
- - subtractWeeks:(long)t
- {
- return [self subtractDays:(t * 7)];
- }
-
- - subtractMonths:(long)t
- {
- long m = t % MISC_TIME_MAX_MONTHS;
- long y = t / MISC_TIME_MAX_MONTHS;
- long sm = [self month];
- if (m > sm) { y++; sm += MISC_TIME_MAX_MONTHS; }
- [self subtractYears:y];
- [self setMonth:(sm - m)];
- return self;
- }
-
- - subtractYears:(long)t
- {
- if (t) [self setYear:([self year] - t)];
- return self;
- }
-
- - copy
- {
- id myCopy = [[MiscTime alloc] init];
- [myCopy setYear:year];
- [myCopy setMonth:month];
- [myCopy setDay:day];
- [myCopy setDayOfWeek:dow];
- [myCopy setHour:hour];
- [myCopy setMinute:minute];
- [myCopy setSecond:second];
- [myCopy setMicrosecond:microsecond];
- [myCopy setRelative:isRelative];
- return myCopy;
- }
-
- - copyTimeFrom:aTime
- {
- [self setYear:[aTime year]];
- [self setMonth:[aTime month]];
- [self setDay:[aTime day]];
- [self setDayOfWeek:[aTime dayOfWeek]];
- [self setHour:[aTime hour]];
- [self setMinute:[aTime minute]];
- [self setSecond:[aTime second]];
- [self setMicrosecond:[aTime microsecond]];
- [self setRelative:[aTime isRelative]];
- return self;
- }
-
- - read:(NXTypedStream *)stream
- {
- [super read:stream];
- NXReadTypes(stream, "cllllllll", &isRelative, µsecond, &second,
- &minute, &hour, &dow, &day, &month, &year);
- if (!myStringValue) myStringValue = (char *)malloc(256);
- return self;
- }
-
- - write:(NXTypedStream *)stream
- {
- [super write:stream];
- NXWriteTypes(stream, "cllllllll", &isRelative, µsecond, &second,
- &minute, &hour, &dow, &day, &month, &year);
- return self;
- }
-
- // NXTransport protocol implementation:
- - encodeUsing:(id <NXEncoding>)portal
- {
- [portal encodeData:&isRelative ofType:"c"];
- [portal encodeData:µsecond ofType:"i"];
- [portal encodeData:&second ofType:"i"];
- [portal encodeData:&minute ofType:"i"];
- [portal encodeData:&hour ofType:"i"];
- [portal encodeData:&dow ofType:"i"];
- [portal encodeData:&day ofType:"i"];
- [portal encodeData:&month ofType:"i"];
- [portal encodeData:&year ofType:"i"];
- return self;
- }
-
- - decodeUsing:(id <NXDecoding>)portal
- {
- [portal decodeData:&isRelative ofType:"c"];
- [portal decodeData:µsecond ofType:"i"];
- [portal decodeData:&second ofType:"i"];
- [portal decodeData:&minute ofType:"i"];
- [portal decodeData:&hour ofType:"i"];
- [portal decodeData:&dow ofType:"i"];
- [portal decodeData:&day ofType:"i"];
- [portal decodeData:&month ofType:"i"];
- [portal decodeData:&year ofType:"i"];
- return self;
- }
-
- - encodeRemotelyFor:(NXConnection *)connection
- freeAfterEncoding:(BOOL *)flagp isBycopy:(BOOL)isByCopy
- {
- if (isByCopy) {
- *flagp = NO; // object will copy.
- return self; //encode object (copy it)
- }
- *flagp = NO; // object will copy.
- // super will encode the proxy otherwise
- return [super encodeRemotelyFor:connection
- freeAfterEncoding:flagp isBycopy:isByCopy];
- }
-
- @end
-