home *** CD-ROM | disk | FTP | other *** search
/ Nebula 1995 August / NEBULA.bin / SourceCode / MiscKit1.2.6 / Source / MiscTime.m < prev    next >
Encoding:
Text File  |  1993-09-28  |  10.1 KB  |  434 lines

  1. //
  2. //    MiscTime.m -- a generic class to simplify manipulation of times
  3. //        Written by Don Yacktman (c) 1993 by Don Yacktman.
  4. //                Version 1.0.  All rights reserved.
  5. //
  6. //        This notice may not be removed from this source code.
  7. //
  8. //        This is a free object!  Contact the author for the latest version.
  9. //        Don Yacktman, 4279 N. Ivy Lane, Provo, UT, 84604
  10. //        e-mail:  Don_Yacktman@byu.edu
  11. //
  12. //    This object is included in the MiscKit by permission from the author
  13. //    and its use is governed by the MiscKit license, found in the file
  14. //    "LICENSE.rtf" in the MiscKit distribution.  Please refer to that file
  15. //    for a list of all applicable permissions and restrictions.
  16. //    
  17.  
  18.     // *****  denotes an unfinished/unimplemented method.
  19.  
  20. #import <misckit/MiscTime.h>
  21. #import <sys/time.h>
  22.  
  23. // a few functions to handle date wierdnesses
  24.  
  25. static int isLeapYear(int year)
  26. {
  27.     // *****
  28.     return 0;
  29. }
  30.  
  31. static int Misc_daysUpTo(int month, int year)
  32. {
  33.     int array[12] = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 };
  34.     if (month < 2) return array[month];
  35.     return (array[month] + isLeapYear(year));
  36. }
  37.  
  38. static int Misc_daysIn(int month, int year)
  39. {
  40.     int array[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
  41.     if (month != 1) return array[month];
  42.     return (array[month] + isLeapYear(year));
  43. }
  44.  
  45. @implementation MiscTime
  46.  
  47. - init
  48. {
  49.     id ret;
  50.     if (!_initted) ret = [super init];
  51.     else ret = self;
  52.     _initted = YES;
  53.     dow = MISC_TIME_UNKNOWN_DOW;
  54.     if (!myStringValue) myStringValue = (char *)malloc(256);
  55.     year = 0; day = 0; month = 0; hour = 0;
  56.     minute = 0; second = 0; microsecond = 0;
  57.     isRelative = NO;
  58.     return ret;
  59. }
  60.  
  61. - initWithCurrentTime
  62. {
  63.     struct timeval tp;
  64.     struct timezone tzp;
  65.     struct tm *tv;
  66.     
  67.     id ret = [self init];
  68.  
  69.     gettimeofday(&tp, &tzp);
  70.     tv = localtime(&tp.tv_sec);
  71.     
  72.     microsecond = tp.tv_usec;
  73.     second = tv->tm_sec;
  74.     minute = tv->tm_min;
  75.     hour   = tv->tm_hour;
  76.     day    = tv->tm_mday - 1;
  77.     dow    = tv->tm_wday;
  78.     month  = tv->tm_mon;
  79.     year   = tv->tm_year;
  80.     return ret;
  81. }
  82.  
  83. - calcDayOfWeek
  84. {
  85.     // ***** 
  86.     return self;
  87. }
  88.  
  89. - setYear:(int)t { year = t; dow = MISC_TIME_UNKNOWN_DOW; return self; }
  90. - setMonth:(int)t { month = t; dow = MISC_TIME_UNKNOWN_DOW; return self; }
  91. - setDayOfWeek:(int)t { dow = t; return self; }
  92. - setDay:(int)t { day = t; dow = MISC_TIME_UNKNOWN_DOW; return self; }
  93. - setHour:(int)t { hour = t; return self; }
  94. - setMinute:(int)t { minute = t; return self; }
  95. - setSecond:(int)t { second = t; return self; }
  96. - setMicrosecond:(int)t { microsecond = t; return self; }
  97. - setRelative:(BOOL)t { isRelative = t; return self; }
  98.  
  99. - (int)_nintValue // ignores usecs.
  100. {    // ***** Not quite right; ignores leap years
  101.     return ((((((year - 1970) * MISC_TIME_MAX_DAYS
  102.                 + Misc_daysUpTo(month, year) + day)
  103.                 * MISC_TIME_MAX_HOURS) + hour)
  104.                 * MISC_TIME_MAX_MINUTES + minute)
  105.                 * MISC_TIME_MAX_SECONDS + second);
  106. }
  107.  
  108. - (int)intValue // # seconds since Jan 1, 1970
  109. { // rounds usec. and add in...
  110.     return ([self _nintValue] +
  111.                 ((microsecond < MISC_TIME_MAX_MICROSECONDS / 2) ? 0 : 1));
  112. }
  113.  
  114. - (double)doubleValue
  115. {
  116.     // *****
  117.     return 0.0;
  118. }
  119.  
  120. - (float)floatValue
  121. {
  122.     // *****
  123.     return 0.0;
  124. }
  125.  
  126. - (const char *)stringValue
  127. { // Need to allow the user to set the time and/or date format! *****
  128.     // Don't free this!  that's why it's a const!
  129.     if (!myStringValue) myStringValue = (char *)malloc(256);
  130.     sprintf(myStringValue, "%ld : %ld : %ld", hour, minute, second);
  131.     return myStringValue;
  132. }
  133.  
  134. - free
  135. {
  136.     free(myStringValue);
  137.     return [super free];
  138. }
  139.  
  140. - (int)dayOfWeek
  141. {
  142.     if (dow < 0) [self calcDayOfWeek];
  143.     return dow;
  144. }
  145.  
  146. - (int)year { return year; }
  147. - (int)month { return month; }
  148. - (int)day { return day; }
  149. - (int)hour { return hour; }
  150. - (int)minute { return minute; }
  151. - (int)second { return second; }
  152. - (int)microsecond { return microsecond; }
  153. - (BOOL)isRelative { return isRelative; }
  154.  
  155.  
  156. - addTime:aTime
  157. {
  158.     if (![aTime isKindOf:[MiscTime class]]) return nil;
  159.     [self addMicroseconds:[aTime microsecond]];
  160.     [self addSeconds:[aTime second]];
  161.     [self addMinutes:[aTime minute]];
  162.     [self addHours:[aTime hour]];
  163.     [self addDays:[aTime day]];
  164.     [self addMonths:[aTime month]];
  165.     [self addYears:[aTime year]];
  166.     return self;
  167. }
  168.  
  169. - subtractTime:aTime
  170. {
  171.     if (![aTime isKindOf:[MiscTime class]]) return nil;
  172.     [self subtractMicroseconds:[aTime microsecond]];
  173.     [self subtractSeconds:[aTime second]];
  174.     [self subtractMinutes:[aTime minute]];
  175.     [self subtractHours:[aTime hour]];
  176.     [self subtractDays:[aTime day]];
  177.     [self subtractMonths:[aTime month]];
  178.     [self subtractYears:[aTime year]];
  179.     return self;
  180. }
  181.  
  182. - addMicroseconds:(long)t
  183. {
  184.     long x = [self microsecond] + t;
  185.     if (!t) return self;
  186.     [self setMicrosecond:(x % MISC_TIME_MAX_MICROSECONDS)];
  187.     [self addSeconds:(x / MISC_TIME_MAX_MICROSECONDS)];
  188.     return self;
  189. }
  190.  
  191. - addSeconds:(long)t
  192. {
  193.     long x = [self second] + t;
  194.     if (!t) return self;
  195.     [self setSecond:(x % MISC_TIME_MAX_SECONDS)];
  196.     [self addMinutes:(x / MISC_TIME_MAX_SECONDS)];
  197.     return self;
  198. }
  199.  
  200. - addMinutes:(long)t
  201. {
  202.     long x = [self minute] + t;
  203.     if (!t) return self;
  204.     [self setMinute:(x % MISC_TIME_MAX_MINUTES)];
  205.     [self addHours:(x / MISC_TIME_MAX_MINUTES)];
  206.     return self;
  207. }
  208.  
  209. - addHours:(long)t
  210. {
  211.     long x = [self hour] + t;
  212.     if (!t) return self;
  213.     [self setHour:(x % MISC_TIME_MAX_HOURS)];
  214.     [self addDays:(x / MISC_TIME_MAX_HOURS)];
  215.     return self;
  216. }
  217.  
  218. - addDays:(long)t
  219. {
  220.     long x = [self day] + t; int k;
  221.     if (!t) return self;
  222.     
  223.     k = Misc_daysIn(month, year);
  224.     while (x >= k) { // This is slow, but it works.
  225.         [self addMonths:1];
  226.         x -= k; k = Misc_daysIn(month, year);
  227.     }
  228.     [self setDay:(x % MISC_TIME_MAX_DAYS)];
  229.     return self;
  230. }
  231.  
  232. - addWeeks:(long)t
  233. {
  234.     return [self addDays:(t * 7)];
  235. }
  236.  
  237. - addMonths:(long)t
  238. {
  239.     long x = [self month] + t;
  240.     if (!t) return self;
  241.     [self setMonth:(x % MISC_TIME_MAX_MONTHS)];
  242.     [self addYears:(x / MISC_TIME_MAX_MONTHS)];
  243.     return self;
  244. }
  245.  
  246. - addYears:(long)t
  247. {
  248.     if (t) [self setYear:([self year] + t)];
  249.     return self;
  250. }
  251.  
  252. - (BOOL)isAfter:aTime
  253. { // returns YES if we are "older" than time passed in
  254.     int si = [self _nintValue];
  255.     int oi = [aTime _nintValue];
  256.     if (si > oi) return YES;
  257.     if ((si == oi) && ([self microsecond] > [aTime microsecond])) return YES;
  258.     return NO;
  259. }
  260.  
  261. - (BOOL)isEqual:aTime
  262. { // returns YES if we are "same" as time passed in
  263.     if (([self _nintValue] == [aTime _nintValue]) &&
  264.             ([self microsecond] == [aTime microsecond])) return YES;
  265.     return NO;
  266. }
  267.  
  268. - subtractMicroseconds:(long)t
  269. {
  270.     long us = t % MISC_TIME_MAX_MICROSECONDS;
  271.     long s = t / MISC_TIME_MAX_MICROSECONDS;
  272.     long sus = [self microsecond];
  273.     if (us > sus) { s++; sus += MISC_TIME_MAX_MICROSECONDS; }
  274.     [self subtractSeconds:s];
  275.     [self setMicrosecond:(sus - us)];
  276.     return self;
  277. }
  278.  
  279. - subtractSeconds:(long)t
  280. {
  281.     long s = t % MISC_TIME_MAX_SECONDS;
  282.     long m = t / MISC_TIME_MAX_SECONDS;
  283.     long ss = [self second];
  284.     if (s > ss) { m++; ss += MISC_TIME_MAX_SECONDS; }
  285.     [self subtractMinutes:m];
  286.     [self setSecond:(ss - s)];
  287.     return self;
  288. }
  289.  
  290. - subtractMinutes:(long)t
  291. {
  292.     long m = t % MISC_TIME_MAX_MINUTES;
  293.     long h = t / MISC_TIME_MAX_MINUTES;
  294.     long sm = [self minute];
  295.     if (m > sm) { h++; sm += MISC_TIME_MAX_MINUTES; }
  296.     [self subtractHours:h];
  297.     [self setMinute:(sm - m)];
  298.     return self;
  299. }
  300.  
  301. - subtractHours:(long)t
  302. {
  303.     long h = t % MISC_TIME_MAX_HOURS;
  304.     long d = t / MISC_TIME_MAX_HOURS;
  305.     long sh = [self hour];
  306.     if (h > sh) { d++; sh += MISC_TIME_MAX_HOURS; }
  307.     [self subtractDays:d];
  308.     [self setHour:(sh - h)];
  309.     return self;
  310. }
  311.  
  312. - subtractDays:(long)t
  313. {
  314.     long sd = [self day];
  315.     while (t > sd) { // this is slow, but it works.
  316.         sd += Misc_daysIn(month, year);
  317.         [self subtractMonths:1];
  318.     }
  319.     [self setDay:(sd - t)];
  320.     return self;
  321. }
  322.  
  323. - subtractWeeks:(long)t
  324. {
  325.     return [self subtractDays:(t * 7)];
  326. }
  327.  
  328. - subtractMonths:(long)t
  329. {
  330.     long m = t % MISC_TIME_MAX_MONTHS;
  331.     long y = t / MISC_TIME_MAX_MONTHS;
  332.     long sm = [self month];
  333.     if (m > sm) { y++; sm += MISC_TIME_MAX_MONTHS; }
  334.     [self subtractYears:y];
  335.     [self setMonth:(sm - m)];
  336.     return self;
  337. }
  338.  
  339. - subtractYears:(long)t
  340. {
  341.     if (t) [self setYear:([self year] - t)];
  342.     return self;
  343. }
  344.  
  345. - copy
  346. {
  347.     id myCopy = [[MiscTime alloc] init];
  348.     [myCopy setYear:year];
  349.     [myCopy setMonth:month];
  350.     [myCopy setDay:day];
  351.     [myCopy setDayOfWeek:dow];
  352.     [myCopy setHour:hour];
  353.     [myCopy setMinute:minute];
  354.     [myCopy setSecond:second];
  355.     [myCopy setMicrosecond:microsecond];
  356.     [myCopy setRelative:isRelative];
  357.     return myCopy;
  358. }
  359.  
  360. - copyTimeFrom:aTime
  361. {
  362.     [self setYear:[aTime year]];
  363.     [self setMonth:[aTime month]];
  364.     [self setDay:[aTime day]];
  365.     [self setDayOfWeek:[aTime dayOfWeek]];
  366.     [self setHour:[aTime hour]];
  367.     [self setMinute:[aTime minute]];
  368.     [self setSecond:[aTime second]];
  369.     [self setMicrosecond:[aTime microsecond]];
  370.     [self setRelative:[aTime isRelative]];
  371.     return self;
  372. }
  373.  
  374. - read:(NXTypedStream *)stream
  375. {
  376.     [super read:stream];
  377.     NXReadTypes(stream, "cllllllll", &isRelative, µsecond, &second,
  378.             &minute, &hour, &dow, &day, &month, &year);
  379.     if (!myStringValue) myStringValue = (char *)malloc(256);
  380.     return self;
  381. }
  382.  
  383. - write:(NXTypedStream *)stream
  384. {
  385.     [super write:stream];
  386.     NXWriteTypes(stream, "cllllllll", &isRelative, µsecond, &second,
  387.             &minute, &hour, &dow, &day, &month, &year);
  388.     return self;
  389. }
  390.  
  391. // NXTransport protocol implementation:
  392. - encodeUsing:(id <NXEncoding>)portal
  393. {
  394.     [portal encodeData:&isRelative  ofType:"c"];
  395.     [portal encodeData:µsecond ofType:"i"];
  396.     [portal encodeData:&second      ofType:"i"];
  397.     [portal encodeData:&minute      ofType:"i"];
  398.     [portal encodeData:&hour        ofType:"i"];
  399.     [portal encodeData:&dow         ofType:"i"];
  400.     [portal encodeData:&day         ofType:"i"];
  401.     [portal encodeData:&month       ofType:"i"];
  402.     [portal encodeData:&year        ofType:"i"];
  403.     return self;
  404. }
  405.  
  406. - decodeUsing:(id <NXDecoding>)portal
  407. {
  408.     [portal decodeData:&isRelative  ofType:"c"];
  409.     [portal decodeData:µsecond ofType:"i"];
  410.     [portal decodeData:&second      ofType:"i"];
  411.     [portal decodeData:&minute      ofType:"i"];
  412.     [portal decodeData:&hour        ofType:"i"];
  413.     [portal decodeData:&dow         ofType:"i"];
  414.     [portal decodeData:&day         ofType:"i"];
  415.     [portal decodeData:&month       ofType:"i"];
  416.     [portal decodeData:&year        ofType:"i"];
  417.     return self;
  418. }
  419.  
  420. - encodeRemotelyFor:(NXConnection *)connection
  421.     freeAfterEncoding:(BOOL *)flagp isBycopy:(BOOL)isByCopy
  422. {
  423.     if (isByCopy) {
  424.         *flagp = NO; // object will copy.
  425.         return self; //encode object (copy it)
  426.     }
  427.     *flagp = NO; // object will copy.
  428.     // super will encode the proxy otherwise
  429.     return [super encodeRemotelyFor:connection
  430.                 freeAfterEncoding:flagp isBycopy:isByCopy];
  431. }
  432.  
  433. @end
  434.