comparison tango/tango/text/locale/Core.d @ 132:1700239cab2e trunk

[svn r136] MAJOR UNSTABLE UPDATE!!! Initial commit after moving to Tango instead of Phobos. Lots of bugfixes... This build is not suitable for most things.
author lindquist
date Fri, 11 Jan 2008 17:57:40 +0100
parents
children
comparison
equal deleted inserted replaced
131:5825d48b27d1 132:1700239cab2e
1 /*******************************************************************************
2
3 copyright: Copyright (c) 2005 John Chapman. All rights reserved
4
5 license: BSD style: $(LICENSE)
6
7 version: Initial release: 2005
8
9 author: John Chapman
10
11 Contains classes that provide information about locales, such as
12 the language and calendars, as well as cultural conventions used
13 for formatting dates, currency and numbers. Use these classes when
14 writing applications for an international audience.
15
16 ******************************************************************************/
17
18 /**
19 * $(MEMBERTABLE
20 * $(TR
21 * $(TH Interface)
22 * $(TH Description)
23 * )
24 * $(TR
25 * $(TD $(LINK2 #IFormatService, IFormatService))
26 * $(TD Retrieves an object to control formatting.)
27 * )
28 * )
29 *
30 * $(MEMBERTABLE
31 * $(TR
32 * $(TH Class)
33 * $(TH Description)
34 * )
35 * $(TR
36 * $(TD $(LINK2 #Calendar, Calendar))
37 * $(TD Represents time in week, month and year divisions.)
38 * )
39 * $(TR
40 * $(TD $(LINK2 #Culture, Culture))
41 * $(TD Provides information about a culture, such as its name, calendar and date and number format patterns.)
42 * )
43 * $(TR
44 * $(TD $(LINK2 #DateTimeFormat, DateTimeFormat))
45 * $(TD Determines how $(LINK2 #Time, Time) values are formatted, depending on the culture.)
46 * )
47 * $(TR
48 * $(TD $(LINK2 #DaylightSavingTime, DaylightSavingTime))
49 * $(TD Represents a period of daylight-saving time.)
50 * )
51 * $(TR
52 * $(TD $(LINK2 #Gregorian, Gregorian))
53 * $(TD Represents the Gregorian calendar.)
54 * )
55 * $(TR
56 * $(TD $(LINK2 #Hebrew, Hebrew))
57 * $(TD Represents the Hebrew calendar.)
58 * )
59 * $(TR
60 * $(TD $(LINK2 #Hijri, Hijri))
61 * $(TD Represents the Hijri calendar.)
62 * )
63 * $(TR
64 * $(TD $(LINK2 #Japanese, Japanese))
65 * $(TD Represents the Japanese calendar.)
66 * )
67 * $(TR
68 * $(TD $(LINK2 #Korean, Korean))
69 * $(TD Represents the Korean calendar.)
70 * )
71 * $(TR
72 * $(TD $(LINK2 #NumberFormat, NumberFormat))
73 * $(TD Determines how numbers are formatted, according to the current culture.)
74 * )
75 * $(TR
76 * $(TD $(LINK2 #Region, Region))
77 * $(TD Provides information about a region.)
78 * )
79 * $(TR
80 * $(TD $(LINK2 #Taiwan, Taiwan))
81 * $(TD Represents the Taiwan calendar.)
82 * )
83 * $(TR
84 * $(TD $(LINK2 #ThaiBuddhist, ThaiBuddhist))
85 * $(TD Represents the Thai Buddhist calendar.)
86 * )
87 * )
88 *
89 * $(MEMBERTABLE
90 * $(TR
91 * $(TH Struct)
92 * $(TH Description)
93 * )
94 * $(TR
95 * $(TD $(LINK2 #Time, Time))
96 * $(TD Represents time expressed as a date and time of day.)
97 * )
98 * $(TR
99 * $(TD $(LINK2 #TimeSpan, TimeSpan))
100 * $(TD Represents a time interval.)
101 * )
102 * )
103 */
104
105 module tango.text.locale.Core;
106
107 private import tango.core.Exception;
108
109 private import tango.text.locale.Data;
110
111 private import tango.time.Time;
112
113 private import tango.time.chrono.Hijri,
114 tango.time.chrono.Korean,
115 tango.time.chrono.Taiwan,
116 tango.time.chrono.Hebrew,
117 tango.time.chrono.Calendar,
118 tango.time.chrono.Japanese,
119 tango.time.chrono.Gregorian,
120 tango.time.chrono.ThaiBuddhist;
121
122 version (Windows)
123 private import tango.text.locale.Win32;
124
125 version (Posix)
126 private import tango.text.locale.Posix;
127
128
129 // Initializes an array.
130 private template arrayOf(T) {
131 private T[] arrayOf(T[] params ...) {
132 return params.dup;
133 }
134 }
135
136
137 /**
138 * Defines the types of cultures that can be retrieved from Culture.getCultures.
139 */
140 public enum CultureTypes {
141 Neutral = 1, /// Refers to cultures that are associated with a language but not specific to a country or region.
142 Specific = 2, /// Refers to cultures that are specific to a country or region.
143 All = Neutral | Specific /// Refers to all cultures.
144 }
145
146
147 /**
148 * $(ANCHOR _IFormatService)
149 * Retrieves an object to control formatting.
150 *
151 * A class implements $(LINK2 #IFormatService_getFormat, getFormat) to retrieve an object that provides format information for the implementing type.
152 * Remarks: IFormatService is implemented by $(LINK2 #Culture, Culture), $(LINK2 #NumberFormat, NumberFormat) and $(LINK2 #DateTimeFormat, DateTimeFormat) to provide locale-specific formatting of
153 * numbers and date and time values.
154 */
155 public interface IFormatService {
156
157 /**
158 * $(ANCHOR IFormatService_getFormat)
159 * Retrieves an object that supports formatting for the specified _type.
160 * Returns: The current instance if type is the same _type as the current instance; otherwise, null.
161 * Params: type = An object that specifies the _type of formatting to retrieve.
162 */
163 Object getFormat(TypeInfo type);
164
165 }
166
167 /**
168 * $(ANCHOR _Culture)
169 * Provides information about a culture, such as its name, calendar and date and number format patterns.
170 * Remarks: tango.text.locale adopts the RFC 1766 standard for culture names in the format <language>"-"<region>.
171 * <language> is a lower-case two-letter code defined by ISO 639-1. <region> is an upper-case
172 * two-letter code defined by ISO 3166. For example, "en-GB" is UK English.
173 * $(BR)$(BR)There are three types of culture: invariant, neutral and specific. The invariant culture is not tied to
174 * any specific region, although it is associated with the English language. A neutral culture is associated with
175 * a language, but not with a region. A specific culture is associated with a language and a region. "es" is a neutral
176 * culture. "es-MX" is a specific culture.
177 * $(BR)$(BR)Instances of $(LINK2 #DateTimeFormat, DateTimeFormat) and $(LINK2 #NumberFormat, NumberFormat) cannot be created for neutral cultures.
178 * Examples:
179 * ---
180 * import tango.io.Stdout, tango.text.locale.Core;
181 *
182 * void main() {
183 * Culture culture = new Culture("it-IT");
184 *
185 * Stdout.formatln("englishName: {}", culture.englishName);
186 * Stdout.formatln("nativeName: {}", culture.nativeName);
187 * Stdout.formatln("name: {}", culture.name);
188 * Stdout.formatln("parent: {}", culture.parent.name);
189 * Stdout.formatln("isNeutral: {}", culture.isNeutral);
190 * }
191 *
192 * // Produces the following output:
193 * // englishName: Italian (Italy)
194 * // nativeName: italiano (Italia)
195 * // name: it-IT
196 * // parent: it
197 * // isNeutral: false
198 * ---
199 */
200 public class Culture : IFormatService {
201
202 private const int LCID_INVARIANT = 0x007F;
203
204 private static Culture[char[]] namedCultures;
205 private static Culture[int] idCultures;
206 private static Culture[char[]] ietfCultures;
207
208 private static Culture currentCulture_;
209 private static Culture userDefaultCulture_; // The user's default culture (GetUserDefaultLCID).
210 private static Culture invariantCulture_; // The invariant culture is associated with the English language.
211 private Calendar calendar_;
212 private Culture parent_;
213 private CultureData* cultureData_;
214 private bool isReadOnly_;
215 private NumberFormat numberFormat_;
216 private DateTimeFormat dateTimeFormat_;
217
218 static this() {
219 invariantCulture_ = new Culture(LCID_INVARIANT);
220 invariantCulture_.isReadOnly_ = true;
221
222 userDefaultCulture_ = new Culture(nativeMethods.getUserCulture());
223 if (userDefaultCulture_ is null)
224 // Fallback
225 userDefaultCulture_ = invariantCulture;
226 else
227 userDefaultCulture_.isReadOnly_ = true;
228 }
229
230 static ~this() {
231 namedCultures = null;
232 idCultures = null;
233 ietfCultures = null;
234 }
235
236 /**
237 * Initializes a new Culture instance from the supplied name.
238 * Params: cultureName = The name of the Culture.
239 */
240 public this(char[] cultureName) {
241 cultureData_ = CultureData.getDataFromCultureName(cultureName);
242 }
243
244 /**
245 * Initializes a new Culture instance from the supplied culture identifier.
246 * Params: cultureID = The identifer (LCID) of the Culture.
247 * Remarks: Culture identifiers correspond to a Windows LCID.
248 */
249 public this(int cultureID) {
250 cultureData_ = CultureData.getDataFromCultureID(cultureID);
251 }
252
253 /**
254 * Retrieves an object defining how to format the specified type.
255 * Params: type = The TypeInfo of the resulting formatting object.
256 * Returns: If type is typeid($(LINK2 #NumberFormat, NumberFormat)), the value of the $(LINK2 #Culture_numberFormat, numberFormat) property. If type is typeid($(LINK2 #DateTimeFormat, DateTimeFormat)), the
257 * value of the $(LINK2 #Culture_dateTimeFormat, dateTimeFormat) property. Otherwise, null.
258 * Remarks: Implements $(LINK2 #IFormatService_getFormat, IFormatService.getFormat).
259 */
260 public Object getFormat(TypeInfo type) {
261 if (type is typeid(NumberFormat))
262 return numberFormat;
263 else if (type is typeid(DateTimeFormat))
264 return dateTimeFormat;
265 return null;
266 }
267
268 version (Clone)
269 {
270 /**
271 * Copies the current Culture instance.
272 * Returns: A copy of the current Culture instance.
273 * Remarks: The values of the $(LINK2 #Culture_numberFormat, numberFormat), $(LINK2 #Culture_dateTimeFormat, dateTimeFormat) and $(LINK2 #Culture_calendar, calendar) properties are copied also.
274 */
275 public Object clone() {
276 Culture culture = cast(Culture)cloneObject(this);
277 if (!culture.isNeutral) {
278 if (dateTimeFormat_ !is null)
279 culture.dateTimeFormat_ = cast(DateTimeFormat)dateTimeFormat_.clone();
280 if (numberFormat_ !is null)
281 culture.numberFormat_ = cast(NumberFormat)numberFormat_.clone();
282 }
283 if (calendar_ !is null)
284 culture.calendar_ = cast(Calendar)calendar_.clone();
285 return culture;
286 }
287 }
288
289 /**
290 * Returns a read-only instance of a culture using the specified culture identifier.
291 * Params: cultureID = The identifier of the culture.
292 * Returns: A read-only culture instance.
293 * Remarks: Instances returned by this method are cached.
294 */
295 public static Culture getCulture(int cultureID) {
296 Culture culture = getCultureInternal(cultureID, null);
297 if (culture is null)
298 error("Culture is not supported.");
299 return culture;
300 }
301
302 /**
303 * Returns a read-only instance of a culture using the specified culture name.
304 * Params: cultureName = The name of the culture.
305 * Returns: A read-only culture instance.
306 * Remarks: Instances returned by this method are cached.
307 */
308 public static Culture getCulture(char[] cultureName) {
309 if (cultureName == null)
310 error("Value cannot be null.");
311 Culture culture = getCultureInternal(0, cultureName);
312 if (culture is null)
313 error("Culture name " ~ cultureName ~ " is not supported.");
314 return culture;
315 }
316
317 /**
318 * Returns a read-only instance using the specified name, as defined by the RFC 3066 standard and maintained by the IETF.
319 * Params: name = The name of the language.
320 * Returns: A read-only culture instance.
321 */
322 public static Culture getCultureFromIetfLanguageTag(char[] name) {
323 if (name == null)
324 error("Value cannot be null.");
325 Culture culture = getCultureInternal(-1, name);
326 if (culture is null)
327 error("Culture IETF name " ~ name ~ " is not a known IETF name.");
328 return culture;
329 }
330
331 private static Culture getCultureInternal(int cultureID, char[] name) {
332 // If cultureID is - 1, name is an IETF name; if it's 0, name is a culture name; otherwise, it's a valid LCID.
333
334 // Look up tables first.
335 if (cultureID == 0) {
336 if (Culture* culture = name in namedCultures)
337 return *culture;
338 }
339 else if (cultureID > 0) {
340 if (Culture* culture = cultureID in idCultures)
341 return *culture;
342 }
343 else if (cultureID == -1) {
344 if (Culture* culture = name in ietfCultures)
345 return *culture;
346 }
347
348 // Nothing found, create a new instance.
349 Culture culture;
350
351 try {
352 if (cultureID == -1) {
353 name = CultureData.getCultureNameFromIetfName(name);
354 if (name == null)
355 return null;
356 }
357 else if (cultureID == 0)
358 culture = new Culture(name);
359 else if (userDefaultCulture_ !is null && userDefaultCulture_.id == cultureID) {
360 culture = userDefaultCulture_;
361 }
362 else
363 culture = new Culture(cultureID);
364 }
365 catch (LocaleException) {
366 return null;
367 }
368
369 culture.isReadOnly_ = true;
370
371 // Now cache the new instance in all tables.
372 ietfCultures[culture.ietfLanguageTag] = culture;
373 namedCultures[culture.name] = culture;
374 idCultures[culture.id] = culture;
375
376 return culture;
377 }
378
379 /**
380 * Returns a list of cultures filtered by the specified $(LINK2 constants.html#CultureTypes, CultureTypes).
381 * Params: types = A combination of CultureTypes.
382 * Returns: An array of Culture instances containing cultures specified by types.
383 */
384 public static Culture[] getCultures(CultureTypes types) {
385 bool includeSpecific = (types & CultureTypes.Specific) != 0;
386 bool includeNeutral = (types & CultureTypes.Neutral) != 0;
387
388 int[] cultures;
389 for (int i = 0; i < CultureData.cultureDataTable.length; i++) {
390 if ((CultureData.cultureDataTable[i].isNeutral && includeNeutral) || (!CultureData.cultureDataTable[i].isNeutral && includeSpecific))
391 cultures ~= CultureData.cultureDataTable[i].lcid;
392 }
393
394 Culture[] result = new Culture[cultures.length];
395 foreach (int i, int cultureID; cultures)
396 result[i] = new Culture(cultureID);
397 return result;
398 }
399
400 /**
401 * Returns the name of the Culture.
402 * Returns: A string containing the name of the Culture in the format &lt;language&gt;"-"&lt;region&gt;.
403 */
404 public override char[] toString() {
405 return cultureData_.name;
406 }
407
408 public override int opEquals(Object obj) {
409 if (obj is this)
410 return true;
411 Culture other = cast(Culture)obj;
412 if (other is null)
413 return false;
414 return other.name == name; // This needs to be changed so it's culturally aware.
415 }
416
417 /**
418 * $(ANCHOR Culture_current)
419 * $(I Property.) Retrieves the culture of the current user.
420 * Returns: The Culture instance representing the user's current culture.
421 */
422 public static Culture current() {
423 if (currentCulture_ !is null)
424 return currentCulture_;
425
426 if (userDefaultCulture_ !is null) {
427 // If the user has changed their locale settings since last we checked, invalidate our data.
428 if (userDefaultCulture_.id != nativeMethods.getUserCulture())
429 userDefaultCulture_ = null;
430 }
431 if (userDefaultCulture_ is null) {
432 userDefaultCulture_ = new Culture(nativeMethods.getUserCulture());
433 if (userDefaultCulture_ is null)
434 userDefaultCulture_ = invariantCulture;
435 else
436 userDefaultCulture_.isReadOnly_ = true;
437 }
438
439 return userDefaultCulture_;
440 }
441 /**
442 * $(I Property.) Assigns the culture of the _current user.
443 * Params: value = The Culture instance representing the user's _current culture.
444 * Examples:
445 * The following examples shows how to change the _current culture.
446 * ---
447 * import tango.io.Print, tango.text.locale.Common;
448 *
449 * void main() {
450 * // Displays the name of the current culture.
451 * Println("The current culture is %s.", Culture.current.englishName);
452 *
453 * // Changes the current culture to el-GR.
454 * Culture.current = new Culture("el-GR");
455 * Println("The current culture is now %s.", Culture.current.englishName);
456 * }
457 *
458 * // Produces the following output:
459 * // The current culture is English (United Kingdom).
460 * // The current culture is now Greek (Greece).
461 * ---
462 */
463 public static void current(Culture value) {
464 checkNeutral(value);
465 nativeMethods.setUserCulture(value.id);
466 currentCulture_ = value;
467 }
468
469 /**
470 * $(I Property.) Retrieves the invariant Culture.
471 * Returns: The Culture instance that is invariant.
472 * Remarks: The invariant culture is culture-independent. It is not tied to any specific region, but is associated
473 * with the English language.
474 */
475 public static Culture invariantCulture() {
476 return invariantCulture_;
477 }
478
479 /**
480 * $(I Property.) Retrieves the identifier of the Culture.
481 * Returns: The culture identifier of the current instance.
482 * Remarks: The culture identifier corresponds to the Windows locale identifier (LCID). It can therefore be used when
483 * interfacing with the Windows NLS functions.
484 */
485 public int id() {
486 return cultureData_.lcid;
487 }
488
489 /**
490 * $(ANCHOR Culture_name)
491 * $(I Property.) Retrieves the name of the Culture in the format &lt;language&gt;"-"&lt;region&gt;.
492 * Returns: The name of the current instance. For example, the name of the UK English culture is "en-GB".
493 */
494 public char[] name() {
495 return cultureData_.name;
496 }
497
498 /**
499 * $(I Property.) Retrieves the name of the Culture in the format &lt;languagename&gt; (&lt;regionname&gt;) in English.
500 * Returns: The name of the current instance in English. For example, the englishName of the UK English culture
501 * is "English (United Kingdom)".
502 */
503 public char[] englishName() {
504 return cultureData_.englishName;
505 }
506
507 /**
508 * $(I Property.) Retrieves the name of the Culture in the format &lt;languagename&gt; (&lt;regionname&gt;) in its native language.
509 * Returns: The name of the current instance in its native language. For example, if Culture.name is "de-DE", nativeName is
510 * "Deutsch (Deutschland)".
511 */
512 public char[] nativeName() {
513 return cultureData_.nativeName;
514 }
515
516 /**
517 * $(I Property.) Retrieves the two-letter language code of the culture.
518 * Returns: The two-letter language code of the Culture instance. For example, the twoLetterLanguageName for English is "en".
519 */
520 public char[] twoLetterLanguageName() {
521 return cultureData_.isoLangName;
522 }
523
524 /**
525 * $(I Property.) Retrieves the three-letter language code of the culture.
526 * Returns: The three-letter language code of the Culture instance. For example, the threeLetterLanguageName for English is "eng".
527 */
528 public char[] threeLetterLanguageName() {
529 return cultureData_.isoLangName2;
530 }
531
532 /**
533 * $(I Property.) Retrieves the RFC 3066 identification for a language.
534 * Returns: A string representing the RFC 3066 language identification.
535 */
536 public final char[] ietfLanguageTag() {
537 return cultureData_.ietfTag;
538 }
539
540 /**
541 * $(I Property.) Retrieves the Culture representing the parent of the current instance.
542 * Returns: The Culture representing the parent of the current instance.
543 */
544 public Culture parent() {
545 if (parent_ is null) {
546 try {
547 int parentCulture = cultureData_.parent;
548 if (parentCulture == LCID_INVARIANT)
549 parent_ = invariantCulture;
550 else
551 parent_ = new Culture(parentCulture);
552 }
553 catch {
554 parent_ = invariantCulture;
555 }
556 }
557 return parent_;
558 }
559
560 /**
561 * $(I Property.) Retrieves a value indicating whether the current instance is a neutral culture.
562 * Returns: true is the current Culture represents a neutral culture; otherwise, false.
563 * Examples:
564 * The following example displays which cultures using Chinese are neutral.
565 * ---
566 * import tango.io.Print, tango.text.locale.Common;
567 *
568 * void main() {
569 * foreach (c; Culture.getCultures(CultureTypes.All)) {
570 * if (c.twoLetterLanguageName == "zh") {
571 * Print(c.englishName);
572 * if (c.isNeutral)
573 * Println("neutral");
574 * else
575 * Println("specific");
576 * }
577 * }
578 * }
579 *
580 * // Produces the following output:
581 * // Chinese (Simplified) - neutral
582 * // Chinese (Taiwan) - specific
583 * // Chinese (People's Republic of China) - specific
584 * // Chinese (Hong Kong S.A.R.) - specific
585 * // Chinese (Singapore) - specific
586 * // Chinese (Macao S.A.R.) - specific
587 * // Chinese (Traditional) - neutral
588 * ---
589 */
590 public bool isNeutral() {
591 return cultureData_.isNeutral;
592 }
593
594 /**
595 * $(I Property.) Retrieves a value indicating whether the instance is read-only.
596 * Returns: true if the instance is read-only; otherwise, false.
597 * Remarks: If the culture is read-only, the $(LINK2 #Culture_dateTimeFormat, dateTimeFormat) and $(LINK2 #Culture_numberFormat, numberFormat) properties return
598 * read-only instances.
599 */
600 public final bool isReadOnly() {
601 return isReadOnly_;
602 }
603
604 /**
605 * $(ANCHOR Culture_calendar)
606 * $(I Property.) Retrieves the calendar used by the culture.
607 * Returns: A Calendar instance respresenting the calendar used by the culture.
608 */
609 public Calendar calendar() {
610 if (calendar_ is null) {
611 calendar_ = getCalendarInstance(cultureData_.calendarType, isReadOnly_);
612 }
613 return calendar_;
614 }
615
616 /**
617 * $(I Property.) Retrieves the list of calendars that can be used by the culture.
618 * Returns: An array of type Calendar representing the calendars that can be used by the culture.
619 */
620 public Calendar[] optionalCalendars() {
621 Calendar[] cals = new Calendar[cultureData_.optionalCalendars.length];
622 foreach (int i, int calID; cultureData_.optionalCalendars)
623 cals[i] = getCalendarInstance(calID);
624 return cals;
625 }
626
627 /**
628 * $(ANCHOR Culture_numberFormat)
629 * $(I Property.) Retrieves a NumberFormat defining the culturally appropriate format for displaying numbers and currency.
630 * Returns: A NumberFormat defining the culturally appropriate format for displaying numbers and currency.
631 */
632 public NumberFormat numberFormat() {
633 checkNeutral(this);
634 if (numberFormat_ is null) {
635 numberFormat_ = new NumberFormat(cultureData_);
636 numberFormat_.isReadOnly_ = isReadOnly_;
637 }
638 return numberFormat_;
639 }
640 /**
641 * $(I Property.) Assigns a NumberFormat defining the culturally appropriate format for displaying numbers and currency.
642 * Params: values = A NumberFormat defining the culturally appropriate format for displaying numbers and currency.
643 */
644 public void numberFormat(NumberFormat value) {
645 checkReadOnly();
646 numberFormat_ = value;
647 }
648
649 /**
650 * $(ANCHOR Culture_dateTimeFormat)
651 * $(I Property.) Retrieves a DateTimeFormat defining the culturally appropriate format for displaying dates and times.
652 * Returns: A DateTimeFormat defining the culturally appropriate format for displaying dates and times.
653 */
654 public DateTimeFormat dateTimeFormat() {
655 checkNeutral(this);
656 if (dateTimeFormat_ is null) {
657 dateTimeFormat_ = new DateTimeFormat(cultureData_, calendar);
658 dateTimeFormat_.isReadOnly_ = isReadOnly_;
659 }
660 return dateTimeFormat_;
661 }
662 /**
663 * $(I Property.) Assigns a DateTimeFormat defining the culturally appropriate format for displaying dates and times.
664 * Params: values = A DateTimeFormat defining the culturally appropriate format for displaying dates and times.
665 */
666 public void dateTimeFormat(DateTimeFormat value) {
667 checkReadOnly();
668 dateTimeFormat_ = value;
669 }
670
671 private static void checkNeutral(Culture culture) {
672 if (culture.isNeutral)
673 error("Culture '" ~ culture.name ~ "' is a neutral culture. It cannot be used in formatting and therefore cannot be set as the current culture.");
674 }
675
676 private void checkReadOnly() {
677 if (isReadOnly_)
678 error("Instance is read-only.");
679 }
680
681 private static Calendar getCalendarInstance(int calendarType, bool readOnly=false) {
682 switch (calendarType) {
683 case Calendar.JAPAN:
684 return new Japanese();
685 case Calendar.TAIWAN:
686 return new Taiwan();
687 case Calendar.KOREA:
688 return new Korean();
689 case Calendar.HIJRI:
690 return new Hijri();
691 case Calendar.THAI:
692 return new ThaiBuddhist();
693 case Calendar.HEBREW:
694 return new Hebrew;
695 case Calendar.GREGORIAN_US:
696 case Calendar.GREGORIAN_ME_FRENCH:
697 case Calendar.GREGORIAN_ARABIC:
698 case Calendar.GREGORIAN_XLIT_ENGLISH:
699 case Calendar.GREGORIAN_XLIT_FRENCH:
700 return new Gregorian(cast(Gregorian.Type) calendarType);
701 default:
702 break;
703 }
704 return new Gregorian();
705 }
706
707 }
708
709 /**
710 * $(ANCHOR _Region)
711 * Provides information about a region.
712 * Remarks: Region does not represent user preferences. It does not depend on the user's language or culture.
713 * Examples:
714 * The following example displays some of the properties of the Region class:
715 * ---
716 * import tango.io.Print, tango.text.locale.Common;
717 *
718 * void main() {
719 * Region region = new Region("en-GB");
720 * Println("name: %s", region.name);
721 * Println("englishName: %s", region.englishName);
722 * Println("isMetric: %s", region.isMetric);
723 * Println("currencySymbol: %s", region.currencySymbol);
724 * Println("isoCurrencySymbol: %s", region.isoCurrencySymbol);
725 * }
726 *
727 * // Produces the following output.
728 * // name: en-GB
729 * // englishName: United Kingdom
730 * // isMetric: true
731 * // currencySymbol: £
732 * // isoCurrencySymbol: GBP
733 * ---
734 */
735 public class Region {
736
737 private CultureData* cultureData_;
738 private static Region currentRegion_;
739 private char[] name_;
740
741 /**
742 * Initializes a new Region instance based on the region associated with the specified culture identifier.
743 * Params: cultureID = A culture indentifier.
744 * Remarks: The name of the Region instance is set to the ISO 3166 two-letter code for that region.
745 */
746 public this(int cultureID) {
747 cultureData_ = CultureData.getDataFromCultureID(cultureID);
748 if (cultureData_.isNeutral)
749 error ("Cannot use a neutral culture to create a region.");
750 name_ = cultureData_.regionName;
751 }
752
753 /**
754 * $(ANCHOR Region_ctor_name)
755 * Initializes a new Region instance based on the region specified by name.
756 * Params: name = A two-letter ISO 3166 code for the region. Or, a culture $(LINK2 #Culture_name, _name) consisting of the language and region.
757 */
758 public this(char[] name) {
759 cultureData_ = CultureData.getDataFromRegionName(name);
760 name_ = name;
761 if (cultureData_.isNeutral)
762 error ("The region name " ~ name ~ " corresponds to a neutral culture and cannot be used to create a region.");
763 }
764
765 package this(CultureData* cultureData) {
766 cultureData_ = cultureData;
767 name_ = cultureData.regionName;
768 }
769
770 /**
771 * $(I Property.) Retrieves the Region used by the current $(LINK2 #Culture, Culture).
772 * Returns: The Region instance associated with the current Culture.
773 */
774 public static Region current() {
775 if (currentRegion_ is null)
776 currentRegion_ = new Region(Culture.current.cultureData_);
777 return currentRegion_;
778 }
779
780 /**
781 * $(I Property.) Retrieves a unique identifier for the geographical location of the region.
782 * Returns: An $(B int) uniquely identifying the geographical location.
783 */
784 public int geoID() {
785 return cultureData_.geoId;
786 }
787
788 /**
789 * $(ANCHOR Region_name)
790 * $(I Property.) Retrieves the ISO 3166 code, or the name, of the current Region.
791 * Returns: The value specified by the name parameter of the $(LINK2 #Region_ctor_name, Region(char[])) constructor.
792 */
793 public char[] name() {
794 return name_;
795 }
796
797 /**
798 * $(I Property.) Retrieves the full name of the region in English.
799 * Returns: The full name of the region in English.
800 */
801 public char[] englishName() {
802 return cultureData_.englishCountry;
803 }
804
805 /**
806 * $(I Property.) Retrieves the full name of the region in its native language.
807 * Returns: The full name of the region in the language associated with the region code.
808 */
809 public char[] nativeName() {
810 return cultureData_.nativeCountry;
811 }
812
813 /**
814 * $(I Property.) Retrieves the two-letter ISO 3166 code of the region.
815 * Returns: The two-letter ISO 3166 code of the region.
816 */
817 public char[] twoLetterRegionName() {
818 return cultureData_.regionName;
819 }
820
821 /**
822 * $(I Property.) Retrieves the three-letter ISO 3166 code of the region.
823 * Returns: The three-letter ISO 3166 code of the region.
824 */
825 public char[] threeLetterRegionName() {
826 return cultureData_.isoRegionName;
827 }
828
829 /**
830 * $(I Property.) Retrieves the currency symbol of the region.
831 * Returns: The currency symbol of the region.
832 */
833 public char[] currencySymbol() {
834 return cultureData_.currency;
835 }
836
837 /**
838 * $(I Property.) Retrieves the three-character currency symbol of the region.
839 * Returns: The three-character currency symbol of the region.
840 */
841 public char[] isoCurrencySymbol() {
842 return cultureData_.intlSymbol;
843 }
844
845 /**
846 * $(I Property.) Retrieves the name in English of the currency used in the region.
847 * Returns: The name in English of the currency used in the region.
848 */
849 public char[] currencyEnglishName() {
850 return cultureData_.englishCurrency;
851 }
852
853 /**
854 * $(I Property.) Retrieves the name in the native language of the region of the currency used in the region.
855 * Returns: The name in the native language of the region of the currency used in the region.
856 */
857 public char[] currencyNativeName() {
858 return cultureData_.nativeCurrency;
859 }
860
861 /**
862 * $(I Property.) Retrieves a value indicating whether the region uses the metric system for measurements.
863 * Returns: true is the region uses the metric system; otherwise, false.
864 */
865 public bool isMetric() {
866 return cultureData_.isMetric;
867 }
868
869 /**
870 * Returns a string containing the ISO 3166 code, or the $(LINK2 #Region_name, name), of the current Region.
871 * Returns: A string containing the ISO 3166 code, or the name, of the current Region.
872 */
873 public override char[] toString() {
874 return name_;
875 }
876
877 }
878
879 /**
880 * $(ANCHOR _NumberFormat)
881 * Determines how numbers are formatted, according to the current culture.
882 * Remarks: Numbers are formatted using format patterns retrieved from a NumberFormat instance.
883 * This class implements $(LINK2 #IFormatService_getFormat, IFormatService.getFormat).
884 * Examples:
885 * The following example shows how to retrieve an instance of NumberFormat for a Culture
886 * and use it to display number formatting information.
887 * ---
888 * import tango.io.Print, tango.text.locale.Common;
889 *
890 * void main(char[][] args) {
891 * foreach (c; Culture.getCultures(CultureTypes.Specific)) {
892 * if (c.twoLetterLanguageName == "en") {
893 * NumberFormat fmt = c.numberFormat;
894 * Println("The currency symbol for %s is '%s'",
895 * c.englishName,
896 * fmt.currencySymbol);
897 * }
898 * }
899 * }
900 *
901 * // Produces the following output:
902 * // The currency symbol for English (United States) is '$'
903 * // The currency symbol for English (United Kingdom) is '£'
904 * // The currency symbol for English (Australia) is '$'
905 * // The currency symbol for English (Canada) is '$'
906 * // The currency symbol for English (New Zealand) is '$'
907 * // The currency symbol for English (Ireland) is '€'
908 * // The currency symbol for English (South Africa) is 'R'
909 * // The currency symbol for English (Jamaica) is 'J$'
910 * // The currency symbol for English (Caribbean) is '$'
911 * // The currency symbol for English (Belize) is 'BZ$'
912 * // The currency symbol for English (Trinidad and Tobago) is 'TT$'
913 * // The currency symbol for English (Zimbabwe) is 'Z$'
914 * // The currency symbol for English (Republic of the Philippines) is 'Php'
915 *---
916 */
917 public class NumberFormat : IFormatService {
918
919 package bool isReadOnly_;
920 private static NumberFormat invariantFormat_;
921
922 private int numberDecimalDigits_;
923 private int numberNegativePattern_;
924 private int currencyDecimalDigits_;
925 private int currencyNegativePattern_;
926 private int currencyPositivePattern_;
927 private int[] numberGroupSizes_;
928 private int[] currencyGroupSizes_;
929 private char[] numberGroupSeparator_;
930 private char[] numberDecimalSeparator_;
931 private char[] currencyGroupSeparator_;
932 private char[] currencyDecimalSeparator_;
933 private char[] currencySymbol_;
934 private char[] negativeSign_;
935 private char[] positiveSign_;
936 private char[] nanSymbol_;
937 private char[] negativeInfinitySymbol_;
938 private char[] positiveInfinitySymbol_;
939 private char[][] nativeDigits_;
940
941 /**
942 * Initializes a new, culturally independent instance.
943 *
944 * Remarks: Modify the properties of the new instance to define custom formatting.
945 */
946 public this() {
947 this(null);
948 }
949
950 package this(CultureData* cultureData) {
951 // Initialize invariant data.
952 numberDecimalDigits_ = 2;
953 numberNegativePattern_ = 1;
954 currencyDecimalDigits_ = 2;
955 numberGroupSizes_ = arrayOf!(int)(3);
956 currencyGroupSizes_ = arrayOf!(int)(3);
957 numberGroupSeparator_ = ",";
958 numberDecimalSeparator_ = ".";
959 currencyGroupSeparator_ = ",";
960 currencyDecimalSeparator_ = ".";
961 currencySymbol_ = "\u00A4";
962 negativeSign_ = "-";
963 positiveSign_ = "+";
964 nanSymbol_ = "NaN";
965 negativeInfinitySymbol_ = "-Infinity";
966 positiveInfinitySymbol_ = "Infinity";
967 nativeDigits_ = arrayOf!(char[])("0", "1", "2", "3", "4", "5", "6", "7", "8", "9");
968
969 if (cultureData !is null && cultureData.lcid != Culture.LCID_INVARIANT) {
970 // Initialize culture-specific data.
971 numberDecimalDigits_ = cultureData.digits;
972 numberNegativePattern_ = cultureData.negativeNumber;
973 currencyDecimalDigits_ = cultureData.currencyDigits;
974 currencyNegativePattern_ = cultureData.negativeCurrency;
975 currencyPositivePattern_ = cultureData.positiveCurrency;
976 numberGroupSizes_ = cultureData.grouping;
977 currencyGroupSizes_ = cultureData.monetaryGrouping;
978 numberGroupSeparator_ = cultureData.thousand;
979 numberDecimalSeparator_ = cultureData.decimal;
980 currencyGroupSeparator_ = cultureData.monetaryThousand;
981 currencyDecimalSeparator_ = cultureData.monetaryDecimal;
982 currencySymbol_ = cultureData.currency;
983 negativeSign_ = cultureData.negativeSign;
984 positiveSign_ = cultureData.positiveSign;
985 nanSymbol_ = cultureData.nan;
986 negativeInfinitySymbol_ = cultureData.negInfinity;
987 positiveInfinitySymbol_ = cultureData.posInfinity;
988 nativeDigits_ = cultureData.nativeDigits;
989 }
990 }
991
992 /**
993 * Retrieves an object defining how to format the specified type.
994 * Params: type = The TypeInfo of the resulting formatting object.
995 * Returns: If type is typeid($(LINK2 #NumberFormat, NumberFormat)), the current NumberFormat instance. Otherwise, null.
996 * Remarks: Implements $(LINK2 #IFormatService_getFormat, IFormatService.getFormat).
997 */
998 public Object getFormat(TypeInfo type) {
999 return (type is typeid(NumberFormat)) ? this : null;
1000 }
1001
1002 version (Clone)
1003 {
1004 /**
1005 * Creates a copy of the instance.
1006 */
1007 public Object clone() {
1008 NumberFormat copy = cast(NumberFormat)cloneObject(this);
1009 copy.isReadOnly_ = false;
1010 return copy;
1011 }
1012 }
1013
1014 /**
1015 * Retrieves the NumberFormat for the specified $(LINK2 #IFormatService, IFormatService).
1016 * Params: formatService = The IFormatService used to retrieve NumberFormat.
1017 * Returns: The NumberFormat for the specified IFormatService.
1018 * Remarks: The method calls $(LINK2 #IFormatService_getFormat, IFormatService.getFormat) with typeof(NumberFormat). If formatService is null,
1019 * then the value of the current property is returned.
1020 */
1021 public static NumberFormat getInstance(IFormatService formatService) {
1022 Culture culture = cast(Culture)formatService;
1023 if (culture !is null) {
1024 if (culture.numberFormat_ !is null)
1025 return culture.numberFormat_;
1026 return culture.numberFormat;
1027 }
1028 if (NumberFormat numberFormat = cast(NumberFormat)formatService)
1029 return numberFormat;
1030 if (formatService !is null) {
1031 if (NumberFormat numberFormat = cast(NumberFormat)(formatService.getFormat(typeid(NumberFormat))))
1032 return numberFormat;
1033 }
1034 return current;
1035 }
1036
1037 /**
1038 * $(I Property.) Retrieves a read-only NumberFormat instance from the current culture.
1039 * Returns: A read-only NumberFormat instance from the current culture.
1040 */
1041 public static NumberFormat current() {
1042 return Culture.current.numberFormat;
1043 }
1044
1045 /**
1046 * $(ANCHOR NumberFormat_invariantFormat)
1047 * $(I Property.) Retrieves the read-only, culturally independent NumberFormat instance.
1048 * Returns: The read-only, culturally independent NumberFormat instance.
1049 */
1050 public static NumberFormat invariantFormat() {
1051 if (invariantFormat_ is null) {
1052 invariantFormat_ = new NumberFormat;
1053 invariantFormat_.isReadOnly_ = true;
1054 }
1055 return invariantFormat_;
1056 }
1057
1058 /**
1059 * $(I Property.) Retrieves a value indicating whether the instance is read-only.
1060 * Returns: true if the instance is read-only; otherwise, false.
1061 */
1062 public final bool isReadOnly() {
1063 return isReadOnly_;
1064 }
1065
1066 /**
1067 * $(I Property.) Retrieves the number of decimal places used for numbers.
1068 * Returns: The number of decimal places used for numbers. For $(LINK2 #NumberFormat_invariantFormat, invariantFormat), the default is 2.
1069 */
1070 public final int numberDecimalDigits() {
1071 return numberDecimalDigits_;
1072 }
1073 /**
1074 * Assigns the number of decimal digits used for numbers.
1075 * Params: value = The number of decimal places used for numbers.
1076 * Throws: Exception if the property is being set and the instance is read-only.
1077 * Examples:
1078 * The following example shows the effect of changing numberDecimalDigits.
1079 * ---
1080 * import tango.io.Print, tango.text.locale.Common;
1081 *
1082 * void main() {
1083 * // Get the NumberFormat from the en-GB culture.
1084 * NumberFormat fmt = (new Culture("en-GB")).numberFormat;
1085 *
1086 * // Display a value with the default number of decimal digits.
1087 * int n = 5678;
1088 * Println(Formatter.format(fmt, "{0:N}", n));
1089 *
1090 * // Display the value with six decimal digits.
1091 * fmt.numberDecimalDigits = 6;
1092 * Println(Formatter.format(fmt, "{0:N}", n));
1093 * }
1094 *
1095 * // Produces the following output:
1096 * // 5,678.00
1097 * // 5,678.000000
1098 * ---
1099 */
1100 public final void numberDecimalDigits(int value) {
1101 checkReadOnly();
1102 numberDecimalDigits_ = value;
1103 }
1104
1105 /**
1106 * $(I Property.) Retrieves the format pattern for negative numbers.
1107 * Returns: The format pattern for negative numbers. For invariantFormat, the default is 1 (representing "-n").
1108 * Remarks: The following table shows valid values for this property.
1109 *
1110 * <table class="definitionTable">
1111 * <tr><th>Value</th><th>Pattern</th></tr>
1112 * <tr><td>0</td><td>(n)</td></tr>
1113 * <tr><td>1</td><td>-n</td></tr>
1114 * <tr><td>2</td><td>- n</td></tr>
1115 * <tr><td>3</td><td>n-</td></tr>
1116 * <tr><td>4</td><td>n -</td></tr>
1117 * </table>
1118 */
1119 public final int numberNegativePattern() {
1120 return numberNegativePattern_;
1121 }
1122 /**
1123 * $(I Property.) Assigns the format pattern for negative numbers.
1124 * Params: value = The format pattern for negative numbers.
1125 * Examples:
1126 * The following example shows the effect of the different patterns.
1127 * ---
1128 * import tango.io.Print, tango.text.locale.Common;
1129 *
1130 * void main() {
1131 * NumberFormat fmt = new NumberFormat;
1132 * int n = -5678;
1133 *
1134 * // Display the default pattern.
1135 * Println(Formatter.format(fmt, "{0:N}", n));
1136 *
1137 * // Display all patterns.
1138 * for (int i = 0; i <= 4; i++) {
1139 * fmt.numberNegativePattern = i;
1140 * Println(Formatter.format(fmt, "{0:N}", n));
1141 * }
1142 * }
1143 *
1144 * // Produces the following output:
1145 * // (5,678.00)
1146 * // (5,678.00)
1147 * // -5,678.00
1148 * // - 5,678.00
1149 * // 5,678.00-
1150 * // 5,678.00 -
1151 * ---
1152 */
1153 public final void numberNegativePattern(int value) {
1154 checkReadOnly();
1155 numberNegativePattern_ = value;
1156 }
1157
1158 /**
1159 * $(I Property.) Retrieves the number of decimal places to use in currency values.
1160 * Returns: The number of decimal digits to use in currency values.
1161 */
1162 public final int currencyDecimalDigits() {
1163 return currencyDecimalDigits_;
1164 }
1165 /**
1166 * $(I Property.) Assigns the number of decimal places to use in currency values.
1167 * Params: value = The number of decimal digits to use in currency values.
1168 */
1169 public final void currencyDecimalDigits(int value) {
1170 checkReadOnly();
1171 currencyDecimalDigits_ = value;
1172 }
1173
1174 /**
1175 * $(I Property.) Retrieves the formal pattern to use for negative currency values.
1176 * Returns: The format pattern to use for negative currency values.
1177 */
1178 public final int currencyNegativePattern() {
1179 return currencyNegativePattern_;
1180 }
1181 /**
1182 * $(I Property.) Assigns the formal pattern to use for negative currency values.
1183 * Params: value = The format pattern to use for negative currency values.
1184 */
1185 public final void currencyNegativePattern(int value) {
1186 checkReadOnly();
1187 currencyNegativePattern_ = value;
1188 }
1189
1190 /**
1191 * $(I Property.) Retrieves the formal pattern to use for positive currency values.
1192 * Returns: The format pattern to use for positive currency values.
1193 */
1194 public final int currencyPositivePattern() {
1195 return currencyPositivePattern_;
1196 }
1197 /**
1198 * $(I Property.) Assigns the formal pattern to use for positive currency values.
1199 * Returns: The format pattern to use for positive currency values.
1200 */
1201 public final void currencyPositivePattern(int value) {
1202 checkReadOnly();
1203 currencyPositivePattern_ = value;
1204 }
1205
1206 /**
1207 * $(I Property.) Retrieves the number of digits int each group to the left of the decimal place in numbers.
1208 * Returns: The number of digits int each group to the left of the decimal place in numbers.
1209 */
1210 public final int[] numberGroupSizes() {
1211 return numberGroupSizes_;
1212 }
1213 /**
1214 * $(I Property.) Assigns the number of digits int each group to the left of the decimal place in numbers.
1215 * Params: value = The number of digits int each group to the left of the decimal place in numbers.
1216 */
1217 public final void numberGroupSizes(int[] value) {
1218 checkReadOnly();
1219 numberGroupSizes_ = value;
1220 }
1221
1222 /**
1223 * $(I Property.) Retrieves the number of digits int each group to the left of the decimal place in currency values.
1224 * Returns: The number of digits int each group to the left of the decimal place in currency values.
1225 */
1226 public final int[] currencyGroupSizes() {
1227 return currencyGroupSizes_;
1228 }
1229 /**
1230 * $(I Property.) Assigns the number of digits int each group to the left of the decimal place in currency values.
1231 * Params: value = The number of digits int each group to the left of the decimal place in currency values.
1232 */
1233 public final void currencyGroupSizes(int[] value) {
1234 checkReadOnly();
1235 currencyGroupSizes_ = value;
1236 }
1237
1238 /**
1239 * $(I Property.) Retrieves the string separating groups of digits to the left of the decimal place in numbers.
1240 * Returns: The string separating groups of digits to the left of the decimal place in numbers. For example, ",".
1241 */
1242 public final char[] numberGroupSeparator() {
1243 return numberGroupSeparator_;
1244 }
1245 /**
1246 * $(I Property.) Assigns the string separating groups of digits to the left of the decimal place in numbers.
1247 * Params: value = The string separating groups of digits to the left of the decimal place in numbers.
1248 */
1249 public final void numberGroupSeparator(char[] value) {
1250 checkReadOnly();
1251 numberGroupSeparator_ = value;
1252 }
1253
1254 /**
1255 * $(I Property.) Retrieves the string used as the decimal separator in numbers.
1256 * Returns: The string used as the decimal separator in numbers. For example, ".".
1257 */
1258 public final char[] numberDecimalSeparator() {
1259 return numberDecimalSeparator_;
1260 }
1261 /**
1262 * $(I Property.) Assigns the string used as the decimal separator in numbers.
1263 * Params: value = The string used as the decimal separator in numbers.
1264 */
1265 public final void numberDecimalSeparator(char[] value) {
1266 checkReadOnly();
1267 numberDecimalSeparator_ = value;
1268 }
1269
1270 /**
1271 * $(I Property.) Retrieves the string separating groups of digits to the left of the decimal place in currency values.
1272 * Returns: The string separating groups of digits to the left of the decimal place in currency values. For example, ",".
1273 */
1274 public final char[] currencyGroupSeparator() {
1275 return currencyGroupSeparator_;
1276 }
1277 /**
1278 * $(I Property.) Assigns the string separating groups of digits to the left of the decimal place in currency values.
1279 * Params: value = The string separating groups of digits to the left of the decimal place in currency values.
1280 */
1281 public final void currencyGroupSeparator(char[] value) {
1282 checkReadOnly();
1283 currencyGroupSeparator_ = value;
1284 }
1285
1286 /**
1287 * $(I Property.) Retrieves the string used as the decimal separator in currency values.
1288 * Returns: The string used as the decimal separator in currency values. For example, ".".
1289 */
1290 public final char[] currencyDecimalSeparator() {
1291 return currencyDecimalSeparator_;
1292 }
1293 /**
1294 * $(I Property.) Assigns the string used as the decimal separator in currency values.
1295 * Params: value = The string used as the decimal separator in currency values.
1296 */
1297 public final void currencyDecimalSeparator(char[] value) {
1298 checkReadOnly();
1299 currencyDecimalSeparator_ = value;
1300 }
1301
1302 /**
1303 * $(I Property.) Retrieves the string used as the currency symbol.
1304 * Returns: The string used as the currency symbol. For example, "£".
1305 */
1306 public final char[] currencySymbol() {
1307 return currencySymbol_;
1308 }
1309 /**
1310 * $(I Property.) Assigns the string used as the currency symbol.
1311 * Params: value = The string used as the currency symbol.
1312 */
1313 public final void currencySymbol(char[] value) {
1314 checkReadOnly();
1315 currencySymbol_ = value;
1316 }
1317
1318 /**
1319 * $(I Property.) Retrieves the string denoting that a number is negative.
1320 * Returns: The string denoting that a number is negative. For example, "-".
1321 */
1322 public final char[] negativeSign() {
1323 return negativeSign_;
1324 }
1325 /**
1326 * $(I Property.) Assigns the string denoting that a number is negative.
1327 * Params: value = The string denoting that a number is negative.
1328 */
1329 public final void negativeSign(char[] value) {
1330 checkReadOnly();
1331 negativeSign_ = value;
1332 }
1333
1334 /**
1335 * $(I Property.) Retrieves the string denoting that a number is positive.
1336 * Returns: The string denoting that a number is positive. For example, "+".
1337 */
1338 public final char[] positiveSign() {
1339 return positiveSign_;
1340 }
1341 /**
1342 * $(I Property.) Assigns the string denoting that a number is positive.
1343 * Params: value = The string denoting that a number is positive.
1344 */
1345 public final void positiveSign(char[] value) {
1346 checkReadOnly();
1347 positiveSign_ = value;
1348 }
1349
1350 /**
1351 * $(I Property.) Retrieves the string representing the NaN (not a number) value.
1352 * Returns: The string representing the NaN value. For example, "NaN".
1353 */
1354 public final char[] nanSymbol() {
1355 return nanSymbol_;
1356 }
1357 /**
1358 * $(I Property.) Assigns the string representing the NaN (not a number) value.
1359 * Params: value = The string representing the NaN value.
1360 */
1361 public final void nanSymbol(char[] value) {
1362 checkReadOnly();
1363 nanSymbol_ = value;
1364 }
1365
1366 /**
1367 * $(I Property.) Retrieves the string representing negative infinity.
1368 * Returns: The string representing negative infinity. For example, "-Infinity".
1369 */
1370 public final char[] negativeInfinitySymbol() {
1371 return negativeInfinitySymbol_;
1372 }
1373 /**
1374 * $(I Property.) Assigns the string representing negative infinity.
1375 * Params: value = The string representing negative infinity.
1376 */
1377 public final void negativeInfinitySymbol(char[] value) {
1378 checkReadOnly();
1379 negativeInfinitySymbol_ = value;
1380 }
1381
1382 /**
1383 * $(I Property.) Retrieves the string representing positive infinity.
1384 * Returns: The string representing positive infinity. For example, "Infinity".
1385 */
1386 public final char[] positiveInfinitySymbol() {
1387 return positiveInfinitySymbol_;
1388 }
1389 /**
1390 * $(I Property.) Assigns the string representing positive infinity.
1391 * Params: value = The string representing positive infinity.
1392 */
1393 public final void positiveInfinitySymbol(char[] value) {
1394 checkReadOnly();
1395 positiveInfinitySymbol_ = value;
1396 }
1397
1398 /**
1399 * $(I Property.) Retrieves a string array of native equivalents of the digits 0 to 9.
1400 * Returns: A string array of native equivalents of the digits 0 to 9.
1401 */
1402 public final char[][] nativeDigits() {
1403 return nativeDigits_;
1404 }
1405 /**
1406 * $(I Property.) Assigns a string array of native equivalents of the digits 0 to 9.
1407 * Params: value = A string array of native equivalents of the digits 0 to 9.
1408 */
1409 public final void nativeDigits(char[][] value) {
1410 checkReadOnly();
1411 nativeDigits_ = value;
1412 }
1413
1414 private void checkReadOnly() {
1415 if (isReadOnly_)
1416 error("NumberFormat instance is read-only.");
1417 }
1418
1419 }
1420
1421 /**
1422 * $(ANCHOR _DateTimeFormat)
1423 * Determines how $(LINK2 #Time, Time) values are formatted, depending on the culture.
1424 * Remarks: To create a DateTimeFormat for a specific culture, create a $(LINK2 #Culture, Culture) for that culture and
1425 * retrieve its $(LINK2 #Culture_dateTimeFormat, dateTimeFormat) property. To create a DateTimeFormat for the user's current
1426 * culture, use the $(LINK2 #Culture_current, current) property.
1427 */
1428 public class DateTimeFormat : IFormatService {
1429
1430 private const char[] rfc1123Pattern_ = "ddd, dd MMM yyyy HH':'mm':'ss 'GMT'";
1431 private const char[] sortableDateTimePattern_ = "yyyy'-'MM'-'dd'T'HH':'mm':'ss";
1432 private const char[] universalSortableDateTimePattern_ = "yyyy'-'MM'-'dd' 'HH':'mm':'ss'Z'";
1433 private const char[] allStandardFormats = [ 'd', 'D', 'f', 'F', 'g', 'G', 'm', 'M', 'r', 'R', 's', 't', 'T', 'u', 'U', 'y', 'Y' ];
1434
1435
1436 package bool isReadOnly_;
1437 private static DateTimeFormat invariantFormat_;
1438 private CultureData* cultureData_;
1439
1440 private Calendar calendar_;
1441 private int[] optionalCalendars_;
1442 private int firstDayOfWeek_ = -1;
1443 private int calendarWeekRule_ = -1;
1444 private char[] dateSeparator_;
1445 private char[] timeSeparator_;
1446 private char[] amDesignator_;
1447 private char[] pmDesignator_;
1448 private char[] shortDatePattern_;
1449 private char[] shortTimePattern_;
1450 private char[] longDatePattern_;
1451 private char[] longTimePattern_;
1452 private char[] monthDayPattern_;
1453 private char[] yearMonthPattern_;
1454 private char[][] abbreviatedDayNames_;
1455 private char[][] dayNames_;
1456 private char[][] abbreviatedMonthNames_;
1457 private char[][] monthNames_;
1458
1459 private char[] fullDateTimePattern_;
1460 private char[] generalShortTimePattern_;
1461 private char[] generalLongTimePattern_;
1462
1463 private char[][] shortTimePatterns_;
1464 private char[][] shortDatePatterns_;
1465 private char[][] longTimePatterns_;
1466 private char[][] longDatePatterns_;
1467 private char[][] yearMonthPatterns_;
1468
1469 /**
1470 * $(ANCHOR DateTimeFormat_ctor)
1471 * Initializes an instance that is writable and culture-independent.
1472 */
1473 public this() {
1474 // This ctor is used by invariantFormat so we can't set the calendar property.
1475 cultureData_ = Culture.invariantCulture.cultureData_;
1476 calendar_ = Gregorian.generic;
1477 initialize();
1478 }
1479
1480 package this(CultureData* cultureData, Calendar calendar) {
1481 cultureData_ = cultureData;
1482 this.calendar = calendar;
1483 }
1484
1485 /**
1486 * $(ANCHOR DateTimeFormat_getFormat)
1487 * Retrieves an object defining how to format the specified type.
1488 * Params: type = The TypeInfo of the resulting formatting object.
1489 * Returns: If type is typeid(DateTimeFormat), the current DateTimeFormat instance. Otherwise, null.
1490 * Remarks: Implements $(LINK2 #IFormatService_getFormat, IFormatService.getFormat).
1491 */
1492 public Object getFormat(TypeInfo type) {
1493 return (type is typeid(DateTimeFormat)) ? this : null;
1494 }
1495
1496 version(Clone)
1497 {
1498 /**
1499 */
1500 public Object clone() {
1501 DateTimeFormat other = cast(DateTimeFormat)cloneObject(this);
1502 other.calendar_ = cast(Calendar)calendar.clone();
1503 other.isReadOnly_ = false;
1504 return other;
1505 }
1506 }
1507
1508 package char[][] shortTimePatterns() {
1509 if (shortTimePatterns_ == null)
1510 shortTimePatterns_ = cultureData_.shortTimes;
1511 return shortTimePatterns_.dup;
1512 }
1513
1514 package char[][] shortDatePatterns() {
1515 if (shortDatePatterns_ == null)
1516 shortDatePatterns_ = cultureData_.shortDates;
1517 return shortDatePatterns_.dup;
1518 }
1519
1520 package char[][] longTimePatterns() {
1521 if (longTimePatterns_ == null)
1522 longTimePatterns_ = cultureData_.longTimes;
1523 return longTimePatterns_.dup;
1524 }
1525
1526 package char[][] longDatePatterns() {
1527 if (longDatePatterns_ == null)
1528 longDatePatterns_ = cultureData_.longDates;
1529 return longDatePatterns_.dup;
1530 }
1531
1532 package char[][] yearMonthPatterns() {
1533 if (yearMonthPatterns_ == null)
1534 yearMonthPatterns_ = cultureData_.yearMonths;
1535 return yearMonthPatterns_;
1536 }
1537
1538 /**
1539 * $(ANCHOR DateTimeFormat_getAllDateTimePatterns)
1540 * Retrieves the standard patterns in which Time values can be formatted.
1541 * Returns: An array of strings containing the standard patterns in which Time values can be formatted.
1542 */
1543 public final char[][] getAllDateTimePatterns() {
1544 char[][] result;
1545 foreach (char format; DateTimeFormat.allStandardFormats)
1546 result ~= getAllDateTimePatterns(format);
1547 return result;
1548 }
1549
1550 /**
1551 * $(ANCHOR DateTimeFormat_getAllDateTimePatterns_char)
1552 * Retrieves the standard patterns in which Time values can be formatted using the specified format character.
1553 * Returns: An array of strings containing the standard patterns in which Time values can be formatted using the specified format character.
1554 */
1555 public final char[][] getAllDateTimePatterns(char format) {
1556
1557 char[][] combinePatterns(char[][] patterns1, char[][] patterns2) {
1558 char[][] result = new char[][patterns1.length * patterns2.length];
1559 for (int i = 0; i < patterns1.length; i++) {
1560 for (int j = 0; j < patterns2.length; j++)
1561 result[i * patterns2.length + j] = patterns1[i] ~ " " ~ patterns2[j];
1562 }
1563 return result;
1564 }
1565
1566 // format must be one of allStandardFormats.
1567 char[][] result;
1568 switch (format) {
1569 case 'd':
1570 result ~= shortDatePatterns;
1571 break;
1572 case 'D':
1573 result ~= longDatePatterns;
1574 break;
1575 case 'f':
1576 result ~= combinePatterns(longDatePatterns, shortTimePatterns);
1577 break;
1578 case 'F':
1579 result ~= combinePatterns(longDatePatterns, longTimePatterns);
1580 break;
1581 case 'g':
1582 result ~= combinePatterns(shortDatePatterns, shortTimePatterns);
1583 break;
1584 case 'G':
1585 result ~= combinePatterns(shortDatePatterns, longTimePatterns);
1586 break;
1587 case 'm':
1588 case 'M':
1589 result ~= monthDayPattern;
1590 break;
1591 case 'r':
1592 case 'R':
1593 result ~= rfc1123Pattern_;
1594 break;
1595 case 's':
1596 result ~= sortableDateTimePattern_;
1597 break;
1598 case 't':
1599 result ~= shortTimePatterns;
1600 break;
1601 case 'T':
1602 result ~= longTimePatterns;
1603 case 'u':
1604 result ~= universalSortableDateTimePattern_;
1605 break;
1606 case 'U':
1607 result ~= combinePatterns(longDatePatterns, longTimePatterns);
1608 break;
1609 case 'y':
1610 case 'Y':
1611 result ~= yearMonthPatterns;
1612 break;
1613 default:
1614 error("The specified format was not valid.");
1615 }
1616 return result;
1617 }
1618
1619 /**
1620 * $(ANCHOR DateTimeFormat_getAbbreviatedDayName)
1621 * Retrieves the abbreviated name of the specified day of the week based on the culture of the instance.
1622 * Params: dayOfWeek = A DayOfWeek value.
1623 * Returns: The abbreviated name of the day of the week represented by dayOfWeek.
1624 */
1625 public final char[] getAbbreviatedDayName(Calendar.DayOfWeek dayOfWeek) {
1626 return abbreviatedDayNames[cast(int)dayOfWeek];
1627 }
1628
1629 /**
1630 * $(ANCHOR DateTimeFormat_getDayName)
1631 * Retrieves the full name of the specified day of the week based on the culture of the instance.
1632 * Params: dayOfWeek = A DayOfWeek value.
1633 * Returns: The full name of the day of the week represented by dayOfWeek.
1634 */
1635 public final char[] getDayName(Calendar.DayOfWeek dayOfWeek) {
1636 return dayNames[cast(int)dayOfWeek];
1637 }
1638
1639 /**
1640 * $(ANCHOR DateTimeFormat_getAbbreviatedMonthName)
1641 * Retrieves the abbreviated name of the specified month based on the culture of the instance.
1642 * Params: month = An integer between 1 and 13 indicating the name of the _month to return.
1643 * Returns: The abbreviated name of the _month represented by month.
1644 */
1645 public final char[] getAbbreviatedMonthName(int month) {
1646 return abbreviatedMonthNames[month - 1];
1647 }
1648
1649 /**
1650 * $(ANCHOR DateTimeFormat_getMonthName)
1651 * Retrieves the full name of the specified month based on the culture of the instance.
1652 * Params: month = An integer between 1 and 13 indicating the name of the _month to return.
1653 * Returns: The full name of the _month represented by month.
1654 */
1655 public final char[] getMonthName(int month) {
1656 return monthNames[month - 1];
1657 }
1658
1659 /**
1660 * $(ANCHOR DateTimeFormat_getInstance)
1661 * Retrieves the DateTimeFormat for the specified IFormatService.
1662 * Params: formatService = The IFormatService used to retrieve DateTimeFormat.
1663 * Returns: The DateTimeFormat for the specified IFormatService.
1664 * Remarks: The method calls $(LINK2 #IFormatService_getFormat, IFormatService.getFormat) with typeof(DateTimeFormat). If formatService is null,
1665 * then the value of the current property is returned.
1666 */
1667 public static DateTimeFormat getInstance(IFormatService formatService) {
1668 Culture culture = cast(Culture)formatService;
1669 if (culture !is null) {
1670 if (culture.dateTimeFormat_ !is null)
1671 return culture.dateTimeFormat_;
1672 return culture.dateTimeFormat;
1673 }
1674 if (DateTimeFormat dateTimeFormat = cast(DateTimeFormat)formatService)
1675 return dateTimeFormat;
1676 if (formatService !is null) {
1677 if (DateTimeFormat dateTimeFormat = cast(DateTimeFormat)(formatService.getFormat(typeid(DateTimeFormat))))
1678 return dateTimeFormat;
1679 }
1680 return current;
1681 }
1682
1683 /**
1684 * $(ANCHOR DateTimeFormat_current)
1685 * $(I Property.) Retrieves a read-only DateTimeFormat instance from the current culture.
1686 * Returns: A read-only DateTimeFormat instance from the current culture.
1687 */
1688 public static DateTimeFormat current() {
1689 return Culture.current.dateTimeFormat;
1690 }
1691
1692 /**
1693 * $(ANCHOR DateTimeFormat_invariantFormat)
1694 * $(I Property.) Retrieves a read-only DateTimeFormat instance that is culturally independent.
1695 * Returns: A read-only DateTimeFormat instance that is culturally independent.
1696 */
1697 public static DateTimeFormat invariantFormat() {
1698 if (invariantFormat_ is null) {
1699 invariantFormat_ = new DateTimeFormat;
1700 invariantFormat_.calendar = new Gregorian();
1701 invariantFormat_.isReadOnly_ = true;
1702 }
1703 return invariantFormat_;
1704 }
1705
1706 /**
1707 * $(ANCHOR DateTimeFormat_isReadOnly)
1708 * $(I Property.) Retrieves a value indicating whether the instance is read-only.
1709 * Returns: true is the instance is read-only; otherwise, false.
1710 */
1711 public final bool isReadOnly() {
1712 return isReadOnly_;
1713 }
1714
1715 /**
1716 * $(I Property.) Retrieves the calendar used by the current culture.
1717 * Returns: The Calendar determining the calendar used by the current culture. For example, the Gregorian.
1718 */
1719 public final Calendar calendar() {
1720 assert(calendar_ !is null);
1721 return calendar_;
1722 }
1723 /**
1724 * $(ANCHOR DateTimeFormat_calendar)
1725 * $(I Property.) Assigns the calendar to be used by the current culture.
1726 * Params: value = The Calendar determining the calendar to be used by the current culture.
1727 * Exceptions: If value is not valid for the current culture, an Exception is thrown.
1728 */
1729 public final void calendar(Calendar value) {
1730 checkReadOnly();
1731 if (value !is calendar_) {
1732 for (int i = 0; i < optionalCalendars.length; i++) {
1733 if (optionalCalendars[i] == value.id) {
1734 if (calendar_ !is null) {
1735 // Clear current properties.
1736 shortDatePattern_ = null;
1737 longDatePattern_ = null;
1738 shortTimePattern_ = null;
1739 yearMonthPattern_ = null;
1740 monthDayPattern_ = null;
1741 generalShortTimePattern_ = null;
1742 generalLongTimePattern_ = null;
1743 fullDateTimePattern_ = null;
1744 shortDatePatterns_ = null;
1745 longDatePatterns_ = null;
1746 yearMonthPatterns_ = null;
1747 abbreviatedDayNames_ = null;
1748 abbreviatedMonthNames_ = null;
1749 dayNames_ = null;
1750 monthNames_ = null;
1751 }
1752 calendar_ = value;
1753 initialize();
1754 return;
1755 }
1756 }
1757 error("Not a valid calendar for the culture.");
1758 }
1759 }
1760
1761 /**
1762 * $(ANCHOR DateTimeFormat_firstDayOfWeek)
1763 * $(I Property.) Retrieves the first day of the week.
1764 * Returns: A DayOfWeek value indicating the first day of the week.
1765 */
1766 public final Calendar.DayOfWeek firstDayOfWeek() {
1767 return cast(Calendar.DayOfWeek)firstDayOfWeek_;
1768 }
1769 /**
1770 * $(I Property.) Assigns the first day of the week.
1771 * Params: valie = A DayOfWeek value indicating the first day of the week.
1772 */
1773 public final void firstDayOfWeek(Calendar.DayOfWeek value) {
1774 checkReadOnly();
1775 firstDayOfWeek_ = value;
1776 }
1777
1778 /**
1779 * $(ANCHOR DateTimeFormat_calendarWeekRule)
1780 * $(I Property.) Retrieves the _value indicating the rule used to determine the first week of the year.
1781 * Returns: A CalendarWeekRule _value determining the first week of the year.
1782 */
1783 public final Calendar.WeekRule calendarWeekRule() {
1784 return cast(Calendar.WeekRule) calendarWeekRule_;
1785 }
1786 /**
1787 * $(I Property.) Assigns the _value indicating the rule used to determine the first week of the year.
1788 * Params: value = A CalendarWeekRule _value determining the first week of the year.
1789 */
1790 public final void calendarWeekRule(Calendar.WeekRule value) {
1791 checkReadOnly();
1792 calendarWeekRule_ = value;
1793 }
1794
1795 /**
1796 * $(ANCHOR DateTimeFormat_nativeCalendarName)
1797 * $(I Property.) Retrieves the native name of the calendar associated with the current instance.
1798 * Returns: The native name of the calendar associated with the current instance.
1799 */
1800 public final char[] nativeCalendarName() {
1801 return cultureData_.nativeCalName;
1802 }
1803
1804 /**
1805 * $(ANCHOR DateTimeFormat_dateSeparator)
1806 * $(I Property.) Retrieves the string separating date components.
1807 * Returns: The string separating date components.
1808 */
1809 public final char[] dateSeparator() {
1810 if (dateSeparator_ == null)
1811 dateSeparator_ = cultureData_.date;
1812 return dateSeparator_;
1813 }
1814 /**
1815 * $(I Property.) Assigns the string separating date components.
1816 * Params: value = The string separating date components.
1817 */
1818 public final void dateSeparator(char[] value) {
1819 checkReadOnly();
1820 dateSeparator_ = value;
1821 }
1822
1823 /**
1824 * $(ANCHOR DateTimeFormat_timeSeparator)
1825 * $(I Property.) Retrieves the string separating time components.
1826 * Returns: The string separating time components.
1827 */
1828 public final char[] timeSeparator() {
1829 if (timeSeparator_ == null)
1830 timeSeparator_ = cultureData_.time;
1831 return timeSeparator_;
1832 }
1833 /**
1834 * $(I Property.) Assigns the string separating time components.
1835 * Params: value = The string separating time components.
1836 */
1837 public final void timeSeparator(char[] value) {
1838 checkReadOnly();
1839 timeSeparator_ = value;
1840 }
1841
1842 /**
1843 * $(ANCHOR DateTimeFormat_amDesignator)
1844 * $(I Property.) Retrieves the string designator for hours before noon.
1845 * Returns: The string designator for hours before noon. For example, "AM".
1846 */
1847 public final char[] amDesignator() {
1848 assert(amDesignator_ != null);
1849 return amDesignator_;
1850 }
1851 /**
1852 * $(I Property.) Assigns the string designator for hours before noon.
1853 * Params: value = The string designator for hours before noon.
1854 */
1855 public final void amDesignator(char[] value) {
1856 checkReadOnly();
1857 amDesignator_ = value;
1858 }
1859
1860 /**
1861 * $(ANCHOR DateTimeFormat_pmDesignator)
1862 * $(I Property.) Retrieves the string designator for hours after noon.
1863 * Returns: The string designator for hours after noon. For example, "PM".
1864 */
1865 public final char[] pmDesignator() {
1866 assert(pmDesignator_ != null);
1867 return pmDesignator_;
1868 }
1869 /**
1870 * $(I Property.) Assigns the string designator for hours after noon.
1871 * Params: value = The string designator for hours after noon.
1872 */
1873 public final void pmDesignator(char[] value) {
1874 checkReadOnly();
1875 pmDesignator_ = value;
1876 }
1877
1878 /**
1879 * $(ANCHOR DateTimeFormat_shortDatePattern)
1880 * $(I Property.) Retrieves the format pattern for a short date value.
1881 * Returns: The format pattern for a short date value.
1882 */
1883 public final char[] shortDatePattern() {
1884 assert(shortDatePattern_ != null);
1885 return shortDatePattern_;
1886 }
1887 /**
1888 * $(I Property.) Assigns the format pattern for a short date _value.
1889 * Params: value = The format pattern for a short date _value.
1890 */
1891 public final void shortDatePattern(char[] value) {
1892 checkReadOnly();
1893 if (shortDatePatterns_ != null)
1894 shortDatePatterns_[0] = value;
1895 shortDatePattern_ = value;
1896 generalLongTimePattern_ = null;
1897 generalShortTimePattern_ = null;
1898 }
1899
1900 /**
1901 * $(ANCHOR DateTimeFormat_shortTimePattern)
1902 * $(I Property.) Retrieves the format pattern for a short time value.
1903 * Returns: The format pattern for a short time value.
1904 */
1905 public final char[] shortTimePattern() {
1906 if (shortTimePattern_ == null)
1907 shortTimePattern_ = cultureData_.shortTime;
1908 return shortTimePattern_;
1909 }
1910 /**
1911 * $(I Property.) Assigns the format pattern for a short time _value.
1912 * Params: value = The format pattern for a short time _value.
1913 */
1914 public final void shortTimePattern(char[] value) {
1915 checkReadOnly();
1916 shortTimePattern_ = value;
1917 generalShortTimePattern_ = null;
1918 }
1919
1920 /**
1921 * $(ANCHOR DateTimeFormat_longDatePattern)
1922 * $(I Property.) Retrieves the format pattern for a long date value.
1923 * Returns: The format pattern for a long date value.
1924 */
1925 public final char[] longDatePattern() {
1926 assert(longDatePattern_ != null);
1927 return longDatePattern_;
1928 }
1929 /**
1930 * $(I Property.) Assigns the format pattern for a long date _value.
1931 * Params: value = The format pattern for a long date _value.
1932 */
1933 public final void longDatePattern(char[] value) {
1934 checkReadOnly();
1935 if (longDatePatterns_ != null)
1936 longDatePatterns_[0] = value;
1937 longDatePattern_ = value;
1938 fullDateTimePattern_ = null;
1939 }
1940
1941 /**
1942 * $(ANCHOR DateTimeFormat_longTimePattern)
1943 * $(I Property.) Retrieves the format pattern for a long time value.
1944 * Returns: The format pattern for a long time value.
1945 */
1946 public final char[] longTimePattern() {
1947 assert(longTimePattern_ != null);
1948 return longTimePattern_;
1949 }
1950 /**
1951 * $(I Property.) Assigns the format pattern for a long time _value.
1952 * Params: value = The format pattern for a long time _value.
1953 */
1954 public final void longTimePattern(char[] value) {
1955 checkReadOnly();
1956 longTimePattern_ = value;
1957 fullDateTimePattern_ = null;
1958 }
1959
1960 /**
1961 * $(ANCHOR DateTimeFormat_monthDayPattern)
1962 * $(I Property.) Retrieves the format pattern for a month and day value.
1963 * Returns: The format pattern for a month and day value.
1964 */
1965 public final char[] monthDayPattern() {
1966 if (monthDayPattern_ == null)
1967 monthDayPattern_ = cultureData_.monthDay;
1968 return monthDayPattern_;
1969 }
1970 /**
1971 * $(I Property.) Assigns the format pattern for a month and day _value.
1972 * Params: value = The format pattern for a month and day _value.
1973 */
1974 public final void monthDayPattern(char[] value) {
1975 checkReadOnly();
1976 monthDayPattern_ = value;
1977 }
1978
1979 /**
1980 * $(ANCHOR DateTimeFormat_yearMonthPattern)
1981 * $(I Property.) Retrieves the format pattern for a year and month value.
1982 * Returns: The format pattern for a year and month value.
1983 */
1984 public final char[] yearMonthPattern() {
1985 assert(yearMonthPattern_ != null);
1986 return yearMonthPattern_;
1987 }
1988 /**
1989 * $(I Property.) Assigns the format pattern for a year and month _value.
1990 * Params: value = The format pattern for a year and month _value.
1991 */
1992 public final void yearMonthPattern(char[] value) {
1993 checkReadOnly();
1994 yearMonthPattern_ = value;
1995 }
1996
1997 /**
1998 * $(ANCHOR DateTimeFormat_abbreviatedDayNames)
1999 * $(I Property.) Retrieves a string array containing the abbreviated names of the days of the week.
2000 * Returns: A string array containing the abbreviated names of the days of the week. For $(LINK2 #DateTimeFormat_invariantFormat, invariantFormat),
2001 * this contains "Sun", "Mon", "Tue", "Wed", "Thu", "Fri" and "Sat".
2002 */
2003 public final char[][] abbreviatedDayNames() {
2004 if (abbreviatedDayNames_ == null)
2005 abbreviatedDayNames_ = cultureData_.abbrevDayNames;
2006 return abbreviatedDayNames_.dup;
2007 }
2008 /**
2009 * $(I Property.) Assigns a string array containing the abbreviated names of the days of the week.
2010 * Params: value = A string array containing the abbreviated names of the days of the week.
2011 */
2012 public final void abbreviatedDayNames(char[][] value) {
2013 checkReadOnly();
2014 abbreviatedDayNames_ = value;
2015 }
2016
2017 /**
2018 * $(ANCHOR DateTimeFormat_dayNames)
2019 * $(I Property.) Retrieves a string array containing the full names of the days of the week.
2020 * Returns: A string array containing the full names of the days of the week. For $(LINK2 #DateTimeFormat_invariantFormat, invariantFormat),
2021 * this contains "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday" and "Saturday".
2022 */
2023 public final char[][] dayNames() {
2024 if (dayNames_ == null)
2025 dayNames_ = cultureData_.dayNames;
2026 return dayNames_.dup;
2027 }
2028 /**
2029 * $(I Property.) Assigns a string array containing the full names of the days of the week.
2030 * Params: value = A string array containing the full names of the days of the week.
2031 */
2032 public final void dayNames(char[][] value) {
2033 checkReadOnly();
2034 dayNames_ = value;
2035 }
2036
2037 /**
2038 * $(ANCHOR DateTimeFormat_abbreviatedMonthNames)
2039 * $(I Property.) Retrieves a string array containing the abbreviated names of the months.
2040 * Returns: A string array containing the abbreviated names of the months. For $(LINK2 #DateTimeFormat_invariantFormat, invariantFormat),
2041 * this contains "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" and "".
2042 */
2043 public final char[][] abbreviatedMonthNames() {
2044 if (abbreviatedMonthNames_ == null)
2045 abbreviatedMonthNames_ = cultureData_.abbrevMonthNames;
2046 return abbreviatedMonthNames_.dup;
2047 }
2048 /**
2049 * $(I Property.) Assigns a string array containing the abbreviated names of the months.
2050 * Params: value = A string array containing the abbreviated names of the months.
2051 */
2052 public final void abbreviatedMonthNames(char[][] value) {
2053 checkReadOnly();
2054 abbreviatedMonthNames_ = value;
2055 }
2056
2057 /**
2058 * $(ANCHOR DateTimeFormat_monthNames)
2059 * $(I Property.) Retrieves a string array containing the full names of the months.
2060 * Returns: A string array containing the full names of the months. For $(LINK2 #DateTimeFormat_invariantFormat, invariantFormat),
2061 * this contains "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" and "".
2062 */
2063 public final char[][] monthNames() {
2064 if (monthNames_ == null)
2065 monthNames_ = cultureData_.monthNames;
2066 return monthNames_.dup;
2067 }
2068 /**
2069 * $(I Property.) Assigns a string array containing the full names of the months.
2070 * Params: value = A string array containing the full names of the months.
2071 */
2072 public final void monthNames(char[][] value) {
2073 checkReadOnly();
2074 monthNames_ = value;
2075 }
2076
2077 /**
2078 * $(ANCHOR DateTimeFormat_fullDateTimePattern)
2079 * $(I Property.) Retrieves the format pattern for a long date and a long time value.
2080 * Returns: The format pattern for a long date and a long time value.
2081 */
2082 public final char[] fullDateTimePattern() {
2083 if (fullDateTimePattern_ == null)
2084 fullDateTimePattern_ = longDatePattern ~ " " ~ longTimePattern;
2085 return fullDateTimePattern_;
2086 }
2087 /**
2088 * $(I Property.) Assigns the format pattern for a long date and a long time _value.
2089 * Params: value = The format pattern for a long date and a long time _value.
2090 */
2091 public final void fullDateTimePattern(char[] value) {
2092 checkReadOnly();
2093 fullDateTimePattern_ = value;
2094 }
2095
2096 /**
2097 * $(ANCHOR DateTimeFormat_rfc1123Pattern)
2098 * $(I Property.) Retrieves the format pattern based on the IETF RFC 1123 specification, for a time value.
2099 * Returns: The format pattern based on the IETF RFC 1123 specification, for a time value.
2100 */
2101 public final char[] rfc1123Pattern() {
2102 return rfc1123Pattern_;
2103 }
2104
2105 /**
2106 * $(ANCHOR DateTimeFormat_sortableDateTimePattern)
2107 * $(I Property.) Retrieves the format pattern for a sortable date and time value.
2108 * Returns: The format pattern for a sortable date and time value.
2109 */
2110 public final char[] sortableDateTimePattern() {
2111 return sortableDateTimePattern_;
2112 }
2113
2114 /**
2115 * $(ANCHOR DateTimeFormat_universalSortableDateTimePattern)
2116 * $(I Property.) Retrieves the format pattern for a universal date and time value.
2117 * Returns: The format pattern for a universal date and time value.
2118 */
2119 public final char[] universalSortableDateTimePattern() {
2120 return universalSortableDateTimePattern_;
2121 }
2122
2123 package char[] generalShortTimePattern() {
2124 if (generalShortTimePattern_ == null)
2125 generalShortTimePattern_ = shortDatePattern ~ " " ~ shortTimePattern;
2126 return generalShortTimePattern_;
2127 }
2128
2129 package char[] generalLongTimePattern() {
2130 if (generalLongTimePattern_ == null)
2131 generalLongTimePattern_ = shortDatePattern ~ " " ~ longTimePattern;
2132 return generalLongTimePattern_;
2133 }
2134
2135 private void checkReadOnly() {
2136 if (isReadOnly_)
2137 error("DateTimeFormat instance is read-only.");
2138 }
2139
2140 private void initialize() {
2141 if (longTimePattern_ == null)
2142 longTimePattern_ = cultureData_.longTime;
2143 if (shortDatePattern_ == null)
2144 shortDatePattern_ = cultureData_.shortDate;
2145 if (longDatePattern_ == null)
2146 longDatePattern_ = cultureData_.longDate;
2147 if (yearMonthPattern_ == null)
2148 yearMonthPattern_ = cultureData_.yearMonth;
2149 if (amDesignator_ == null)
2150 amDesignator_ = cultureData_.am;
2151 if (pmDesignator_ == null)
2152 pmDesignator_ = cultureData_.pm;
2153 if (firstDayOfWeek_ == -1)
2154 firstDayOfWeek_ = cultureData_.firstDayOfWeek;
2155 if (calendarWeekRule_ == -1)
2156 calendarWeekRule_ = cultureData_.firstDayOfYear;
2157 }
2158
2159 private int[] optionalCalendars() {
2160 if (optionalCalendars_ is null)
2161 optionalCalendars_ = cultureData_.optionalCalendars;
2162 return optionalCalendars_;
2163 }
2164
2165 private void error(char[] msg) {
2166 throw new LocaleException (msg);
2167 }
2168
2169 }
2170
2171