API  0.9.10
CPDate.j
Go to the documentation of this file.
1 /*
2  * CPDate.j
3  * Foundation
4  *
5  * Created by Thomas Robinson.
6  * Copyright 2008, 280 North, Inc.
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21  */
22 
23 
24 var CPDateReferenceDate = new Date(Date.UTC(2001, 0, 1, 0, 0, 0, 0));
25 
30 @implementation CPDate : CPObject
31 {
32  id __doxygen__;
33 }
34 
35 + (id)alloc
36 {
37  var result = new Date;
38  result.isa = [self class];
39  return result;
40 }
41 
42 + (id)date
43 {
44  return [[self alloc] init];
45 }
46 
47 + (id)dateWithTimeIntervalSinceNow:(CPTimeInterval)seconds
48 {
49  return [[CPDate alloc] initWithTimeIntervalSinceNow:seconds];
50 }
51 
52 + (id)dateWithTimeIntervalSince1970:(CPTimeInterval)seconds
53 {
54  return [[CPDate alloc] initWithTimeIntervalSince1970:seconds];
55 }
56 
57 + (id)dateWithTimeIntervalSinceReferenceDate:(CPTimeInterval)seconds
58 {
60 }
61 
63 {
64  return [CPDate dateWithTimeIntervalSinceReferenceDate:-63113817600.0];
65 }
66 
68 {
69  return [CPDate dateWithTimeIntervalSinceReferenceDate:63113990400.0];
70 }
71 
72 - (id)initWithTimeIntervalSinceNow:(CPTimeInterval)seconds
73 {
74  if (!_isNumberType(seconds))
75  CPLog.warn(@"The parameter of the method initWithTimeIntervalSinceNow: should be an integer or a float");
76 
77  self = new Date((new Date()).getTime() + seconds * 1000);
78  return self;
79 }
80 
81 - (id)initWithTimeIntervalSince1970:(CPTimeInterval)seconds
82 {
83  if (!_isNumberType(seconds))
84  CPLog.warn(@"The parameter of the method initWithTimeIntervalSince1970: should be an integer or a float");
85 
86  self = new Date(seconds * 1000);
87  return self;
88 }
89 
90 - (id)initWithTimeIntervalSinceReferenceDate:(CPTimeInterval)seconds
91 {
92  if (!_isNumberType(seconds))
93  CPLog.warn(@"The parameter of the method initWithTimeIntervalSinceReferenceDate: should be an integer or a float");
94 
95  self = [self initWithTimeInterval:seconds sinceDate:CPDateReferenceDate];
96  return self;
97 }
98 
99 - (id)initWithTimeInterval:(CPTimeInterval)seconds sinceDate:(CPDate)refDate
100 {
101  if (!_isNumberType(seconds))
102  CPLog.warn(@"The parameter of the method initWithTimeInterval:sinceDate: should be an integer or a float");
103 
104  self = new Date(refDate.getTime() + seconds * 1000);
105  return self;
106 }
107 
113 - (id)initWithString:(CPString)description
114 {
115  var format = new RegExp("(\\d{4})-(\\d{2})-(\\d{2}) (\\d{2}):(\\d{2}):(\\d{2}) ([-+])(\\d{2})(\\d{2})"),
116  d = description.match(new RegExp(format));
117 
118  if (!d || d.length != 10)
119  [CPException raise:CPInvalidArgumentException
120  reason:"initWithString: the string must be in YYYY-MM-DD HH:MM:SS 1HHMM format"];
121 
122  var date = new Date(d[1], d[2] - 1, d[3]),
123  timeZoneOffset = (Number(d[8]) * 60 + Number(d[9])) * (d[7] === '-' ? 1 : -1);
124 
125  date.setHours(d[4]);
126  date.setMinutes(d[5]);
127  date.setSeconds(d[6]);
128 
129  self = new Date(date.getTime() + (timeZoneOffset - date.getTimezoneOffset()) * 60 * 1000);
130  return self;
131 }
132 
133 - (CPTimeInterval)timeIntervalSinceDate:(CPDate)anotherDate
134 {
135  return (self.getTime() - anotherDate.getTime()) / 1000.0;
136 }
137 
138 - (CPTimeInterval)timeIntervalSinceNow
139 {
140  return [self timeIntervalSinceDate:[CPDate date]];
141 }
142 
143 - (CPTimeInterval)timeIntervalSince1970
144 {
145  return self.getTime() / 1000.0;
146 }
147 
149 {
150  return (self.getTime() - CPDateReferenceDate.getTime()) / 1000.0;
151 }
152 
153 + (CPTimeInterval)timeIntervalSinceReferenceDate
154 {
156 }
157 
162 - (id)dateByAddingTimeInterval:(CPTimeInterval)seconds
163 {
164  return [[CPDate alloc] initWithTimeInterval:seconds sinceDate:self];
165 }
166 
167 - (BOOL)isEqual:(CPDate)aDate
168 {
169  if (self === aDate)
170  return YES;
171 
172  if (!aDate || ![aDate isKindOfClass:[CPDate class]])
173  return NO;
174 
175  return [self isEqualToDate:aDate];
176 }
177 
178 - (BOOL)isEqualToDate:(CPDate)aDate
179 {
180  if (!aDate)
181  return NO;
182 
183  return !(self < aDate || self > aDate);
184 }
185 
186 - (CPComparisonResult)compare:(CPDate)anotherDate
187 {
188  return (self > anotherDate) ? CPOrderedDescending : ((self < anotherDate) ? CPOrderedAscending : CPOrderedSame);
189 }
190 
191 - (CPDate)earlierDate:(CPDate)anotherDate
192 {
193  return (self < anotherDate) ? self : anotherDate;
194 }
195 
196 - (CPDate)laterDate:(CPDate)anotherDate
197 {
198  return (self > anotherDate) ? self : anotherDate;
199 }
200 
204 + (CPString)timezoneOffsetString:(int)timezoneOffset
205 {
206  var offset = -timezoneOffset,
207  positive = offset >= 0,
208  hours = positive ? FLOOR(offset / 60) : CEIL(offset / 60),
209  minutes = offset - hours * 60;
210  return [CPString stringWithFormat:@"%s%02d%02d", positive ? "+" : "-", ABS(hours), ABS(minutes)];
211 }
212 
217 - (CPString)description
218 {
219  return [CPString stringWithFormat:@"%04d-%02d-%02d %02d:%02d:%02d %s", self.getFullYear(), self.getMonth() + 1, self.getDate(), self.getHours(), self.getMinutes(), self.getSeconds(), [CPDate timezoneOffsetString:self.getTimezoneOffset()]];
220 }
221 
222 - (id)copy
223 {
224  return new Date(self.getTime());
225 }
226 
227 @end
228 
229 var CPDateTimeKey = @"CPDateTimeKey";
230 
231 @implementation CPDate (CPCoding)
232 
233 - (id)initWithCoder:(CPCoder)aCoder
234 {
235  if (self)
236  {
237  self.setTime([aCoder decodeIntForKey:CPDateTimeKey]);
238  }
239 
240  return self;
241 }
242 
243 - (void)encodeWithCoder:(CPCoder)aCoder
244 {
245  [aCoder encodeInt:self.getTime() forKey:CPDateTimeKey];
246 }
247 
248 @end
249 
250 // Based on 'Universal JavaScript Date.parse for ISO 8601' available at https://github.com/csnover/js-iso8601.
251 var numericKeys = [1, 4, 5, 6, 7, 10, 11];
252 
253 Date.parseISO8601 = function (date)
254 {
255  var timestamp,
256  struct,
257  minutesOffset = 0;
258 
259  // First, check for native parsing.
260  timestamp = Date.parse(date);
261 
262  if (isNaN(timestamp) && (struct = new RegExp("^(\\d{4}|[+\\-]\\d{6})(?:-(\\d{2})(?:-(\\d{2}))?)?(?:T(\\d{2}):(\\d{2})(?::(\\d{2})(?:\\.(\\d{3}))?)?(?:(Z)|([+\\-])(\\d{2})(?::(\\d{2}))?)?)?$").exec(date)))
263  {
264  // avoid NaN timestamps caused by "undefined" values being passed to Date.UTC
265  for (var i = 0, k; (k = numericKeys[i]); ++i)
266  struct[k] = +struct[k] || 0;
267 
268  // allow undefined days and months
269  struct[2] = (+struct[2] || 1) - 1;
270  struct[3] = +struct[3] || 1;
271 
272  if (struct[8] !== 'Z' && struct[9] !== undefined)
273  {
274  minutesOffset = struct[10] * 60 + struct[11];
275 
276  if (struct[9] === '+')
277  minutesOffset = 0 - minutesOffset;
278  }
279 
280  return Date.UTC(struct[1], struct[2], struct[3], struct[4], struct[5] + minutesOffset, struct[6], struct[7]);
281  }
282 
283  return timestamp;
284 };
285 
286 Date.prototype.isa = CPDate;
287 
288 function _isNumberType(value)
289 {
290  if (typeof value === 'number')
291  return YES;
292  else
293  return NO;
294 }
Used to implement exception handling (creating & raising).
Definition: CPException.h:2
CPOrderedAscending
Definition: CPObjJRuntime.j:48
var numericKeys
Definition: CPDate.j:251
CPString timezoneOffsetString:(int timezoneOffset)
Definition: CPDate.j:204
CPTimeInterval timeIntervalSinceNow()
Definition: CPDate.j:138
var isEqual
A representation of a single point in time.
Definition: CPDate.h:2
CPOrderedSame
Definition: CPObjJRuntime.j:54
CPTimeInterval timeIntervalSince1970()
Definition: CPDate.j:143
CPTimeInterval timeIntervalSinceDate:(CPDate anotherDate)
Definition: CPDate.j:133
void raise:reason:(CPString aName, [reason] CPString aReason)
Definition: CPException.j:66
id distantFuture()
Definition: CPDate.j:67
id dateWithTimeIntervalSinceReferenceDate:(CPTimeInterval seconds)
Definition: CPDate.j:57
id initWithTimeIntervalSince1970:(CPTimeInterval seconds)
Definition: CPDate.j:81
An immutable string (collection of characters).
Definition: CPString.h:2
id distantPast()
Definition: CPDate.j:62
CPOrderedDescending
Definition: CPObjJRuntime.j:60
id copy()
Definition: CPDate.j:222
BOOL isEqualToDate:(CPDate aDate)
Definition: CPDate.j:178
id initWithTimeIntervalSinceReferenceDate:(CPTimeInterval seconds)
Definition: CPDate.j:90
id self()
Definition: CPObject.j:588
var CPDateReferenceDate
Definition: CPDate.j:24
Defines methods for use when archiving & restoring (enc/decoding).
Definition: CPCoder.h:2
id alloc()
Definition: CPDate.j:35
id initWithTimeIntervalSinceNow:(CPTimeInterval seconds)
Definition: CPDate.j:72
id initWithTimeInterval:sinceDate:(CPTimeInterval seconds, [sinceDate] CPDate refDate)
Definition: CPDate.j:99
id date()
Definition: CPDate.j:42
var CPDateTimeKey
Definition: CPDate.j:229
Class class()
Definition: CPObject.j:179
CPTimeInterval timeIntervalSinceReferenceDate()
Definition: CPDate.j:148
id stringWithFormat:(CPString format, [,] ...)
Definition: CPString.j:166