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