API  0.9.10
CPDateFormatter.j
Go to the documentation of this file.
1 /*
2  * CPDateFormatter.j
3  * Foundation
4  *
5  * Created by Alexander Ljungberg.
6  * Copyright 2012, SlevenBits Ltd.
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 
26 @global CPLocaleCountryCode
27 
28 @typedef CPDateFormatterStyle
34 
35 @typedef CPDateFormatterBehavior
39 
43 
51 @implementation CPDateFormatter : CPFormatter
52 {
53  BOOL _allowNaturalLanguage;
54  BOOL _doesRelativeDateFormatting;
55  CPDate _defaultDate;
56  CPDate _twoDigitStartDate;
57  CPDateFormatterBehavior _formatterBehavior;
58  CPDateFormatterStyle _dateStyle;
59  CPDateFormatterStyle _timeStyle;
60  CPLocale _locale;
61  CPString _AMSymbol;
62  CPString _dateFormat;
63  CPString _PMSymbol;
64  CPTimeZone _timeZone;
65 
66  CPDictionary _symbols;
67 }
68 
69 
70 + (void)initialize
71 {
72  if (self !== [CPDateFormatter class])
73  return;
74 
76  @"fr" : [@"demain", 1, @"apr" + String.fromCharCode(233) + @"s-demain", 2, @"apr" + String.fromCharCode(233) + @"s-apr" + String.fromCharCode(233) + @"s-demain", 3, @"hier", -1, @"avant-hier", -2, @"avant-avant-hier", -3],
77  @"en" : [@"tomorrow", 1, @"yesterday", -1],
78  @"de" : [],
79  @"es" : []
80  };
81 
82  patternStringTokens = [@"QQQ", @"qqq", @"QQQQ", @"qqqq", @"MMM", @"MMMM", @"LLL", @"LLLL", @"E", @"EE", @"EEE", @"eee", @"eeee", @"eeeee", @"a", @"z", @"zz", @"zzz", @"zzzz", @"Z", @"ZZ", @"ZZZ", @"ZZZZ", @"ZZZZZ", @"v", @"vv", @"vvv", @"vvvv", @"V", @"VV", @"VVV", @"VVVV"];
83 }
84 
91 + (CPString)localizedStringFromDate:(CPDate)date dateStyle:(CPDateFormatterStyle)dateStyle timeStyle:(CPDateFormatterStyle)timeStyle
92 {
93  var formatter = [[CPDateFormatter alloc] init];
94 
95  [formatter setFormatterBehavior:CPDateFormatterBehavior10_4];
96  [formatter setDateStyle:dateStyle];
97  [formatter setTimeStyle:timeStyle];
98 
99  return [formatter stringForObjectValue:date];
100 }
101 
109 + (CPString)dateFormatFromTemplate:(CPString)template options:(CPUInteger)opts locale:(CPLocale)locale
110 {
111  // TODO : check every template from cocoa and return a good format (have fun ^^)
112 }
113 
117 + (CPDateFormatterBehavior)defaultFormatterBehavior
118 {
120 }
121 
125 + (void)setDefaultFormatterBehavior:(CPDateFormatterBehavior)behavior
126 {
127  defaultDateFormatterBehavior = behavior;
128 }
129 
133 - (id)init
134 {
135  if (self = [super init])
136  {
137  _dateStyle = nil;
138  _timeStyle = nil;
139 
140  [self _init];
141  }
142 
143  return self;
144 }
145 
151 - (id)initWithDateFormat:(CPString)format allowNaturalLanguage:(BOOL)flag
152 {
153  if (self = [self init])
154  {
155  _dateFormat = format;
156  _allowNaturalLanguage = flag;
157  }
158 
159  return self
160 }
161 
164 - (void)_init
165 {
166  var AMSymbol = [CPString stringWithFormat:@"%s", @"AM"],
167  PMSymbol = [CPString stringWithFormat:@"%s", @"PM"],
168  weekdaySymbols = [CPArray arrayWithObjects:@"Sunday", @"Monday", @"Tuesday", @"Wednesday", @"Thursday", @"Friday", @"Saturday"],
169  shortWeekdaySymbols = [CPArray arrayWithObjects:@"Sun", @"Mon", @"Tue", @"Wed", @"Thu", @"Fri", @"Sat"],
170  veryShortWeekdaySymbols = [CPArray arrayWithObjects:@"S", @"M", @"T", @"W", @"T", @"F", @"S"],
171  standaloneWeekdaySymbols = [CPArray arrayWithObjects:@"Sunday", @"Monday", @"Tuesday", @"Wednesday", @"Thursday", @"Friday", @"Saturday"],
172  shortStandaloneWeekdaySymbols = [CPArray arrayWithObjects:@"Sun", @"Mon", @"Tue", @"Wed", @"Thu", @"Fri", @"Sat"],
173  veryShortStandaloneWeekdaySymbols = [CPArray arrayWithObjects:@"S", @"M", @"T", @"W", @"T", @"F", @"S"],
174  monthSymbols = [CPArray arrayWithObjects:@"January", @"February", @"March", @"April", @"May", @"June", @"July", @"August", @"September", @"October", @"November", @"December"],
175  shortMonthSymbols = [CPArray arrayWithObjects:@"Jan", @"Feb", @"Mar", @"Apr", @"May", @"Jun", @"Jul", @"Aug", @"Sep", @"Oct", @"Nov", @"Dec"],
176  veryShortMonthSymbols = [CPArray arrayWithObjects:@"J", @"F", @"M", @"A", @"M", @"J", @"J", @"A", @"S", @"O", @"N", @"D"],
177  standaloneMonthSymbols = [CPArray arrayWithObjects:@"January", @"February", @"March", @"April", @"May", @"June", @"July", @"August", @"September", @"October", @"November", @"December"],
178  shortStandaloneMonthSymbols = [CPArray arrayWithObjects:@"Jan", @"Feb", @"Mar", @"Apr", @"May", @"Jun", @"Jul", @"Aug", @"Sep", @"Oct", @"Nov", @"Dec"],
179  veryShortStandaloneMonthSymbols = [CPArray arrayWithObjects:@"J", @"F", @"M", @"A", @"M", @"J", @"J", @"A", @"S", @"O", @"N", @"D"],
180  quarterSymbols = [CPArray arrayWithObjects:@"1st quarter", @"2nd quarter", @"3rd quarter", @"4th quarter"],
181  shortQuarterSymbols = [CPArray arrayWithObjects:@"Q1", @"Q2", @"Q3", @"Q4"],
182  standaloneQuarterSymbols = [CPArray arrayWithObjects:@"1st quarter", @"2nd quarter", @"3rd quarter", @"4th quarter"],
183  shortStandaloneQuarterSymbols = [CPArray arrayWithObjects:@"Q1", @"Q2", @"Q3", @"Q4"];
184 
185  _symbols = @{
186  @"root" : @{
187  @"AMSymbol" : AMSymbol,
188  @"PMSymbol" : PMSymbol,
189  @"weekdaySymbols" : weekdaySymbols,
190  @"shortWeekdaySymbols" : shortWeekdaySymbols,
191  @"veryShortWeekdaySymbols" : veryShortWeekdaySymbols,
192  @"standaloneWeekdaySymbols" : standaloneWeekdaySymbols,
193  @"shortStandaloneWeekdaySymbols" : shortStandaloneWeekdaySymbols,
194  @"veryShortStandaloneWeekdaySymbols" : veryShortStandaloneWeekdaySymbols,
195  @"monthSymbols" : monthSymbols,
196  @"shortMonthSymbols" : shortMonthSymbols,
197  @"veryShortMonthSymbols" : veryShortMonthSymbols,
198  @"standaloneMonthSymbols" : standaloneMonthSymbols,
199  @"shortStandaloneMonthSymbols" : shortStandaloneMonthSymbols,
200  @"veryShortStandaloneMonthSymbols" : veryShortStandaloneMonthSymbols,
201  @"quarterSymbols" : quarterSymbols,
202  @"shortQuarterSymbols" : shortQuarterSymbols,
203  @"standaloneQuarterSymbols" : standaloneQuarterSymbols,
204  @"shortStandaloneQuarterSymbols" : shortStandaloneQuarterSymbols
205  }
206 
207  };
208 
209  _timeZone = [CPTimeZone systemTimeZone];
210  _twoDigitStartDate = [[CPDate alloc] initWithString:@"1950-01-01 00:00:00 +0000"];
211  _locale = [CPLocale currentLocale];
212 }
213 
214 
215 #pragma mark -
216 #pragma mark Setter Getter Helper
217 
220 - (CPDictionary)symbolsForLanguageCode:(CPString)languageCode
221 {
222  var languageSymbols = [_symbols valueForKey:languageCode];
223 
224  if (!languageSymbols)
225  {
226  languageSymbols = [self symbolsForLanguageCode:@"root"];
227  [self setSymbols:languageSymbols forLanguageCode:languageCode];
228  }
229 
230  return languageSymbols;
231 }
232 
235 - (void)setSymbols:(CPDictionary)symbols forLanguageCode:(CPString)languageCode
236 {
237  [_symbols setValue:symbols forKey:languageCode];
238 }
239 
242 - (id)symbolForKey:(CPString)aKey languageCode:(CPString)languageCode
243 {
244  var languageSymbols = [self symbolsForLanguageCode:languageCode],
245  symbol = [languageSymbols valueForKey:aKey];
246 
247  if (!symbol)
248  {
249  symbol = [self symbolForKey:aKey languageCode:@"root"];
250  [self setSymbol:symbol forKey:aKey languageCode:languageCode];
251  }
252 
253  return symbol;
254 }
255 
258 - (void)setSymbol:(CPString)aSymbol forKey:(CPString)aKey languageCode:(CPString)languageCode
259 {
260  var languageSymbols = [self symbolsForLanguageCode:languageCode];
261  [languageSymbols setValue:aSymbol forKey:aKey];
262 }
263 
264 #pragma mark -
265 #pragma mark Setter Getter
266 
270 {
271  return [self symbolForKey:@"AMSymbol" languageCode:[_locale objectForKey:CPLocaleLanguageCode]];
272 }
273 
276 - (void)setAMSymbol:(CPString)aValue
277 {
278  [self setSymbol:aValue forKey:@"AMSymbol" languageCode:[_locale objectForKey:CPLocaleLanguageCode]];
279 }
280 
284 {
285  return [self symbolForKey:@"PMSymbol" languageCode:[_locale objectForKey:CPLocaleLanguageCode]];
286 }
287 
290 - (void)setPMSymbol:(CPString)aValue
291 {
292  [self setSymbol:aValue forKey:@"PMSymbol" languageCode:[_locale objectForKey:CPLocaleLanguageCode]];
293 }
294 
297 - (CPArray)weekdaySymbols
298 {
299  return [self symbolForKey:@"weekdaySymbols" languageCode:[_locale objectForKey:CPLocaleLanguageCode]];
300 }
301 
304 - (void)setWeekdaySymbols:(CPArray)aValue
305 {
306  [self setSymbol:aValue forKey:@"weekdaySymbols" languageCode:[_locale objectForKey:CPLocaleLanguageCode]];
307 }
308 
312 {
313  return [self symbolForKey:@"shortWeekdaySymbols" languageCode:[_locale objectForKey:CPLocaleLanguageCode]];
314 }
315 
318 - (void)setShortWeekdaySymbols:(CPArray)aValue
319 {
320  [self setSymbol:aValue forKey:@"shortWeekdaySymbols" languageCode:[_locale objectForKey:CPLocaleLanguageCode]];
321 }
322 
326 {
327  return [self symbolForKey:@"veryShortWeekdaySymbols" languageCode:[_locale objectForKey:CPLocaleLanguageCode]];
328 }
329 
332 - (void)setVeryShortWeekdaySymbols:(CPArray)aValue
333 {
334  [self setSymbol:aValue forKey:@"veryShortWeekdaySymbols" languageCode:[_locale objectForKey:CPLocaleLanguageCode]];
335 }
336 
340 {
341  return [self symbolForKey:@"standaloneWeekdaySymbols" languageCode:[_locale objectForKey:CPLocaleLanguageCode]];
342 }
343 
346 - (void)setStandaloneWeekdaySymbols:(CPArray)aValue
347 {
348  [self setSymbol:aValue forKey:@"standaloneWeekdaySymbols" languageCode:[_locale objectForKey:CPLocaleLanguageCode]];
349 }
350 
354 {
355  return [self symbolForKey:@"shortStandaloneWeekdaySymbols" languageCode:[_locale objectForKey:CPLocaleLanguageCode]];
356 }
357 
360 - (void)setShortStandaloneWeekdaySymbols:(CPArray)aValue
361 {
362  [self setSymbol:aValue forKey:@"shortStandaloneWeekdaySymbols" languageCode:[_locale objectForKey:CPLocaleLanguageCode]];
363 }
364 
368 {
369  return [self symbolForKey:@"veryShortStandaloneWeekdaySymbols" languageCode:[_locale objectForKey:CPLocaleLanguageCode]];
370 }
371 
374 - (void)setVeryShortStandaloneWeekdaySymbols:(CPArray)aValue
375 {
376  [self setSymbol:aValue forKey:@"veryShortStandaloneWeekdaySymbols" languageCode:[_locale objectForKey:CPLocaleLanguageCode]];
377 }
378 
381 - (CPArray)monthSymbols
382 {
383  return [self symbolForKey:@"monthSymbols" languageCode:[_locale objectForKey:CPLocaleLanguageCode]];
384 }
385 
388 - (void)setMonthSymbols:(CPArray)aValue
389 {
390  [self setSymbol:aValue forKey:@"monthSymbols" languageCode:[_locale objectForKey:CPLocaleLanguageCode]];
391 }
392 
396 {
397  return [self symbolForKey:@"shortMonthSymbols" languageCode:[_locale objectForKey:CPLocaleLanguageCode]];
398 }
399 
402 - (void)setShortMonthSymbols:(CPArray)aValue
403 {
404  [self setSymbol:aValue forKey:@"shortMonthSymbols" languageCode:[_locale objectForKey:CPLocaleLanguageCode]];
405 }
406 
410 {
411  return [self symbolForKey:@"veryShortMonthSymbols" languageCode:[_locale objectForKey:CPLocaleLanguageCode]];
412 }
413 
416 - (void)setVeryShortMonthSymbols:(CPArray)aValue
417 {
418  [self setSymbol:aValue forKey:@"veryShortMonthSymbols" languageCode:[_locale objectForKey:CPLocaleLanguageCode]];
419 }
420 
424 {
425  return [self symbolForKey:@"standaloneMonthSymbols" languageCode:[_locale objectForKey:CPLocaleLanguageCode]];
426 }
427 
430 - (void)setStandaloneMonthSymbols:(CPArray)aValue
431 {
432  [self setSymbol:aValue forKey:@"standaloneMonthSymbols" languageCode:[_locale objectForKey:CPLocaleLanguageCode]];
433 }
434 
438 {
439  return [self symbolForKey:@"shortStandaloneMonthSymbols" languageCode:[_locale objectForKey:CPLocaleLanguageCode]];
440 }
441 
444 - (void)setShortStandaloneMonthSymbols:(CPArray)aValue
445 {
446  [self setSymbol:aValue forKey:@"shortStandaloneMonthSymbols" languageCode:[_locale objectForKey:CPLocaleLanguageCode]];
447 }
448 
452 {
453  return [self symbolForKey:@"veryShortStandaloneMonthSymbols" languageCode:[_locale objectForKey:CPLocaleLanguageCode]];
454 }
455 
458 - (void)setVeryShortStandaloneMonthSymbols:(CPArray)aValue
459 {
460  [self setSymbol:aValue forKey:@"veryShortStandaloneMonthSymbols" languageCode:[_locale objectForKey:CPLocaleLanguageCode]];
461 }
462 
465 - (CPArray)quarterSymbols
466 {
467  return [self symbolForKey:@"quarterSymbols" languageCode:[_locale objectForKey:CPLocaleLanguageCode]];
468 }
469 
472 - (void)setQuarterSymbols:(CPArray)aValue
473 {
474  [self setSymbol:aValue forKey:@"quarterSymbols" languageCode:[_locale objectForKey:CPLocaleLanguageCode]];
475 }
476 
480 {
481  return [self symbolForKey:@"shortQuarterSymbols" languageCode:[_locale objectForKey:CPLocaleLanguageCode]];
482 }
483 
486 - (void)setShortQuarterSymbols:(CPArray)aValue
487 {
488  [self setSymbol:aValue forKey:@"shortQuarterSymbols" languageCode:[_locale objectForKey:CPLocaleLanguageCode]];
489 }
490 
494 {
495  return [self symbolForKey:@"standaloneQuarterSymbols" languageCode:[_locale objectForKey:CPLocaleLanguageCode]];
496 }
497 
500 - (void)setStandaloneQuarterSymbols:(CPArray)aValue
501 {
502  [self setSymbol:aValue forKey:@"standaloneQuarterSymbols" languageCode:[_locale objectForKey:CPLocaleLanguageCode]];
503 }
504 
508 {
509  return [self symbolForKey:@"shortStandaloneQuarterSymbols" languageCode:[_locale objectForKey:CPLocaleLanguageCode]];
510 }
511 
514 - (void)setShortStandaloneQuarterSymbols:(CPArray)aValue
515 {
516  [self setSymbol:aValue forKey:@"shortStandaloneQuarterSymbols" languageCode:[_locale objectForKey:CPLocaleLanguageCode]];
517 }
518 
519 
520 #pragma mark -
521 #pragma mark StringFromDate methods
522 
528 - (CPString)stringFromDate:(CPDate)aDate
529 {
530  var format,
531  relativeWord,
532  result;
533 
534  if (!aDate)
535  return;
536 
537  aDate = [aDate copy];
538  [aDate _dateWithTimeZone:_timeZone];
539 
540  if (_dateFormat)
541  return [self _stringFromDate:aDate format:_dateFormat];
542 
543  switch (_dateStyle)
544  {
546  format = @"";
547  break;
548 
550  if ([self _isAmericanFormat])
551  format = @"M/d/yy";
552  else
553  format = @"dd/MM/yy";
554 
555  break;
556 
558  if ([self _isAmericanFormat])
559  format = @"MMM d, Y";
560  else
561  format = @"d MMM Y";
562 
563  break;
564 
566  if ([self _isAmericanFormat])
567  format = @"MMMM d, Y";
568  else
569  format = @"d MMMM Y";
570 
571  break;
572 
574  if ([self _isAmericanFormat])
575  format = @"EEEE, MMMM d, Y";
576  else
577  format = @"EEEE d MMMM Y";
578 
579  break;
580 
581  default:
582  format = @"";
583  }
584 
585 
586  if ([self doesRelativeDateFormatting])
587  {
588  var language = [_locale objectForKey:CPLocaleLanguageCode],
589  relativeWords = [relativeDateFormating valueForKey:language];
590 
591  for (var i = 1; i < [relativeWords count]; i = i + 2)
592  {
593  var date = [CPDate date];
594  [date _dateWithTimeZone:_timeZone];
595 
596  date.setHours(12);
597  date.setMinutes(0);
598  date.setSeconds(0);
599 
600  date.setDate([relativeWords objectAtIndex:i] + date.getDate());
601 
602  if (date.getDate() == aDate.getDate() && date.getMonth() == aDate.getMonth() && date.getFullYear() == aDate.getFullYear())
603  {
604  relativeWord = [relativeWords objectAtIndex:(i - 1)];
605  format = @"";
606  break;
607  }
608  }
609  }
610 
611  if ((relativeWord || format.length) && _timeStyle != CPDateFormatterNoStyle)
612  format += @" ";
613 
614  switch (_timeStyle)
615  {
617  format += @"";
618  break;
619 
621  if ([self _isEnglishFormat])
622  format += @"h:mm a";
623  else
624  format += @"H:mm";
625 
626  break;
627 
629  if ([self _isEnglishFormat])
630  format += @"h:mm:ss a";
631  else
632  format += @"H:mm:ss"
633 
634  break;
635 
637  if ([self _isEnglishFormat])
638  format += @"h:mm:ss a z";
639  else
640  format += @"H:mm:ss z";
641 
642  break;
643 
645  if ([self _isEnglishFormat])
646  format += @"h:mm:ss a zzzz";
647  else
648  format += @"h:mm:ss zzzz";
649 
650  break;
651 
652  default:
653  format += @"";
654  }
655 
656  result = [self _stringFromDate:aDate format:format];
657 
658  if (relativeWord)
659  result = relativeWord + result;
660 
661  return result;
662 }
663 
669 - (CPString)stringForObjectValue:(id)anObject
670 {
671  if ([anObject isKindOfClass:[CPDate class]])
672  return [self stringFromDate:anObject];
673  else
674  return nil;
675 }
676 
682 - (CPString)editingStringForObjectValue:(id)anObject
683 {
684  return [self stringForObjectValue:anObject];
685 }
686 
692 - (CPString)_stringFromDate:(CPDate)aDate format:(CPString)aFormat
693 {
694  var length = [aFormat length],
695  currentToken = [CPString new],
696  isTextToken = NO,
697  result = [CPString new];
698 
699  for (var i = 0; i < length; i++)
700  {
701  var character = [aFormat characterAtIndex:i];
702 
703  if (isTextToken)
704  {
705  if ([character isEqualToString:@"'"])
706  {
707  isTextToken = NO;
708  result += currentToken;
709  currentToken = [CPString new];
710  }
711  else
712  {
713  currentToken += character;
714  }
715 
716  continue;
717  }
718 
719  if ([character isEqualToString:@"'"])
720  {
721  if (!isTextToken)
722  {
723  isTextToken = YES;
724  result += currentToken;
725  currentToken = [CPString new];
726  }
727 
728  continue;
729  }
730 
731  if ([character isEqualToString:@","] || [character isEqualToString:@":"] || [character isEqualToString:@"/"] || [character isEqualToString:@"-"] || [character isEqualToString:@" "])
732  {
733  result += [self _stringFromToken:currentToken date:aDate];
734  result += character;
735  currentToken = [CPString new];
736  }
737  else
738  {
739  if ([currentToken length] && ![[currentToken characterAtIndex:0] isEqualToString:character])
740  {
741  result += [self _stringFromToken:currentToken date:aDate];
742  currentToken = [CPString new];
743  }
744 
745  currentToken += character;
746 
747  if (i == (length - 1))
748  result += [self _stringFromToken:currentToken date:aDate];
749  }
750  }
751 
752  return result;
753 }
754 
760 - (CPString)_stringFromToken:(CPString)aToken date:(CPDate)aDate
761 {
762  if (![aToken length])
763  return aToken;
764 
765  var character = [aToken characterAtIndex:0],
766  length = [aToken length],
767  timeZone = _timeZone;
768 
769  switch (character)
770  {
771  case @"G":
772  // TODO
773  CPLog.warn(@"Token not yet implemented " + aToken);
774  return [CPString new];
775 
776  case @"y":
777  var currentLength = [[CPString stringWithFormat:@"%i", aDate.getFullYear()] length];
778 
779  return [self _stringValueForValue:aDate.getFullYear() length:(length == 2)?length:currentLength];
780 
781  case @"Y":
782  var currentLength = [[CPString stringWithFormat:@"%i", aDate.getFullYear()] length];
783 
784  return [self _stringValueForValue:aDate.getFullYear() length:(length == 2)?length:currentLength];
785 
786  case @"u":
787  // TODO
788  CPLog.warn(@"Token not yet implemented " + aToken);
789  return [CPString new];
790 
791  case @"U":
792  // TODO
793  CPLog.warn(@"Token not yet implemented " + aToken);
794  return [CPString new];
795 
796  case @"Q":
797  var quarter = 1;
798 
799  if (aDate.getMonth() < 6 && aDate.getMonth() > 2)
800  quarter = 2;
801 
802  if (aDate.getMonth() > 5 && aDate.getMonth() < 9)
803  quarter = 3;
804 
805  if (aDate.getMonth() >= 9)
806  quarter = 4;
807 
808  if (length <= 2)
809  return [self _stringValueForValue:quarter length:MIN(2,length)];
810 
811  if (length == 3)
812  return [[self shortQuarterSymbols] objectAtIndex:(quarter - 1)];
813 
814  if (length >= 4)
815  return [[self quarterSymbols] objectAtIndex:(quarter - 1)];
816 
817  case @"q":
818  var quarter = 1;
819 
820  if (aDate.getMonth() < 6 && aDate.getMonth() > 2)
821  quarter = 2;
822 
823  if (aDate.getMonth() > 5 && aDate.getMonth() < 9)
824  quarter = 3;
825 
826  if (aDate.getMonth() >= 9)
827  quarter = 4;
828 
829  if (length <= 2)
830  return [self _stringValueForValue:quarter length:MIN(2,length)];
831 
832  if (length == 3)
833  return [[self shortStandaloneQuarterSymbols] objectAtIndex:(quarter - 1)];
834 
835  if (length >= 4)
836  return [[self standaloneQuarterSymbols] objectAtIndex:(quarter - 1)];
837 
838  case @"M":
839  var currentLength = [[CPString stringWithFormat:@"%i", aDate.getMonth() + 1] length];
840 
841  if (length <= 2)
842  return [self _stringValueForValue:(aDate.getMonth() + 1) length:MAX(currentLength,length)];
843 
844  if (length == 3)
845  return [[self shortMonthSymbols] objectAtIndex:aDate.getMonth()];
846 
847  if (length == 4)
848  return [[self monthSymbols] objectAtIndex:aDate.getMonth()];
849 
850  if (length >= 5)
851  return [[self veryShortMonthSymbols] objectAtIndex:aDate.getMonth()];
852 
853  case @"L":
854  var currentLength = [[CPString stringWithFormat:@"%i", aDate.getMonth() + 1] length];
855 
856  if (length <= 2)
857  return [self _stringValueForValue:(aDate.getMonth() + 1) length:MAX(currentLength,length)];
858 
859  if (length == 3)
860  return [[self shortStandaloneMonthSymbols] objectAtIndex:aDate.getMonth()];
861 
862  if (length == 4)
863  return [[self standaloneMonthSymbols] objectAtIndex:aDate.getMonth()];
864 
865  if (length >= 5)
866  return [[self veryShortStandaloneMonthSymbols] objectAtIndex:aDate.getMonth()];
867 
868  case @"I":
869  // Deprecated
870  CPLog.warn(@"Depreacted - Token not yet implemented " + aToken);
871  return [CPString new];
872 
873  case @"w":
874  var d = [aDate copy];
875 
876  d.setHours(0, 0, 0);
877  d.setDate(d.getDate() + 4 - (d.getDay() || 7));
878 
879  var yearStart = new Date(d.getFullYear(), 0, 1),
880  weekOfYear = Math.ceil((((d - yearStart) / 86400000) + 1) / 7);
881 
882  return [self _stringValueForValue:(weekOfYear + 1) length:MAX(2, length)];
883 
884  case @"W":
885  var firstDay = new Date(aDate.getFullYear(), aDate.getMonth(), 1).getDay(),
886  weekOfMonth = Math.ceil((aDate.getDate() + firstDay) / 7);
887 
888  return [self _stringValueForValue:weekOfMonth length:1];
889 
890  case @"d":
891  var currentLength = [[CPString stringWithFormat:@"%i", aDate.getDate()] length];
892 
893  return [self _stringValueForValue:aDate.getDate() length:MAX(length, currentLength)];
894 
895  case @"D":
896  var oneJan = new Date(aDate.getFullYear(), 0, 1),
897  dayOfYear = Math.ceil((aDate - oneJan) / 86400000),
898  currentLength = [[CPString stringWithFormat:@"%i", dayOfYear] length];
899 
900  return [self _stringValueForValue:dayOfYear length:MAX(currentLength, MIN(3, length))];
901 
902  case @"F":
903  var dayOfWeek = 1,
904  day = aDate.getDate();
905 
906  if (day > 7 && day < 15)
907  dayOfWeek = 2;
908 
909  if (day > 14 && day < 22)
910  dayOfWeek = 3;
911 
912  if (day > 21 && day < 29)
913  dayOfWeek = 4;
914 
915  if (day > 28)
916  dayOfWeek = 5;
917 
918  return [self _stringValueForValue:dayOfWeek length:1];
919 
920  case @"g":
921  CPLog.warn(@"Token not yet implemented " + aToken);
922  return [CPString new];
923 
924  case @"E":
925  var day = aDate.getDay();
926 
927  if (length <= 3)
928  return [[self shortWeekdaySymbols] objectAtIndex:day];
929 
930  if (length == 4)
931  return [[self weekdaySymbols] objectAtIndex:day];
932 
933  if (length >= 5)
934  return [[self veryShortWeekdaySymbols] objectAtIndex:day];
935 
936  case @"e":
937  var day = aDate.getDay();
938 
939  if (length <= 2)
940  return [self _stringValueForValue:(day + 1) length:MIN(2, length)];
941 
942  if (length == 3)
943  return [[self shortWeekdaySymbols] objectAtIndex:day];
944 
945  if (length == 4)
946  return [[self weekdaySymbols] objectAtIndex:day];
947 
948  if (length >= 5)
949  return [[self veryShortWeekdaySymbols] objectAtIndex:day];
950 
951  case @"c":
952  var day = aDate.getDay();
953 
954  if (length <= 2)
955  return [self _stringValueForValue:(day + 1) length:aDate.getDay().toString().length];
956 
957  if (length == 3)
958  return [[self shortStandaloneWeekdaySymbols] objectAtIndex:day];
959 
960  if (length == 4)
961  return [[self standaloneWeekdaySymbols] objectAtIndex:day];
962 
963  if (length >= 5)
964  return [[self veryShortStandaloneWeekdaySymbols] objectAtIndex:day];
965 
966  case @"a":
967 
968  if (aDate.getHours() > 11)
969  return [self PMSymbol];
970  else
971  return [self AMSymbol];
972 
973  case @"h":
974  var hours = aDate.getHours();
975 
976  if ([self _isAmericanFormat] || [self _isEnglishFormat])
977  {
978  if (hours == 0)
979  hours = 12;
980  else if (hours > 12)
981  hours = hours - 12;
982  }
983 
984  var currentLength = [[CPString stringWithFormat:@"%i", hours] length];
985 
986  return [self _stringValueForValue:hours length:MAX(currentLength, MIN(2, length))];
987 
988  case @"H":
989  var currentLength = [[CPString stringWithFormat:@"%i", aDate.getHours()] length];
990 
991  return [self _stringValueForValue:aDate.getHours() length:MAX(currentLength, MIN(2, length))];
992 
993  case @"K":
994  var hours = aDate.getHours();
995 
996  if (hours > 12)
997  hours -= 12;
998 
999  var currentLength = [[CPString stringWithFormat:@"%i", hours] length];
1000 
1001  return [self _stringValueForValue:hours length:MAX(currentLength, MIN(2, length))];
1002 
1003  case @"k":
1004  var hours = aDate.getHours();
1005 
1006  if (aDate.getHours() == 0)
1007  hours = 24;
1008 
1009  var currentLength = [[CPString stringWithFormat:@"%i", hours] length];
1010 
1011  return [self _stringValueForValue:hours length:MAX(currentLength, MIN(2, length))];
1012 
1013  case @"j":
1014  CPLog.warn(@"Token not yet implemented " + aToken);
1015  return [CPString new];
1016 
1017  case @"m":
1018  var currentLength = [[CPString stringWithFormat:@"%i", aDate.getMinutes()] length];
1019 
1020  return [self _stringValueForValue:aDate.getMinutes() length:MAX(currentLength, MIN(2, length))];
1021 
1022  case @"s":
1023  var currentLength = [[CPString stringWithFormat:@"%i", aDate.getMinutes()] length];
1024 
1025  return [self _stringValueForValue:aDate.getSeconds() length:MIN(2, length)];
1026 
1027  case @"S":
1028  return [self _stringValueForValue:aDate.getMilliseconds() length:length];
1029 
1030  case @"A":
1031  var value = aDate.getHours() * 60 * 60 * 1000 + aDate.getMinutes() * 60 * 1000 + aDate.getSeconds() * 1000 + aDate.getMilliseconds();
1032 
1033  return [self _stringValueForValue:value length:value.toString().length];
1034 
1035  case @"z":
1036  if (length <= 3)
1037  return [timeZone localizedName:CPTimeZoneNameStyleShortDaylightSaving locale:_locale];
1038  else
1039  return [timeZone localizedName:CPTimeZoneNameStyleDaylightSaving locale:_locale];
1040 
1041  case @"Z":
1042  var seconds = [timeZone secondsFromGMT],
1043  minutes = seconds / 60,
1044  hours = minutes / 60,
1045  result,
1046  diffMinutes = (hours - parseInt(hours)) * 100 * 60 / 100;
1047 
1048  if (length <= 3)
1049  {
1050  result = diffMinutes.toString();
1051 
1052  while ([result length] < 2)
1053  result = @"0" + result;
1054 
1055  result = ABS(parseInt(hours)) + result;
1056 
1057  while ([result length] < 4)
1058  result = @"0" + result;
1059 
1060  if (seconds > 0)
1061  result = @"+" + result;
1062  else
1063  result = @"-" + result;
1064 
1065  return result;
1066  }
1067  else if (length == 4)
1068  {
1069  result = diffMinutes.toString();
1070 
1071  while ([result length] < 2)
1072  result = @"0" + result;
1073 
1074  result = @":" + result;
1075  result = ABS(parseInt(hours)) + result;
1076 
1077  while ([result length] < 5)
1078  result = @"0" + result;
1079 
1080  if (seconds > 0)
1081  result = @"+" + result;
1082  else
1083  result = @"-" + result;
1084 
1085  return @"GMT" + result;
1086  }
1087  else
1088  {
1089  result = diffMinutes.toString();
1090 
1091  while ([result length] < 2)
1092  result = @"0" + result;
1093 
1094  result = @":" + result;
1095  result = ABS(parseInt(hours)) + result;
1096 
1097  while ([result length] < 5)
1098  result = @"0" + result;
1099 
1100  if (seconds > 0)
1101  result = @"+" + result;
1102  else
1103  result = @"-" + result;
1104 
1105  return result;
1106  }
1107 
1108  case @"v":
1109  if (length == 1)
1110  return [timeZone localizedName:CPTimeZoneNameStyleShortGeneric locale:_locale];
1111  else if (length == 4)
1112  return [timeZone localizedName:CPTimeZoneNameStyleGeneric locale:_locale];
1113 
1114  return @" ";
1115 
1116  case @"V":
1117  if (length == 1)
1118  {
1119  return [timeZone localizedName:CPTimeZoneNameStyleShortDaylightSaving locale:_locale];
1120  }
1121  else if (length == 4)
1122  {
1123  CPLog.warn(@"No pattern found for " + aToken);
1124  return @"";
1125  }
1126 
1127  return @" ";
1128 
1129  default:
1130  CPLog.warn(@"No pattern found for " + aToken);
1131  return aToken;
1132  }
1133 
1134  return [CPString new];
1135 }
1136 
1137 
1138 #pragma mark -
1139 #pragma mark datefromString
1140 
1146 - (CPDate)dateFromString:(CPString)aString
1147 {
1148  var format;
1149 
1150  if (_dateFormat != nil)
1151  return [self _dateFromString:aString format:_dateFormat];
1152 
1153  switch (_dateStyle)
1154  {
1156  format = @"";
1157  break;
1158 
1160  if ([self _isAmericanFormat])
1161  format = @"M/d/yy";
1162  else
1163  format = @"dd/MM/yy";
1164 
1165  break;
1166 
1168  if ([self _isAmericanFormat])
1169  format = @"MMM d, Y";
1170  else
1171  format = @"d MMM Y";
1172 
1173  break;
1174 
1176  if ([self _isAmericanFormat])
1177  format = @"MMMM d, Y";
1178  else
1179  format = @"d MMMM Y";
1180 
1181  break;
1182 
1184  if ([self _isAmericanFormat])
1185  format = @"EEEE, MMMM d, Y";
1186  else
1187  format = @"EEEE d MMMM Y";
1188 
1189  break;
1190 
1191  default:
1192  format = @"";
1193  }
1194 
1195  switch (_timeStyle)
1196  {
1198  format += @"";
1199  break;
1200 
1202  if ([self _isEnglishFormat])
1203  format += @" h:mm a";
1204  else
1205  format += @" H:mm";
1206  break;
1207 
1209  if ([self _isEnglishFormat])
1210  format += @" h:mm:ss a";
1211  else
1212  format += @" H:mm:ss"
1213  break;
1214 
1216  if ([self _isEnglishFormat])
1217  format += @" h:mm:ss a z";
1218  else
1219  format += @" H:mm:ss z";
1220  break;
1221 
1223  if ([self _isEnglishFormat])
1224  format += @" h:mm:ss a zzzz";
1225  else
1226  format += @" h:mm:ss zzzz";
1227  break;
1228 
1229  default:
1230  format += @"";
1231  }
1232 
1233  return [self _dateFromString:aString format:format];
1234 }
1235 
1242 - (BOOL)getObjectValue:(idRef)anObject forString:(CPString)aString errorDescription:(CPStringRef)anError
1243 {
1244  var value = [self dateFromString:aString];
1245  @deref(anObject) = value;
1246 
1247  if (!value)
1248  {
1249  if (anError)
1250  @deref(anError) = @"The value \"" + aString + "\" is invalid.";
1251 
1252  return NO;
1253  }
1254 
1255  return YES;
1256 }
1257 
1263 - (CPDate)_dateFromString:(CPString)aString format:(CPString)aFormat
1264 {
1265  // Interpret @"" as the date 2000-01-01 00:00:00 +0000, like in Cocoa. No idea why they picked this particular date.
1266  if (!aString)
1268 
1269  if (aFormat == nil)
1270  return nil;
1271 
1272  var currentToken = [CPString new],
1273  isTextToken = NO,
1274  tokens = [CPArray array],
1275  dateComponents = [CPArray array],
1276  patternTokens = [CPArray array];
1277 
1278  for (var i = 0; i < [aFormat length]; i++)
1279  {
1280  var character = [aFormat characterAtIndex:i];
1281 
1282  if (isTextToken)
1283  {
1284  if ([character isEqualToString:@"'"])
1285  currentToken = [CPString new];
1286 
1287  continue;
1288  }
1289 
1290  if ([character isEqualToString:@"'"])
1291  {
1292  if (!isTextToken)
1293  isTextToken = YES;
1294 
1295  continue;
1296  }
1297 
1298  if ([character isEqualToString:@","] || [character isEqualToString:@":"] || [character isEqualToString:@"/"] || [character isEqualToString:@"-"] || [character isEqualToString:@" "])
1299  {
1300  [tokens addObject:currentToken];
1301 
1302  if ([patternStringTokens containsObject:currentToken])
1303  [patternTokens addObject:[tokens count] - 1];
1304 
1305  currentToken = [CPString new];
1306  }
1307  else
1308  {
1309  if ([currentToken length] && ![[currentToken characterAtIndex:0] isEqualToString:character])
1310  {
1311  [tokens addObject:currentToken];
1312 
1313  if ([patternStringTokens containsObject:currentToken])
1314  [patternTokens addObject:[tokens count] - 1];
1315 
1316  currentToken = [CPString new];
1317  }
1318 
1319  currentToken += character;
1320 
1321  if (i == ([aFormat length] - 1))
1322  {
1323  [tokens addObject:currentToken];
1324 
1325  if ([patternStringTokens containsObject:currentToken])
1326  [patternTokens addObject:[tokens count] - 1];
1327  }
1328  }
1329  }
1330 
1331  isTextToken = NO;
1332  currentToken = [CPString new];
1333 
1334  var currentIndexSpecialPattern = 0;
1335 
1336  if ([patternTokens count] == 0)
1337  [patternTokens addObject:CPNotFound];
1338 
1339  for (var i = 0; i < [aString length]; i++)
1340  {
1341  var character = [aString characterAtIndex:i];
1342 
1343  if (isTextToken)
1344  {
1345  if ([character isEqualToString:@"'"])
1346  currentToken = [CPString new];
1347 
1348  continue;
1349  }
1350 
1351  if ([character isEqualToString:@"'"])
1352  {
1353  if (!isTextToken)
1354  isTextToken = YES;
1355 
1356  continue;
1357  }
1358 
1359  // Need to do this to check if the word match with the token. We can get some words with space...
1360  if ([dateComponents count] == [patternTokens objectAtIndex:currentIndexSpecialPattern])
1361  {
1362  var j = [self _lastIndexMatchedString:aString token:[tokens objectAtIndex:[dateComponents count]] index:i];
1363 
1364  if (j == CPNotFound)
1365  return nil;
1366 
1367  currentIndexSpecialPattern++;
1368  [dateComponents addObject:[aString substringWithRange:CPMakeRange(i, (j - i))]];
1369  i = j;
1370 
1371  continue;
1372  }
1373 
1374  if ([character isEqualToString:@","] || [character isEqualToString:@":"] || [character isEqualToString:@"/"] || [character isEqualToString:@"-"] || [character isEqualToString:@" "])
1375  {
1376  [dateComponents addObject:currentToken];
1377  currentToken = [CPString new];
1378  }
1379  else
1380  {
1381  currentToken += character;
1382 
1383  if (i == ([aString length] - 1))
1384  [dateComponents addObject:currentToken];
1385  }
1386  }
1387 
1388  if ([dateComponents count] != [tokens count])
1389  return nil;
1390 
1391  return [self _dateFromTokens:tokens dateComponents:dateComponents];
1392 }
1393 
1394 - (CPDate)_dateFromTokens:(CPArray)tokens dateComponents:(CPArray)dateComponents
1395 {
1396  var timeZoneseconds = [_timeZone secondsFromGMT],
1397  dateArray = [2000, 01, 01, 00, 00, 00, @"+0000"],
1398  isPM = NO,
1399  dayOfYear,
1400  dayIndexInWeek,
1401  weekOfYear,
1402  weekOfMonth;
1403 
1404  for (var i = 0; i < [tokens count]; i++)
1405  {
1406  var token = [tokens objectAtIndex:i],
1407  dateComponent = [dateComponents objectAtIndex:i],
1408  character = [token characterAtIndex:0],
1409  length = [token length];
1410 
1411  switch (character)
1412  {
1413  case @"G":
1414  // TODO
1415  CPLog.warn(@"Token not yet implemented " + token);
1416  break;
1417 
1418  case @"y":
1419  var u = _twoDigitStartDate.getFullYear() % 10,
1420  d = parseInt(_twoDigitStartDate.getFullYear() / 10) % 10,
1421  c = parseInt(_twoDigitStartDate.getFullYear() / 100) % 10,
1422  m = parseInt(_twoDigitStartDate.getFullYear() / 1000) % 10;
1423 
1424  if (length == 2 && dateComponent.length == 2)
1425  {
1426  if ((u + d * 10) >= parseInt(dateComponent))
1427  dateArray[0] = (c + 1) * 100 + m * 1000 + parseInt(dateComponent);
1428  else
1429  dateArray[0] = c * 100 + m * 1000 + parseInt(dateComponent);
1430  }
1431  else
1432  {
1433  dateArray[0] = parseInt(dateComponent);
1434  }
1435 
1436  break;
1437 
1438  case @"Y":
1439  var u = _twoDigitStartDate.getFullYear() % 10,
1440  d = parseInt(_twoDigitStartDate.getFullYear() / 10) % 10,
1441  c = parseInt(_twoDigitStartDate.getFullYear() / 100) % 10,
1442  m = parseInt(_twoDigitStartDate.getFullYear() / 1000) % 10;
1443 
1444  if (length == 2 && dateComponent.length == 2)
1445  {
1446  if ((u + d * 10) >= parseInt(dateComponent))
1447  dateArray[0] = (c + 1) * 100 + m * 1000 + parseInt(dateComponent);
1448  else
1449  dateArray[0] = c * 100 + m * 1000 + parseInt(dateComponent);
1450  }
1451  else
1452  {
1453  dateArray[0] = parseInt(dateComponent);
1454  }
1455 
1456  break;
1457 
1458  case @"u":
1459  // TODO
1460  CPLog.warn(@"Token not yet implemented " + token);
1461  break;
1462 
1463  case @"U":
1464  // TODO
1465  CPLog.warn(@"Token not yet implemented " + token);
1466  break;
1467 
1468  case @"Q":
1469  var month;
1470 
1471  if (length <= 2)
1472  month = (parseInt(dateComponent) - 1) * 3;
1473 
1474  if (length == 3)
1475  {
1476  if (![[self shortQuarterSymbols] containsObject:dateComponent])
1477  return nil;
1478 
1479  month = [[self shortQuarterSymbols] indexOfObject:dateComponent] * 3;
1480  }
1481 
1482  if (length >= 4)
1483  {
1484  if (![[self quarterSymbols] containsObject:dateComponent])
1485  return nil;
1486 
1487  month = [[self quarterSymbols] indexOfObject:dateComponent] * 3;
1488  }
1489 
1490  if (month > 11)
1491  return nil;
1492 
1493  dateArray[1] = month + 1;
1494  break;
1495 
1496  case @"q":
1497  var month;
1498 
1499  if (length <= 2)
1500  month = (parseInt(dateComponent) - 1) * 3;
1501 
1502  if (length == 3)
1503  {
1504  if (![[self shortQuarterSymbols] containsObject:dateComponent])
1505  return nil;
1506 
1507  month = [[self shortQuarterSymbols] indexOfObject:dateComponent] * 3;
1508  }
1509 
1510  if (length >= 4)
1511  {
1512  if (![[self quarterSymbols] containsObject:dateComponent])
1513  return nil;
1514 
1515  month = [[self quarterSymbols] indexOfObject:dateComponent] * 3;
1516  }
1517 
1518  if (month > 11)
1519  return nil;
1520 
1521  dateArray[1] = month + 1;
1522  break;
1523 
1524  case @"M":
1525  var month;
1526 
1527  if (length <= 2)
1528  month = parseInt(dateComponent)
1529 
1530  if (length == 3)
1531  {
1532  if (![[self shortMonthSymbols] containsObject:dateComponent])
1533  return nil;
1534 
1535  month = [[self shortMonthSymbols] indexOfObject:dateComponent] + 1;
1536  }
1537 
1538  if (length == 4)
1539  {
1540  if (![[self monthSymbols] containsObject:dateComponent])
1541  return nil;
1542 
1543  month = [[self monthSymbols] indexOfObject:dateComponent] + 1;
1544  }
1545 
1546  if (month > 12 || length >= 5)
1547  return nil;
1548 
1549  dateArray[1] = month;
1550  break;
1551 
1552  case @"L":
1553  var month;
1554 
1555  if (length <= 2)
1556  month = parseInt(dateComponent);
1557 
1558  if (length == 3)
1559  {
1560  if (![[self shortStandaloneMonthSymbols] containsObject:dateComponent])
1561  return nil;
1562 
1563  month = [[self shortStandaloneMonthSymbols] indexOfObject:dateComponent] + 1;
1564  }
1565 
1566  if (length == 4)
1567  {
1568  if (![[self standaloneMonthSymbols] containsObject:dateComponent])
1569  return nil;
1570 
1571  month = [[self standaloneMonthSymbols] indexOfObject:dateComponent] + 1;
1572  }
1573 
1574  if (month > 12 || length >= 5)
1575  return nil;
1576 
1577  dateArray[1] = month;
1578  break;
1579 
1580  case @"I":
1581  // Deprecated
1582  CPLog.warn(@"Depreacted - Token not yet implemented " + token);
1583  break;
1584 
1585  case @"w":
1586  if (dateComponent > 52)
1587  return nil;
1588 
1589  weekOfYear = dateComponent;
1590  break;
1591 
1592  case @"W":
1593  if (dateComponent > 52)
1594  return nil;
1595 
1596  weekOfMonth = dateComponent;
1597  break;
1598 
1599  case @"d":
1600  dateArray[2] = parseInt(dateComponent);
1601  break;
1602 
1603  case @"D":
1604  if (isNaN(parseInt(dateComponent)) || parseInt(dateComponent) > 345)
1605  return nil;
1606 
1607  dayOfYear = parseInt(dateComponent);
1608  break;
1609 
1610  case @"F":
1611  if (isNaN(parseInt(dateComponent)) || parseInt(dateComponent) > 5 || parseInt(dateComponent) == 0)
1612  return nil;
1613 
1614  if (parseInt(dateComponent) == 1)
1615  dateArray[2] = 1;
1616 
1617  if (parseInt(dateComponent) == 2)
1618  dateArray[2] = 8;
1619 
1620  if (parseInt(dateComponent) == 3)
1621  dateArray[2] = 15;
1622 
1623  if (parseInt(dateComponent) == 4)
1624  dateArray[2] = 22;
1625 
1626  if (parseInt(dateComponent) == 5)
1627  dateArray[2] = 29;
1628 
1629  break;
1630 
1631  case @"g":
1632  CPLog.warn(@"Token not yet implemented " + token);
1633  break;
1634 
1635  case @"E":
1636  if (length <= 3)
1637  dayIndexInWeek = [[self shortWeekdaySymbols] indexOfObject:dateComponent];
1638 
1639  if (length == 4)
1640  dayIndexInWeek = [[self weekdaySymbols] indexOfObject:dateComponent];
1641 
1642  if (dayIndexInWeek == CPNotFound || length >= 5)
1643  return nil;
1644 
1645  break;
1646 
1647  case @"e":
1648  if (length <= 2 && isNaN(parseInt(dateComponent)))
1649  return nil;
1650 
1651  if (length <= 2)
1652  dayIndexInWeek = parseInt(dateComponent);
1653 
1654  if (length == 3)
1655  dayIndexInWeek = [[self shortWeekdaySymbols] indexOfObject:dateComponent];
1656 
1657  if (length == 4)
1658  dayIndexInWeek = [[self weekdaySymbols] indexOfObject:dateComponent];
1659 
1660  if (dayIndexInWeek == CPNotFound || length >= 5)
1661  return nil;
1662 
1663  break;
1664 
1665  case @"c":
1666  if (length <= 2 && isNaN(parseInt(dateComponent)))
1667  return nil;
1668 
1669  if (length <= 2)
1670  dayIndexInWeek = dateComponent;
1671 
1672  if (length == 3)
1673  dayIndexInWeek = [[self shortStandaloneWeekdaySymbols] indexOfObject:dateComponent];
1674 
1675  if (length == 4)
1676  dayIndexInWeek = [[self standaloneWeekdaySymbols] indexOfObject:dateComponent];
1677 
1678  if (length == 5)
1679  dayIndexInWeek = [[self veryShortStandaloneWeekdaySymbols] indexOfObject:dateComponent];
1680 
1681  if (dayIndexInWeek == CPNotFound || length >= 5)
1682  return nil;
1683 
1684  break;
1685 
1686  case @"a":
1687  if (![dateComponent isEqualToString:[self PMSymbol]] && ![dateComponent isEqualToString:[self AMSymbol]])
1688  return nil;
1689 
1690  if ([dateComponent isEqualToString:[self PMSymbol]])
1691  isPM = YES;
1692 
1693  break;
1694 
1695  case @"h":
1696  if (parseInt(dateComponent) < 0 || parseInt(dateComponent) > 12)
1697  return nil;
1698 
1699  dateArray[3] = parseInt(dateComponent);
1700  break;
1701 
1702  case @"H":
1703  if (parseInt(dateComponent) < 0 || parseInt(dateComponent) > 23)
1704  return nil;
1705 
1706  dateArray[3] = parseInt(dateComponent);
1707  break;
1708 
1709  case @"K":
1710  if (parseInt(dateComponent) < 0 || parseInt(dateComponent) > 11)
1711  return nil;
1712 
1713  dateArray[3] = parseInt(dateComponent);
1714  break;
1715 
1716  case @"k":
1717  if (parseInt(dateComponent) < 0 || parseInt(dateComponent) > 12)
1718  return nil;
1719 
1720  dateArray[3] = parseInt(dateComponent);
1721  break;
1722 
1723  case @"j":
1724  CPLog.warn(@"Token not yet implemented " + token);
1725  break;
1726 
1727  case @"m":
1728  var minutes = parseInt(dateComponent);
1729 
1730  if (minutes > 59)
1731  return nil;
1732 
1733  dateArray[4] = minutes;
1734  break;
1735 
1736  case @"s":
1737  var seconds = parseInt(dateComponent);
1738 
1739  if (seconds > 59)
1740  return nil;
1741 
1742  dateArray[5] = seconds;
1743  break;
1744 
1745  case @"S":
1746  if (isNaN(parseInt(dateComponent)))
1747  return nil;
1748 
1749  break;
1750 
1751  case @"A":
1752  if (isNaN(parseInt(dateComponent)))
1753  return nil;
1754 
1755  var millisecondsInDay = parseInt(dateComponent),
1756  tmpDate = new Date();
1757 
1758  tmpDate.setHours(0);
1759  tmpDate.setMinutes(0);
1760  tmpDate.setSeconds(0);
1761  tmpDate.setMilliseconds(0);
1762 
1763  tmpDate.setMilliseconds(millisecondsInDay);
1764 
1765  dateArray[3] = tmpDate.getHours();
1766  dateArray[4] = tmpDate.getMinutes();
1767  dateArray[5] = tmpDate.getSeconds();
1768  break;
1769 
1770  case @"z":
1771  if (length < 4)
1772  timeZoneseconds = [self _secondsFromTimeZoneString:dateComponent style:CPTimeZoneNameStyleShortDaylightSaving];
1773  else
1774  timeZoneseconds = [self _secondsFromTimeZoneString:dateComponent style:CPTimeZoneNameStyleDaylightSaving];
1775 
1776  if (!timeZoneseconds)
1777  timeZoneseconds = [self _secondsFromTimeZoneDefaultFormatString:dateComponent];
1778 
1779  if (!timeZoneseconds)
1780  return nil;
1781 
1782  timeZoneseconds = timeZoneseconds + 60 * 60;
1783 
1784  break;
1785 
1786  case @"Z":
1787  timeZoneseconds = [self _secondsFromTimeZoneDefaultFormatString:dateComponent];
1788 
1789  if (!timeZoneseconds)
1790  return nil;
1791 
1792  timeZoneseconds = timeZoneseconds + 60 * 60;
1793 
1794  break;
1795 
1796  case @"v":
1797  if (length <= 3)
1798  timeZoneseconds = [self _secondsFromTimeZoneString:dateComponent style:CPTimeZoneNameStyleShortGeneric];
1799  else
1800  timeZoneseconds = [self _secondsFromTimeZoneString:dateComponent style:CPTimeZoneNameStyleGeneric];
1801 
1802  if (!timeZoneseconds && length == 4)
1803  timeZoneseconds = [self _secondsFromTimeZoneDefaultFormatString:dateComponent];
1804 
1805  if (!timeZoneseconds)
1806  return nil;
1807 
1808  timeZoneseconds = timeZoneseconds + 60 * 60;
1809 
1810  break;
1811 
1812  case @"V":
1813  if (length <= 3)
1814  timeZoneseconds = [self _secondsFromTimeZoneString:dateComponent style:CPTimeZoneNameStyleShortStandard];
1815  else
1816  timeZoneseconds = [self _secondsFromTimeZoneString:dateComponent style:CPTimeZoneNameStyleStandard];
1817 
1818  if (!timeZoneseconds)
1819  timeZoneseconds = [self _secondsFromTimeZoneDefaultFormatString:dateComponent];
1820 
1821  if (!timeZoneseconds)
1822  return nil;
1823 
1824  timeZoneseconds = timeZoneseconds + 60 * 60;
1825 
1826  break;
1827 
1828  default:
1829  CPLog.warn(@"No pattern found for " + token);
1830  return nil;
1831  }
1832  }
1833 
1834  // Make the calcul day of the year
1835  if (dayOfYear)
1836  {
1837  var tmpDate = new Date();
1838  tmpDate.setFullYear(dateArray[0]);
1839  tmpDate.setMonth(0);
1840 
1841  tmpDate.setDate(dayOfYear)
1842 
1843  dateArray[1] = tmpDate.getMonth() + 1;
1844  dateArray[2] = tmpDate.getDate();
1845  }
1846 
1847  if (weekOfMonth)
1848  dateArray[2] = (weekOfMonth - 1) * 7 + 1;
1849 
1850  if (weekOfYear)
1851  {
1852  var tmpDate = new Date();
1853  tmpDate.setFullYear(dateArray[0]);
1854  tmpDate.setMonth(0);
1855  tmpDate.setDate(1);
1856 
1857  while (tmpDate.getDay() != 0)
1858  tmpDate.setDate(tmpDate.getDate() + 1);
1859 
1860  tmpDate.setDate(tmpDate.getDate() + (weekOfYear - 1) * 7);
1861 
1862  dateArray[1] = tmpDate.getMonth() + 1;
1863  dateArray[2] = tmpDate.getDate() - 1;
1864  }
1865 
1866  // Check if the day is possible in the current month
1867  var tmpDate = new Date();
1868  tmpDate.setMonth(dateArray[1] - 1);
1869  tmpDate.setFullYear(dateArray[0]);
1870 
1871  if (dateArray[2] <= 0 || dateArray[2] > [tmpDate _daysInMonth])
1872  return nil;
1873 
1874  // PM hours
1875  if (isPM)
1876  dateArray[3] += 12;
1877 
1878  if (isNaN(parseInt(dateArray[0])) || isNaN(parseInt(dateArray[1])) || isNaN(parseInt(dateArray[2])) || isNaN(parseInt(dateArray[3])) || isNaN(parseInt(dateArray[4])) || isNaN(parseInt(dateArray[5])) || isNaN(parseInt(dateArray[6])))
1879  return nil;
1880 
1881  var dateResult = [[CPDate alloc] initWithString:[CPString stringWithFormat:@"%04d-%02d-%02d %02d:%02d:%02d %s", dateArray[0], dateArray[1], dateArray[2], dateArray[3], dateArray[4], dateArray[5], dateArray[6]]];
1882  dateResult.setSeconds(dateResult.getSeconds() - timeZoneseconds + 60 * 60);
1883 
1884  return dateResult;
1885 }
1886 
1887 
1888 #pragma mark -
1889 #pragma mark Utils
1890 
1891 - (CPString)_stringValueForValue:(id)aValue length:(int)length
1892 {
1893  var string = [CPString stringWithFormat:@"%i", aValue];
1894 
1895  if ([string length] == length)
1896  return string;
1897 
1898  if ([string length] > length)
1899  return [string substringFromIndex:([string length] - length)];
1900 
1901  while ([string length] < length)
1902  string = [CPString stringWithFormat:@"0%s", string];
1903 
1904  return string;
1905 }
1906 
1909 - (BOOL)_isAmericanFormat
1910 {
1911  return [[_locale objectForKey:CPLocaleCountryCode] isEqualToString:@"US"];
1912 }
1913 
1916 - (BOOL)_isEnglishFormat
1917 {
1918  return [[_locale objectForKey:CPLocaleLanguageCode] isEqualToString:@"en"];
1919 }
1920 
1923 - (int)_secondsFromTimeZoneDefaultFormatString:(CPString)aTimeZoneFormatString
1924 {
1925  var format = new RegExp("\\w*([HPG-GMT])?([+-])(\\d{1,2})([:])?(\\d{2})\\w*"),
1926  result = aTimeZoneFormatString.match(new RegExp(format)),
1927  seconds = 0;
1928 
1929  if (!result)
1930  return nil;
1931 
1932  seconds = result[3] * 60 * 60 + result[5] * 60;
1933 
1934  if ([result[2] isEqualToString:@"-"])
1935  seconds = -seconds;
1936 
1937  return seconds;
1938 }
1939 
1942 - (int)_secondsFromTimeZoneString:(CPString)aTimeZoneString style:(NSTimeZoneNameStyle)aStyle
1943 {
1944  var timeZone = [CPTimeZone _timeZoneFromString:aTimeZoneString style:aStyle locale:_locale];
1945 
1946  if (!timeZone)
1947  return nil;
1948 
1949  return [timeZone secondsFromGMT];
1950 }
1951 
1958 - (int)_lastIndexMatchedString:(CPString)aString token:(CPString)aToken index:anIndex
1959 {
1960  var character = [aToken characterAtIndex:0],
1961  length = [aToken length],
1962  targetedArray,
1963  format = new RegExp("\\w*([HPG-GMT])?([+-])(\\d{1,2})([:])?(\\d{2})\\w*"),
1964  result = aString.match(new RegExp(format));
1965 
1966  switch (character)
1967  {
1968  case @"Q":
1969  if (length == 3)
1970  targetedArray = [self shortQuarterSymbols];
1971 
1972  if (length >= 4)
1973  targetedArray = [self quarterSymbols];
1974 
1975  break;
1976 
1977  case @"q":
1978  if (length == 3)
1979  targetedArray = [self shortStandaloneQuarterSymbols];
1980 
1981  if (length >= 4)
1982  targetedArray = [self standaloneQuarterSymbols];
1983 
1984  break;
1985 
1986  case @"M":
1987  if (length == 3)
1988  targetedArray = [self shortMonthSymbols];
1989 
1990  if (length == 4)
1991  targetedArray = [self monthSymbols];
1992 
1993  if (length >= 5)
1994  targetedArray = [self veryShortMonthSymbols];
1995 
1996  break;
1997 
1998  case @"L":
1999  if (length == 3)
2000  targetedArray = [self shortStandaloneMonthSymbols];
2001 
2002  if (length == 4)
2003  targetedArray = [self standaloneMonthSymbols];
2004 
2005  if (length >= 5)
2006  targetedArray = [self veryShortStandaloneMonthSymbols];
2007 
2008  break;
2009 
2010  case @"E":
2011  if (length <= 3)
2012  targetedArray = [self shortWeekdaySymbols];
2013 
2014  if (length == 4)
2015  targetedArray = [self weekdaySymbols];
2016 
2017  if (length >= 5)
2018  targetedArray = [self veryShortWeekdaySymbols];
2019 
2020  break;
2021 
2022  case @"e":
2023  if (length == 3)
2024  targetedArray = [self shortWeekdaySymbols];
2025 
2026  if (length == 4)
2027  targetedArray = [self weekdaySymbols];
2028 
2029  if (length >= 5)
2030  targetedArray = [self veryShortWeekdaySymbols];
2031 
2032  break;
2033 
2034  case @"c":
2035  if (length == 3)
2036  targetedArray = [self shortStandaloneWeekdaySymbols];
2037 
2038  if (length == 4)
2039  targetedArray = [self standaloneWeekdaySymbols];
2040 
2041  if (length >= 5)
2042  targetedArray = [self veryShortStandaloneWeekdaySymbols];
2043 
2044  break;
2045 
2046  case @"a":
2047  targetedArray = [[self PMSymbol], [self AMSymbol]];
2048  break;
2049 
2050  case @"z":
2051  if (length <= 3)
2052  targetedArray = [CPTimeZone _namesForStyle:CPTimeZoneNameStyleShortDaylightSaving locale:_locale];
2053  else
2054  targetedArray = [CPTimeZone _namesForStyle:CPTimeZoneNameStyleDaylightSaving locale:_locale];
2055 
2056  if (result)
2057  return anIndex + [result objectAtIndex:0].length;
2058 
2059  break;
2060 
2061  case @"Z":
2062  if (result)
2063  return anIndex + [result objectAtIndex:0].length;
2064 
2065  return CPNotFound;
2066 
2067  case @"v":
2068  if (length == 1)
2069  targetedArray = [CPTimeZone _namesForStyle:CPTimeZoneNameStyleShortGeneric locale:_locale];
2070  else if (length == 4)
2071  targetedArray = [CPTimeZone _namesForStyle:CPTimeZoneNameStyleGeneric locale:_locale];
2072 
2073  if (result)
2074  return anIndex + [result objectAtIndex:0].length;
2075 
2076  break;
2077 
2078  case @"V":
2079  if (length == 1)
2080  targetedArray = [CPTimeZone _namesForStyle:CPTimeZoneNameStyleShortStandard locale:_locale];
2081 
2082  if (result)
2083  return anIndex + [result objectAtIndex:0].length;
2084 
2085  break;
2086 
2087  default:
2088  CPLog.warn(@"No pattern found for " + aToken);
2089  return CPNotFound;
2090  }
2091 
2092  for (var i = 0; i < [targetedArray count]; i++)
2093  {
2094  var currentObject = [targetedArray objectAtIndex:i],
2095  range = [aString rangeOfString:currentObject];
2096 
2097  if (range.length == 0)
2098  continue;
2099 
2100  character = [aString characterAtIndex:(anIndex + range.length)];
2101 
2102  if ([character isEqualToString:@"'"] || [character isEqualToString:@","] || [character isEqualToString:@":"] || [character isEqualToString:@"/"] || [character isEqualToString:@"-"] || [character isEqualToString:@" "] || [character isEqualToString:@""])
2103  return anIndex + range.length;
2104  }
2105 
2106  return CPNotFound;
2107 }
2108 
2109 @end
2110 
2111 var CPDateFormatterDateStyleKey = @"CPDateFormatterDateStyle",
2112  CPDateFormatterTimeStyleKey = @"CPDateFormatterTimeStyleKey",
2113  CPDateFormatterFormatterBehaviorKey = @"CPDateFormatterFormatterBehaviorKey",
2114  CPDateFormatterDoseRelativeDateFormattingKey = @"CPDateFormatterDoseRelativeDateFormattingKey",
2115  CPDateFormatterDateFormatKey = @"CPDateFormatterDateFormatKey",
2116  CPDateFormatterAllowNaturalLanguageKey = @"CPDateFormatterAllowNaturalLanguageKey",
2117  CPDateFormatterLocaleKey = @"CPDateFormatterLocaleKey";
2118 
2120 
2121 - (id)initWithCoder:(CPCoder)aCoder
2122 {
2123  self = [super initWithCoder:aCoder];
2124 
2125  if (self)
2126  {
2127  _allowNaturalLanguage = [aCoder decodeBoolForKey:CPDateFormatterAllowNaturalLanguageKey];
2128  _dateFormat = [aCoder decodeObjectForKey:CPDateFormatterDateFormatKey];
2129  _dateStyle = [aCoder decodeIntForKey:CPDateFormatterDateStyleKey];
2130  _doesRelativeDateFormatting = [aCoder decodeBoolForKey:CPDateFormatterDoseRelativeDateFormattingKey];
2131  _formatterBehavior = [aCoder decodeIntForKey:CPDateFormatterFormatterBehaviorKey];
2132  _locale = [aCoder decodeObjectForKey:CPDateFormatterLocaleKey];
2133  _timeStyle = [aCoder decodeIntForKey:CPDateFormatterTimeStyleKey];
2134  }
2135 
2136  [self _init];
2137 
2138  return self;
2139 }
2140 
2141 - (void)encodeWithCoder:(CPCoder)aCoder
2142 {
2143  [super encodeWithCoder:aCoder];
2144 
2145  [aCoder encodeBool:_allowNaturalLanguage forKey:CPDateFormatterAllowNaturalLanguageKey];
2146  [aCoder encodeInt:_dateStyle forKey:CPDateFormatterDateStyleKey];
2147  [aCoder encodeObject:_dateFormat forKey:CPDateFormatterDateFormatKey];
2148  [aCoder encodeBool:_doesRelativeDateFormatting forKey:CPDateFormatterDoseRelativeDateFormattingKey];
2149  [aCoder encodeInt:_formatterBehavior forKey:CPDateFormatterFormatterBehaviorKey];
2150  [aCoder encodeInt:_locale forKey:CPDateFormatterLocaleKey];
2151  [aCoder encodeInt:_timeStyle forKey:CPDateFormatterTimeStyleKey];
2152 }
2153 
2154 @end
2155 
2156 
2157 @implementation CPDate (CPTimeZone)
2158 
2161 - (void)_dateWithTimeZone:(CPTimeZone)aTimeZone
2162 {
2163  if (!aTimeZone)
2164  return;
2165 
2166  self.setSeconds(self.getSeconds() - [aTimeZone secondsFromGMTForDate:self]);
2167  self.setSeconds(self.getSeconds() + [aTimeZone secondsFromGMT]);
2168 }
2169 
2170 @end
2171 
2173 
2178 {
2179  return _allowNaturalLanguage;
2180 }
2181 
2186 {
2187  return _doesRelativeDateFormatting;
2188 }
2189 
2193 - (void)setDoesRelativeDateFormatting:(BOOL)aValue
2194 {
2195  _doesRelativeDateFormatting = aValue;
2196 }
2197 
2202 {
2203  return _defaultDate;
2204 }
2205 
2209 - (void)setDefaultDate:(CPDate)aValue
2210 {
2211  _defaultDate = aValue;
2212 }
2213 
2218 {
2219  return _twoDigitStartDate;
2220 }
2221 
2225 - (void)setTwoDigitStartDate:(CPDate)aValue
2226 {
2227  _twoDigitStartDate = aValue;
2228 }
2229 
2233 - (CPDateFormatterBehavior)formatterBehavior
2234 {
2235  return _formatterBehavior;
2236 }
2237 
2241 - (void)setFormatterBehavior:(CPDateFormatterBehavior)aValue
2242 {
2243  _formatterBehavior = aValue;
2244 }
2245 
2249 - (CPDateFormatterStyle)dateStyle
2250 {
2251  return _dateStyle;
2252 }
2253 
2257 - (void)setDateStyle:(CPDateFormatterStyle)aValue
2258 {
2259  _dateStyle = aValue;
2260 }
2261 
2265 - (CPDateFormatterStyle)timeStyle
2266 {
2267  return _timeStyle;
2268 }
2269 
2273 - (void)setTimeStyle:(CPDateFormatterStyle)aValue
2274 {
2275  _timeStyle = aValue;
2276 }
2277 
2281 - (CPLocale)locale
2282 {
2283  return _locale;
2284 }
2285 
2289 - (void)setLocale:(CPLocale)aValue
2290 {
2291  _locale = aValue;
2292 }
2293 
2298 {
2299  return _AMSymbol;
2300 }
2301 
2305 - (void)setAMSymbol:(CPString)aValue
2306 {
2307  _AMSymbol = aValue;
2308 }
2309 
2314 {
2315  return _dateFormat;
2316 }
2317 
2321 - (void)setDateFormat:(CPString)aValue
2322 {
2323  _dateFormat = aValue;
2324 }
2325 
2330 {
2331  return _PMSymbol;
2332 }
2333 
2337 - (void)setPMSymbol:(CPString)aValue
2338 {
2339  _PMSymbol = aValue;
2340 }
2341 
2346 {
2347  return _timeZone;
2348 }
2349 
2353 - (void)setTimeZone:(CPTimeZone)aValue
2354 {
2355  _timeZone = aValue;
2356 }
2357 
2358 @end
var CPDateFormatterLocaleKey
var CPDateFormatterDoseRelativeDateFormattingKey
CPArray shortWeekdaySymbols()
CPArray quarterSymbols()
var patternStringTokens
id currentLocale()
Definition: CPLocale.j:86
A representation of a single point in time.
Definition: CPDate.h:2
var defaultDateFormatterBehavior
var CPDateFormatterDateStyleKey
CPLocaleCountryCode
Definition: CPLocale.j:26
CPTimeZone timeZone()
var CPDateFormatterTimeStyleKey
CPString substringWithRange:(CPRange aRange)
Definition: CPString.j:291
CPDictionary symbolsForLanguageCode:(CPString languageCode)
CPString stringFromDate:(CPDate aDate)
CPArray shortMonthSymbols()
CPDateFormatterBehavior10_4
void setSymbol:forKey:languageCode:(CPString aSymbol, [forKey] CPString aKey, [languageCode] CPString languageCode)
A mutable key-value pair collection.
Definition: CPDictionary.h:2
CPLocaleLanguageCode
Definition: CPLocale.j:25
CPArray veryShortMonthSymbols()
CPInteger secondsFromGMT()
Definition: CPTimeZone.j:578
CPDate dateFromString:(CPString aString)
CPDateFormatterShortStyle
An immutable string (collection of characters).
Definition: CPString.h:2
CPTimeZone systemTimeZone()
Definition: CPTimeZone.j:436
CPDateFormatterMediumStyle
id initWithCoder:(CPCoder aCoder)
Definition: CPFormatter.j:167
global CPLocaleLanguageCode global CPLocaleCountryCode typedef CPDateFormatterStyle CPDateFormatterNoStyle
var CPDateFormatterDateFormatKey
id copy()
Definition: CPDate.j:222
CPFormatter is an abstract class that declares an interface for objects that create, interpret, and validate the textual representation of cell contents. The Foundation framework provides two concrete subclasses of CPFormatter to generate these objects: CPNumberFormatter and CPDateFormatter.
Definition: CPFormatter.h:2
CPArray shortStandaloneQuarterSymbols()
CPDateFormatterLongStyle
CPArray shortQuarterSymbols()
int length()
Definition: CPString.j:186
CPTimeZone is a class to define the behvior of time zone object (like CPDatePicker) ...
Definition: CPTimeZone.h:2
CPString localizedName:locale:(NSTimeZoneNameStyle style, [locale] CPLocale locale)
Definition: CPTimeZone.j:618
CPArray veryShortStandaloneMonthSymbols()
id symbolForKey:languageCode:(CPString aKey, [languageCode] CPString languageCode)
var relativeDateFormating
id initWithTimeIntervalSinceReferenceDate:(CPTimeInterval seconds)
Definition: CPDate.j:90
CPArray veryShortWeekdaySymbols()
void setSymbols:forLanguageCode:(CPDictionary symbols, [forLanguageCode] CPString languageCode)
CPArray standaloneQuarterSymbols()
CPArray standaloneMonthSymbols()
Defines methods for use when archiving & restoring (enc/decoding).
Definition: CPCoder.h:2
CPDateFormatterBehavior CPDateFormatterBehaviorDefault
var CPDateFormatterAllowNaturalLanguageKey
CPNotFound
Definition: CPObjJRuntime.j:62
CPArray shortStandaloneWeekdaySymbols()
id alloc()
Definition: CPDate.j:35
CPDateFormatterFullStyle
CPString stringForObjectValue:(id anObject)
id new()
Definition: CPObject.j:122
CPDateFormatterBehavior formatterBehavior()
id date()
Definition: CPDate.j:42
CPString characterAtIndex:(CPUInteger anIndex)
Definition: CPString.j:195
var CPDateFormatterFormatterBehaviorKey
CPArray standaloneWeekdaySymbols()
CPArray veryShortStandaloneWeekdaySymbols()
void encodeWithCoder:(CPCoder aCoder)
Definition: CPFormatter.j:172
CPDateFormatterBehavior defaultFormatterBehavior()
CPRange rangeOfString:(CPString aString)
Definition: CPString.j:322
CPDateFormatterBehavior10_0
CPArray weekdaySymbols()
id alloc()
Definition: CPObject.j:130
id stringWithFormat:(CPString format, [,] ...)
Definition: CPString.j:166
CPArray shortStandaloneMonthSymbols()