11
11
12
12
namespace System
13
13
{
14
- /*
14
+ /*
15
15
Customized format patterns:
16
16
P.S. Format in the table below is the internal number format used to display the pattern.
17
17
@@ -58,14 +58,14 @@ Patterns Format Description Example
58
58
"ddd" short weekday name (abbreviation) Mon
59
59
"dddd" full weekday name Monday
60
60
"dddd*" full weekday name Monday
61
-
61
+
62
62
63
63
"M" "0" month w/o leading zero 2
64
64
"MM" "00" month with leading zero 02
65
65
"MMM" short month name (abbreviation) Feb
66
66
"MMMM" full month name Febuary
67
67
"MMMM*" full month name Febuary
68
-
68
+
69
69
"y" "0" two digit year (year % 100) w/o leading zero 0
70
70
"yy" "00" two digit year (year % 100) with leading zero 00
71
71
"yyy" "D3" year 2000
@@ -77,10 +77,10 @@ Patterns Format Description Example
77
77
"zz" "+00;-00" timezone offset with leading zero -08
78
78
"zzz" "+00;-00" for hour offset, "00" for minute offset full timezone offset -07:30
79
79
"zzz*" "+00;-00" for hour offset, "00" for minute offset full timezone offset -08:00
80
-
80
+
81
81
"K" -Local "zzz", e.g. -08:00
82
82
-Utc "'Z'", representing UTC
83
- -Unspecified ""
83
+ -Unspecified ""
84
84
-DateTimeOffset "zzzzz" e.g -07:30:15
85
85
86
86
"g*" the current era name A.D.
@@ -91,12 +91,12 @@ Patterns Format Description Example
91
91
'"' quoted string "ABC" will insert ABC into the formatted string.
92
92
"%" used to quote a single pattern characters E.g.The format character "%y" is to print two digit year.
93
93
"\" escaped character E.g. '\d' insert the character 'd' into the format string.
94
- other characters insert the character into the format string.
94
+ other characters insert the character into the format string.
95
95
96
- Pre-defined format characters:
96
+ Pre-defined format characters:
97
97
(U) to indicate Universal time is used.
98
98
(G) to indicate Gregorian calendar is used.
99
-
99
+
100
100
Format Description Real format Example
101
101
========= ================================= ====================== =======================
102
102
"d" short date culture-specific 10/31/1999
@@ -120,7 +120,7 @@ based on ISO 8601.
120
120
121
121
*/
122
122
123
- //This class contains only static members and does not require the serializable attribute.
123
+ //This class contains only static members and does not require the serializable attribute.
124
124
internal static
125
125
class DateTimeFormat
126
126
{
@@ -155,16 +155,16 @@ class DateTimeFormat
155
155
} ;
156
156
157
157
////////////////////////////////////////////////////////////////////////////
158
- //
159
- // Format the positive integer value to a string and perfix with assigned
158
+ //
159
+ // Format the positive integer value to a string and perfix with assigned
160
160
// length of leading zero.
161
161
//
162
162
// Parameters:
163
163
// value: The value to format
164
- // len: The maximum length for leading zero.
164
+ // len: The maximum length for leading zero.
165
165
// If the digits of the value is greater than len, no leading zero is added.
166
166
//
167
- // Notes:
167
+ // Notes:
168
168
// The function can format to Int32.MaxValue.
169
169
//
170
170
////////////////////////////////////////////////////////////////////////////
@@ -252,16 +252,16 @@ private static String FormatMonth(int month, int repeatCount, DateTimeFormatInfo
252
252
//
253
253
// Action: Return the Hebrew month name for the specified DateTime.
254
254
// Returns: The month name string for the specified DateTime.
255
- // Arguments:
255
+ // Arguments:
256
256
// time the time to format
257
- // month The month is the value of HebrewCalendar.GetMonth(time).
257
+ // month The month is the value of HebrewCalendar.GetMonth(time).
258
258
// repeat Return abbreviated month name if repeat=3, or full month name if repeat=4
259
259
// dtfi The DateTimeFormatInfo which uses the Hebrew calendars as its calendar.
260
260
// Exceptions: None.
261
- //
261
+ //
262
262
263
263
/* Note:
264
- If DTFI is using Hebrew calendar, GetMonthName()/GetAbbreviatedMonthName() will return month names like this:
264
+ If DTFI is using Hebrew calendar, GetMonthName()/GetAbbreviatedMonthName() will return month names like this:
265
265
1 Hebrew 1st Month
266
266
2 Hebrew 2nd Month
267
267
.. ...
@@ -274,7 +274,7 @@ 11 Hebrew 10th Month
274
274
12 Hebrew 11th Month
275
275
13 Hebrew 12th Month
276
276
277
- Therefore, if we are in a regular year, we have to increment the month name if moth is greater or eqaul to 7.
277
+ Therefore, if we are in a regular year, we have to increment the month name if moth is greater or eqaul to 7.
278
278
*/
279
279
private static String FormatHebrewMonthName ( DateTime time , int month , int repeatCount , DateTimeFormatInfo dtfi )
280
280
{
@@ -377,7 +377,7 @@ internal static int ParseNextChar(ReadOnlySpan<char> format, int pos)
377
377
//
378
378
// Actions: Check the format to see if we should use genitive month in the formatting.
379
379
// Starting at the position (index) in the (format) string, look back and look ahead to
380
- // see if there is "d" or "dd". In the case like "d MMMM" or "MMMM dd", we can use
380
+ // see if there is "d" or "dd". In the case like "d MMMM" or "MMMM dd", we can use
381
381
// genitive form. Genitive form is not used if there is more than two "d".
382
382
// Arguments:
383
383
// format The format string to be scanned.
@@ -447,7 +447,7 @@ private static bool IsUseGenitiveForm(ReadOnlySpan<char> format, int index, int
447
447
// FormatCustomized
448
448
//
449
449
// Actions: Format the DateTime instance using the specified format.
450
- //
450
+ //
451
451
private static StringBuilder FormatCustomized (
452
452
DateTime dateTime , ReadOnlySpan < char > format , DateTimeFormatInfo dtfi , TimeSpan offset , StringBuilder result )
453
453
{
@@ -459,9 +459,11 @@ private static StringBuilder FormatCustomized(
459
459
resultBuilderIsPooled = true ;
460
460
result = StringBuilderCache . Acquire ( ) ;
461
461
}
462
-
462
+
463
463
// This is a flag to indicate if we are format the dates using Hebrew calendar.
464
464
bool isHebrewCalendar = ( cal . ID == CalendarId . HEBREW ) ;
465
+ bool isJapaneseCalendar = ( cal . ID == CalendarId . JAPAN ) ;
466
+
465
467
// This is a flag to indicate if we are formating hour/minute/second only.
466
468
bool bTimeOnly = true ;
467
469
@@ -601,7 +603,7 @@ private static StringBuilder FormatCustomized(
601
603
bTimeOnly = false ;
602
604
break ;
603
605
case 'M' :
604
- //
606
+ //
605
607
// tokenLen == 1 : Month as digits with no leading zero.
606
608
// tokenLen == 2 : Month as digits with leading zero for single-digit months.
607
609
// tokenLen == 3 : Month as a three-letter abbreviation.
@@ -653,7 +655,19 @@ private static StringBuilder FormatCustomized(
653
655
654
656
int year = cal . GetYear ( dateTime ) ;
655
657
tokenLen = ParseRepeatPattern ( format , i , ch ) ;
656
- if ( dtfi . HasForceTwoDigitYears )
658
+ if ( isJapaneseCalendar &&
659
+ ! AppContextSwitches . FormatJapaneseFirstYearAsANumber &&
660
+ year == 1 &&
661
+ i + tokenLen < format . Length - 1 &&
662
+ format [ i + tokenLen ] == '\' ' &&
663
+ format [ i + tokenLen + 1 ] == DateTimeFormatInfoScanner . CJKYearSuff [ 0 ] )
664
+ {
665
+ // We are formatting a Japanese date with year equals 1 and the year number is followed by the year sign \u5e74
666
+ // In Japanese dates, the first year in the era is not formatted as a number 1 instead it is formatted as \u5143 which means
667
+ // first or beginning of the era.
668
+ result . Append ( DateTimeFormatInfo . JapaneseEraStart [ 0 ] ) ;
669
+ }
670
+ else if ( dtfi . HasForceTwoDigitYears )
657
671
{
658
672
FormatDigits ( result , year , tokenLen <= 2 ? tokenLen : 2 ) ;
659
673
}
@@ -697,7 +711,7 @@ private static StringBuilder FormatCustomized(
697
711
break ;
698
712
case '%' :
699
713
// Optional format character.
700
- // For example, format string "%d" will print day of month
714
+ // For example, format string "%d" will print day of month
701
715
// without leading zero. Most of the cases, "%" can be ignored.
702
716
nextChar = ParseNextChar ( format , i ) ;
703
717
// nextChar will be -1 if we already reach the end of the format string.
@@ -726,7 +740,7 @@ private static StringBuilder FormatCustomized(
726
740
// Escaped character. Can be used to insert character into the format string.
727
741
// For exmple, "\d" will insert the character 'd' into the string.
728
742
//
729
- // NOTENOTE : we can remove this format character if we enforce the enforced quote
743
+ // NOTENOTE : we can remove this format character if we enforce the enforced quote
730
744
// character rule.
731
745
// That is, we ask everyone to use single quote or double quote to insert characters,
732
746
// then we can remove this character.
@@ -775,7 +789,7 @@ private static void FormatCustomizedTimeZone(DateTime dateTime, TimeSpan offset,
775
789
776
790
if ( timeOnly && dateTime . Ticks < Calendar . TicksPerDay )
777
791
{
778
- // For time only format and a time only input, the time offset on 0001/01/01 is less
792
+ // For time only format and a time only input, the time offset on 0001/01/01 is less
779
793
// accurate than the system's current offset because of daylight saving time.
780
794
offset = TimeZoneInfo . GetLocalUtcOffset ( DateTime . Now , TimeZoneInfoOptions . NoThrowOnInvalidTime ) ;
781
795
}
@@ -820,8 +834,8 @@ private static void FormatCustomizedTimeZone(DateTime dateTime, TimeSpan offset,
820
834
private static void FormatCustomizedRoundripTimeZone ( DateTime dateTime , TimeSpan offset , StringBuilder result )
821
835
{
822
836
// The objective of this format is to round trip the data in the type
823
- // For DateTime it should round-trip the Kind value and preserve the time zone.
824
- // DateTimeOffset instance, it should do so by using the internal time zone.
837
+ // For DateTime it should round-trip the Kind value and preserve the time zone.
838
+ // DateTimeOffset instance, it should do so by using the internal time zone.
825
839
826
840
if ( offset == NullOffset )
827
841
{
@@ -897,7 +911,7 @@ internal static String GetRealFormat(ReadOnlySpan<char> format, DateTimeFormatIn
897
911
realFormat = RoundtripFormat ;
898
912
break ;
899
913
case 'r' :
900
- case 'R' : // RFC 1123 Standard
914
+ case 'R' : // RFC 1123 Standard
901
915
realFormat = dtfi . RFC1123Pattern ;
902
916
break ;
903
917
case 's' : // Sortable without Time Zone Info
@@ -940,7 +954,7 @@ private static String ExpandPredefinedFormat(ReadOnlySpan<char> format, ref Date
940
954
dtfi = DateTimeFormatInfo . InvariantInfo ;
941
955
break ;
942
956
case 'r' :
943
- case 'R' : // RFC 1123 Standard
957
+ case 'R' : // RFC 1123 Standard
944
958
if ( offset != NullOffset )
945
959
{
946
960
// Convert to UTC invariants mean this will be in range
@@ -952,7 +966,7 @@ private static String ExpandPredefinedFormat(ReadOnlySpan<char> format, ref Date
952
966
}
953
967
dtfi = DateTimeFormatInfo . InvariantInfo ;
954
968
break ;
955
- case 's' : // Sortable without Time Zone Info
969
+ case 's' : // Sortable without Time Zone Info
956
970
dtfi = DateTimeFormatInfo . InvariantInfo ;
957
971
break ;
958
972
case 'u' : // Universal time in sortable format.
@@ -1075,7 +1089,7 @@ private static StringBuilder FormatStringBuilder(DateTime dateTime, ReadOnlySpan
1075
1089
// If the time is less than 1 day, consider it as time of day.
1076
1090
// Just print out the short time format.
1077
1091
//
1078
- // This is a workaround for VB, since they use ticks less then one day to be
1092
+ // This is a workaround for VB, since they use ticks less then one day to be
1079
1093
// time of day. In cultures which use calendar other than Gregorian calendar, these
1080
1094
// alternative calendar may not support ticks less than a day.
1081
1095
// For example, Japanese calendar only supports date after 1868/9/8.
0 commit comments