// // FormatCustomized // // Actions: Format the DateTime instance using the specified format. // private static String FormatCustomized(DateTime dateTime, String format, DateTimeFormatInfo dtfi, TimeSpan offset) { Calendar cal = dtfi.Calendar; StringBuilder result = StringBuilderCache.Acquire(); // This is a flag to indicate if we are format the dates using Hebrew calendar. bool isHebrewCalendar = (cal.ID == Calendar.CAL_HEBREW); // This is a flag to indicate if we are formating hour/minute/second only. bool bTimeOnly = true; int i = 0; int tokenLen, hour12; while (i < format.Length) { char ch = format[i]; int nextChar; switch (ch) { case 'g': tokenLen = ParseRepeatPattern(format, i, ch); result.Append(dtfi.GetEraName(cal.GetEra(dateTime))); break; case 'h': tokenLen = ParseRepeatPattern(format, i, ch); hour12 = dateTime.Hour % 12; if (hour12 == 0) { hour12 = 12; } FormatDigits(result, hour12, tokenLen); break; case 'H': tokenLen = ParseRepeatPattern(format, i, ch); FormatDigits(result, dateTime.Hour, tokenLen); break; case 'm': tokenLen = ParseRepeatPattern(format, i, ch); FormatDigits(result, dateTime.Minute, tokenLen); break; case 's': tokenLen = ParseRepeatPattern(format, i, ch); FormatDigits(result, dateTime.Second, tokenLen); break; case 'f': case 'F': tokenLen = ParseRepeatPattern(format, i, ch); if (tokenLen <= MaxSecondsFractionDigits) { long fraction = (dateTime.Ticks % Calendar.TicksPerSecond); fraction = fraction / (long)Math.Pow(10, 7 - tokenLen); if (ch == 'f') { result.Append(((int)fraction).ToString(fixedNumberFormats[tokenLen - 1], CultureInfo.InvariantCulture)); } else { int effectiveDigits = tokenLen; while (effectiveDigits > 0) { if (fraction % 10 == 0) { fraction = fraction / 10; effectiveDigits--; } else { break; } } if (effectiveDigits > 0) { result.Append(((int)fraction).ToString(fixedNumberFormats[effectiveDigits - 1], CultureInfo.InvariantCulture)); } else { // No fraction to emit, so see if we should remove decimal also. if (result.Length > 0 && result[result.Length - 1] == '.') { result.Remove(result.Length - 1, 1); } } } } else { throw new FormatException(Environment.GetResourceString("Format_InvalidString")); } break; case 't': tokenLen = ParseRepeatPattern(format, i, ch); if (tokenLen == 1) { if (dateTime.Hour < 12) { if (dtfi.AMDesignator.Length >= 1) { result.Append(dtfi.AMDesignator[0]); } } else { if (dtfi.PMDesignator.Length >= 1) { result.Append(dtfi.PMDesignator[0]); } } } else { result.Append((dateTime.Hour < 12 ? dtfi.AMDesignator : dtfi.PMDesignator)); } break; case 'd': // // tokenLen == 1 : Day of month as digits with no leading zero. // tokenLen == 2 : Day of month as digits with leading zero for single-digit months. // tokenLen == 3 : Day of week as a three-leter abbreviation. // tokenLen >= 4 : Day of week as its full name. // tokenLen = ParseRepeatPattern(format, i, ch); if (tokenLen <= 2) { int day = cal.GetDayOfMonth(dateTime); if (isHebrewCalendar) { // For Hebrew calendar, we need to convert numbers to Hebrew text for yyyy, MM, and dd values. HebrewFormatDigits(result, day); } else { FormatDigits(result, day, tokenLen); } } else { int dayOfWeek = (int)cal.GetDayOfWeek(dateTime); result.Append(FormatDayOfWeek(dayOfWeek, tokenLen, dtfi)); } bTimeOnly = false; break; case 'M': // // tokenLen == 1 : Month as digits with no leading zero. // tokenLen == 2 : Month as digits with leading zero for single-digit months. // tokenLen == 3 : Month as a three-letter abbreviation. // tokenLen >= 4 : Month as its full name. // tokenLen = ParseRepeatPattern(format, i, ch); int month = cal.GetMonth(dateTime); if (tokenLen <= 2) { if (isHebrewCalendar) { // For Hebrew calendar, we need to convert numbers to Hebrew text for yyyy, MM, and dd values. HebrewFormatDigits(result, month); } else { FormatDigits(result, month, tokenLen); } } else { if (isHebrewCalendar) { result.Append(FormatHebrewMonthName(dateTime, month, tokenLen, dtfi)); } else { if ((dtfi.FormatFlags & DateTimeFormatFlags.UseGenitiveMonth) != 0 && tokenLen >= 4) { result.Append( dtfi.internalGetMonthName( month, IsUseGenitiveForm(format, i, tokenLen, 'd')? MonthNameStyles.Genitive : MonthNameStyles.Regular, false)); } else { result.Append(FormatMonth(month, tokenLen, dtfi)); } } } bTimeOnly = false; break; case 'y': // Notes about OS behavior: // y: Always print (year % 100). No leading zero. // yy: Always print (year % 100) with leading zero. // yyy/yyyy/yyyyy/... : Print year value. No leading zero. int year = cal.GetYear(dateTime); tokenLen = ParseRepeatPattern(format, i, ch); if (dtfi.HasForceTwoDigitYears) { FormatDigits(result, year, tokenLen <= 2 ? tokenLen : 2); } else if (cal.ID == Calendar.CAL_HEBREW) { HebrewFormatDigits(result, year); } else { if (tokenLen <= 2) { FormatDigits(result, year % 100, tokenLen); } else { String fmtPattern = "D" + tokenLen; result.Append(year.ToString(fmtPattern, CultureInfo.InvariantCulture)); } } bTimeOnly = false; break; case 'z': tokenLen = ParseRepeatPattern(format, i, ch); FormatCustomizedTimeZone(dateTime, offset, format, tokenLen, bTimeOnly, result); break; case 'K': tokenLen = 1; FormatCustomizedRoundripTimeZone(dateTime, offset, result); break; case ':': result.Append(dtfi.TimeSeparator); tokenLen = 1; break; case '/': result.Append(dtfi.DateSeparator); tokenLen = 1; break; case '\'': case '\"': StringBuilder enquotedString = new StringBuilder(); tokenLen = ParseQuoteString(format, i, enquotedString); result.Append(enquotedString); break; case '%': // Optional format character. // For example, format string "%d" will print day of month // without leading zero. Most of the cases, "%" can be ignored. nextChar = ParseNextChar(format, i); // nextChar will be -1 if we already reach the end of the format string. // Besides, we will not allow "%%" appear in the pattern. if (nextChar >= 0 && nextChar != (int)'%') { result.Append(FormatCustomized(dateTime, ((char)nextChar).ToString(), dtfi, offset)); tokenLen = 2; } else { // // This means that '%' is at the end of the format string or // "%%" appears in the format string. // throw new FormatException(Environment.GetResourceString("Format_InvalidString")); } break; case '\\': // Escaped character. Can be used to insert character into the format string. // For exmple, "\d" will insert the character 'd' into the string. // // NOTENOTE : we can remove this format character if we enforce the enforced quote // character rule. // That is, we ask everyone to use single quote or double quote to insert characters, // then we can remove this character. // nextChar = ParseNextChar(format, i); if (nextChar >= 0) { result.Append(((char)nextChar)); tokenLen = 2; } else { // // This means that '\' is at the end of the formatting string. // throw new FormatException(Environment.GetResourceString("Format_InvalidString")); } break; default: // NOTENOTE : we can remove this rule if we enforce the enforced quote // character rule. // That is, if we ask everyone to use single quote or double quote to insert characters, // then we can remove this default block. result.Append(ch); tokenLen = 1; break; } i += tokenLen; } return StringBuilderCache.GetStringAndRelease(result); }
private static bool MatchEraName(ref __DTString str, DateTimeFormatInfo dtfi, ref int result) { if (str.GetNext()) { int[] eras = dtfi.Calendar.Eras; if (eras != null) { for (int i = 0; i < eras.Length; i++) { string text = dtfi.GetEraName(eras[i]); if (str.MatchSpecifiedWord(text)) { str.Index += text.Length - 1; result = eras[i]; return true; } text = dtfi.GetAbbreviatedEraName(eras[i]); if (str.MatchSpecifiedWord(text)) { str.Index += text.Length - 1; result = eras[i]; return true; } } } } return false; }
/// <summary> /// Returns a string representation of this object. /// </summary> /// <param name="format"> /// The format pattern. /// </param> /// <param name="dtfi"> /// The <see cref="DateTimeFormatInfo"/> to use for formatting. /// </param> /// <param name="nameProvider"> /// The day and month name provider. /// </param> /// <param name="nativeDigits"> /// If not <c>null</c> and valid, uses for number representation the specified native digits. /// </param> /// <returns> /// A <see cref="System.String"/> that represents this instance. /// </returns> private string ToString(string format, DateTimeFormatInfo dtfi, ICustomFormatProvider nameProvider, string[] nativeDigits = null) { if (dtfi == null) { dtfi = CultureInfo.CurrentUICulture.DateTimeFormat; } if (string.IsNullOrEmpty(format)) { format = nameProvider != null ? nameProvider.ShortDatePattern : dtfi.ShortDatePattern; } else if (format.Length == 1) { switch (format[0]) { case 'D': { format = nameProvider != null ? nameProvider.LongDatePattern : dtfi.LongDatePattern; break; } case 'm': case 'M': { format = nameProvider != null ? nameProvider.MonthDayPattern : dtfi.MonthDayPattern; break; } case 'y': case 'Y': { format = nameProvider != null ? nameProvider.YearMonthPattern : dtfi.YearMonthPattern; break; } default: { format = nameProvider != null ? nameProvider.ShortDatePattern : dtfi.ShortDatePattern; break; } } } format = format.Replace(nameProvider != null ? nameProvider.DateSeparator : dtfi.DateSeparator, "/"); StringBuilder sb = new StringBuilder(); Calendar c = nameProvider != null ? nameProvider.Calendar : dtfi.Calendar; int i = 0; while (i < format.Length) { int tokLen; char ch = format[i]; switch (ch) { case 'd': { tokLen = CountChar(format, i, ch); sb.Append( tokLen <= 2 ? DateMethods.GetNumberString(this.Day, nativeDigits, tokLen == 2) : GetDayName(c.GetDayOfWeek(this.Date), dtfi, nameProvider, tokLen == 3)); break; } case 'M': { tokLen = CountChar(format, i, ch); sb.Append( tokLen <= 2 ? DateMethods.GetNumberString(this.Month, nativeDigits, tokLen == 2) : GetMonthName(this.Month, this.Year, dtfi, nameProvider, tokLen == 3)); break; } case 'y': { tokLen = CountChar(format, i, ch); sb.Append( tokLen <= 2 ? DateMethods.GetNumberString(this.Year % 100, nativeDigits, true) : DateMethods.GetNumberString(this.Year, nativeDigits, false)); break; } case 'g': { tokLen = CountChar(format, i, ch); sb.Append(nameProvider != null ? nameProvider.GetEraName(c.GetEra(this.Date)) : dtfi.GetEraName(c.GetEra(this.Date))); break; } case '/': { tokLen = CountChar(format, i, ch); sb.Append(nameProvider != null ? nameProvider.DateSeparator : dtfi.DateSeparator); break; } case '\'': { tokLen = 1; break; } default: { tokLen = 1; sb.Append(ch.ToString(CultureInfo.CurrentUICulture)); break; } } i += tokLen; } return sb.ToString(); }
private static JObject CreateDateInfoJson(DateTimeFormatInfo di) { var obj = new { firstDay = di.FirstDayOfWeek, days = new { names = di.DayNames, namesAbbr = di.AbbreviatedDayNames, namesShort = di.ShortestDayNames }, months = new { names = di.MonthNames, namesAbbr = di.AbbreviatedMonthNames }, AM = di.AMDesignator, PM = di.PMDesignator, eras = di.Calendar.Eras.Select(era => new { offset = 0, start = (string)null, name = di.GetEraName(era) }).ToArray(), twoDigitYearMax = di.Calendar.TwoDigitYearMax, patterns = new { d = di.ShortDatePattern, D = di.LongDatePattern, t = di.ShortTimePattern, T = di.LongTimePattern, f = di.LongDatePattern + " " + di.ShortTimePattern, F = di.LongDatePattern + " " + di.LongTimePattern, M = di.MonthDayPattern, Y = di.YearMonthPattern, } }; var jobj = JObject.FromObject(obj); jobj["/"] = di.DateSeparator; jobj[":"] = di.TimeSeparator; if (!di.MonthNames.SequenceEqual(di.MonthGenitiveNames)) { var monthsGenitive = jobj["monthsGenitive"] = new JObject(); monthsGenitive["names"] = JArray.FromObject(di.MonthGenitiveNames); monthsGenitive["namesAbbr"] = JArray.FromObject(di.AbbreviatedMonthGenitiveNames); } return new JObject() { {"standard", jobj } }; }
// Format a date value as a string using a particular pattern format. public static String Format(String format, DateTime date, DateTimeFormatInfo info) { // Format the date/time value. StringBuilder builder = new StringBuilder(); int posn = 0; char ch; int count, value; while(posn < format.Length) { // Extract the next format character plus its count. ch = format[posn++]; count = 1; switch(ch) { case 'd': case 'm': case 'M': case 'y': case 'g': case 'h': case 'H': case 's': case 'f': case 't': case 'z': { while(posn < format.Length && format[posn] == ch) { ++posn; ++count; } } break; case ':': { builder.Append(info.TimeSeparator); continue; } // Not reached. case '/': { builder.Append(info.DateSeparator); continue; } // Not reached. case '%': { // Used to escape custom patterns that would // otherwise look like single-letter formats. continue; } // Not reached. case '\\': { // Escape the next character. if(posn < format.Length) { builder.Append(format[posn++]); } continue; } // Not reached. case '\'': { // Quoted text. while(posn < format.Length) { ch = format[posn++]; if(ch == '\'') { break; } builder.Append(ch); } continue; } // Not reached. default: { // Literal character. builder.Append(ch); continue; } // Not reached. } // Process the format character. switch(ch) { case 'd': { // Output the day or weekday. if(count == 1) { value = date.Day; if(value < 10) { builder.Append((char)('0' + value)); } else { builder.Append((char)('0' + (value / 10))); builder.Append((char)('0' + (value % 10))); } } else if(count == 2) { value = date.Day; builder.Append((char)('0' + (value / 10))); builder.Append((char)('0' + (value % 10))); } else if(count == 3) { builder.Append (info.AbbreviatedDayNames [(int)(date.DayOfWeek)]); } else { builder.Append (info.DayNames[(int)(date.DayOfWeek)]); } } break; case 'M': { // Output the month. value = date.Month; if(count == 1) { if(value < 10) { builder.Append((char)('0' + value)); } else { builder.Append((char)('0' + (value / 10))); builder.Append((char)('0' + (value % 10))); } } else if(count == 2) { builder.Append((char)('0' + (value / 10))); builder.Append((char)('0' + (value % 10))); } else if(count == 3) { builder.Append (info.AbbreviatedMonthNames[value - 1]); } else { builder.Append(info.MonthNames[value - 1]); } } break; case 'y': { // Output the year. value = date.Year; if(count == 1) { value %= 100; if(value < 10) { builder.Append((char)('0' + value)); } else { builder.Append((char)('0' + (value / 10))); builder.Append((char)('0' + (value % 10))); } } else if(count == 2) { value %= 100; builder.Append((char)('0' + (value / 10))); builder.Append((char)('0' + (value % 10))); } else { builder.Append((char)('0' + (value / 1000))); builder.Append ((char)('0' + ((value / 100 % 10)))); builder.Append ((char)('0' + ((value / 10 % 10)))); builder.Append((char)('0' + (value % 10))); } } break; case 'g': { // Output the era name. try { int era = info.Calendar.GetEra(date); builder.Append(info.GetEraName(era)); } catch(ArgumentException) { // The date does not have an era. } } break; case 'h': { // Output the hour in 12-hour format. value = date.Hour; if(value == 0) { value = 12; } else if(value > 12) { value -= 12; } if(count == 1) { if(value < 10) { builder.Append((char)('0' + value)); } else { builder.Append((char)('0' + (value / 10))); builder.Append((char)('0' + (value % 10))); } } else { builder.Append((char)('0' + (value / 10))); builder.Append((char)('0' + (value % 10))); } } break; case 'H': { // Output the hour in 24-hour format. value = date.Hour; if(count == 1) { if(value < 10) { builder.Append((char)('0' + value)); } else { builder.Append((char)('0' + (value / 10))); builder.Append((char)('0' + (value % 10))); } } else { builder.Append((char)('0' + (value / 10))); builder.Append((char)('0' + (value % 10))); } } break; case 'm': { // Output the minute. value = date.Minute; if(count == 1) { if(value < 10) { builder.Append((char)('0' + value)); } else { builder.Append((char)('0' + (value / 10))); builder.Append((char)('0' + (value % 10))); } } else { builder.Append((char)('0' + (value / 10))); builder.Append((char)('0' + (value % 10))); } } break; case 's': { // Output the second. value = date.Second; if(count == 1) { if(value < 10) { builder.Append((char)('0' + value)); } else { builder.Append((char)('0' + (value / 10))); builder.Append((char)('0' + (value % 10))); } } else { builder.Append((char)('0' + (value / 10))); builder.Append((char)('0' + (value % 10))); } } break; case 'f': { // Output fractions of a second. if(count > 7) { count = 7; } long frac = date.Ticks; long divisor = TimeSpan.TicksPerSecond; while(count > 0) { divisor /= 10; value = (int)((frac / divisor) % 10); builder.Append((char)('0' + value)); frac %= divisor; --count; } } break; case 't': { value = date.Hour; if(count == 1) { if(value < 12) { builder.Append(info.AMDesignator[0]); } else { builder.Append(info.PMDesignator[0]); } } else { if(value < 12) { builder.Append(info.AMDesignator); } else { builder.Append(info.PMDesignator); } } } break; #if !ECMA_COMPAT case 'z': { long offset = TimeZone.CurrentTimeZone .GetUtcOffset(date).Ticks; int hour, min; if(offset >= 0) { builder.Append('+'); } else { builder.Append('-'); offset = -offset; } hour = (int)(offset / TimeSpan.TicksPerHour); offset %= TimeSpan.TicksPerHour; min = (int)(offset / TimeSpan.TicksPerMinute); if(count == 1) { if(hour < 10) { builder.Append((char)('0' + hour)); } else { builder.Append((char)('0' + (hour / 10))); builder.Append((char)('0' + (hour % 10))); } } else if(count == 2) { builder.Append((char)('0' + (hour / 10))); builder.Append((char)('0' + (hour % 10))); } else { builder.Append((char)('0' + (hour / 10))); builder.Append((char)('0' + (hour % 10))); builder.Append(':'); builder.Append((char)('0' + (min / 10))); builder.Append((char)('0' + (min % 10))); } } break; #endif } } // Return the formatted string to the caller. return builder.ToString(); }
private ClientCultureInfo(CultureInfo cultureInfo) { name = cultureInfo.Name; numberFormat = cultureInfo.NumberFormat; dateTimeFormat = cultureInfo.DateTimeFormat; var calendar = dateTimeFormat == null ? null : dateTimeFormat.Calendar; if (calendar != null) { // Dev10 425049: Support Eras for gregorian based calendars // with a simple year offset, and non-gregorian calendars. // Era data is stored in binary resource "culture.nlp" in mscorlib, // hard coded here for simplicity. // era array has the following structure: // [eraNumber1, eraName1, eraStartInTicks1, eraGregorianYearOffset1, eraNumber2, ...] eras = new object[calendar.Eras.Length * 4]; int i = 0; foreach (int era in calendar.Eras) { // era number eras[i + eraNumber] = era; // era name eras[i + eraName] = dateTimeFormat.GetEraName(era); // calendars with only one era will have a null tick count // signifying that the era starts from the lowest datetime // era begining in ticks (null = the oldest era) // eras[i + eraStart] = null; // era year offset from normal gregorian year // some calendars dont have an offset, just a different name // for the A.D. era (B.C. is not supported by normal calendar, // so most calendars only have 1 era) eras[i + eraYearOffset] = 0; i += 4; } var calendarType = calendar.GetType(); if (calendarType != typeof(GregorianCalendar)) { if (calendarType == typeof(TaiwanCalendar)) { // Only the current era is supported, so no tick count is needed //eras[eraStart] = -1830384000000; eras[eraYearOffset] = 1911; } else if (calendarType == typeof(KoreanCalendar)) { // only one era to speak of, so no tick count is needed //eras[eraStart] = -62135596800000; eras[eraYearOffset] = -2333; } else if (calendarType == typeof(ThaiBuddhistCalendar)) { // only one era to speak of, so no tick count is needed //eras[eraStart] = -62135596800000; eras[eraYearOffset] = -543; } else if (calendarType == typeof(JapaneseCalendar)) { // there are multiple eras eras[0 + eraStart] = 60022080000; eras[0 + eraYearOffset] = 1988; eras[4 + eraStart] = -1357603200000; eras[4 + eraYearOffset] = 1925; eras[8 + eraStart] = -1812153600000; eras[8 + eraYearOffset] = 1911; // oldest era is technically from this offset, but for simplicity // it is counted from the lowest date time, so no tick count needed. //eras[12 + eraStart] = -3218832000000; eras[12 + eraYearOffset] = 1867; } else if (calendarType == typeof(HijriCalendar)) { _convertScript = "Date.HijriCalendar.js"; _adjustment = ((HijriCalendar)calendar).HijriAdjustment; } else if (calendarType == typeof(UmAlQuraCalendar)) { _convertScript = "Date.UmAlQuraCalendar.js"; } // else { other calendars arent supported or have no era offsets just different names for A.D. } } }
private void VerificationHelper(DateTimeFormatInfo info, int era, string expected) { string actual = info.GetEraName(era); Assert.Equal(expected, actual); }
public static string ToString (DateTime dt, TimeSpan? utc_offset, string format, DateTimeFormatInfo dfi) { // the length of the format is usually a good guess of the number // of chars in the result. Might save us a few bytes sometimes // Add + 10 for cases like mmmm dddd StringBuilder result = new StringBuilder (format.Length + 10); // For some cases, the output should not use culture dependent calendar DateTimeFormatInfo inv = DateTimeFormatInfo.InvariantInfo; if (format == inv.RFC1123Pattern) dfi = inv; else if (format == inv.UniversalSortableDateTimePattern) dfi = inv; int i = 0; while (i < format.Length) { int tokLen; bool omitZeros = false; char ch = format [i]; switch (ch) { // // Time Formats // case 'h': // hour, [1, 12] tokLen = DateTimeUtils.CountRepeat (format, i, ch); int hr = dt.Hour % 12; if (hr == 0) hr = 12; DateTimeUtils.ZeroPad (result, hr, tokLen == 1 ? 1 : 2); break; case 'H': // hour, [0, 23] tokLen = DateTimeUtils.CountRepeat (format, i, ch); DateTimeUtils.ZeroPad (result, dt.Hour, tokLen == 1 ? 1 : 2); break; case 'm': // minute, [0, 59] tokLen = DateTimeUtils.CountRepeat (format, i, ch); DateTimeUtils.ZeroPad (result, dt.Minute, tokLen == 1 ? 1 : 2); break; case 's': // second [0, 29] tokLen = DateTimeUtils.CountRepeat (format, i, ch); DateTimeUtils.ZeroPad (result, dt.Second, tokLen == 1 ? 1 : 2); break; case 'F': omitZeros = true; goto case 'f'; case 'f': // fraction of second, to same number of // digits as there are f's tokLen = DateTimeUtils.CountRepeat (format, i, ch); if (tokLen > 7) throw new FormatException ("Invalid Format String"); int dec = (int)((long)(dt.Ticks % TimeSpan.TicksPerSecond) / (long) Math.Pow (10, 7 - tokLen)); int startLen = result.Length; DateTimeUtils.ZeroPad (result, dec, tokLen); if (omitZeros) { while (result.Length > startLen && result [result.Length - 1] == '0') result.Length--; // when the value was 0, then trim even preceding '.' (!) It is fixed character. if (dec == 0 && startLen > 0 && result [startLen - 1] == '.') result.Length--; } break; case 't': // AM/PM. t == first char, tt+ == full tokLen = DateTimeUtils.CountRepeat (format, i, ch); string desig = dt.Hour < 12 ? dfi.AMDesignator : dfi.PMDesignator; if (tokLen == 1) { if (desig.Length >= 1) result.Append (desig [0]); } else result.Append (desig); break; case 'z': // timezone. t = +/-h; tt = +/-hh; ttt+=+/-hh:mm tokLen = DateTimeUtils.CountRepeat (format, i, ch); TimeSpan offset = utc_offset ?? TimeZone.CurrentTimeZone.GetUtcOffset (dt); if (offset.Ticks >= 0) result.Append ('+'); else result.Append ('-'); switch (tokLen) { case 1: result.Append (Math.Abs (offset.Hours)); break; case 2: result.Append (Math.Abs (offset.Hours).ToString ("00")); break; default: result.Append (Math.Abs (offset.Hours).ToString ("00")); result.Append (':'); result.Append (Math.Abs (offset.Minutes).ToString ("00")); break; } break; case 'K': // 'Z' (UTC) or zzz (Local) tokLen = 1; if (utc_offset != null || dt.Kind == DateTimeKind.Local) { offset = utc_offset ?? TimeZone.CurrentTimeZone.GetUtcOffset (dt); if (offset.Ticks >= 0) result.Append ('+'); else result.Append ('-'); result.Append (Math.Abs (offset.Hours).ToString ("00")); result.Append (':'); result.Append (Math.Abs (offset.Minutes).ToString ("00")); } else if (dt.Kind == DateTimeKind.Utc) result.Append ('Z'); break; // // Date tokens // case 'd': // day. d(d?) = day of month (leading 0 if two d's) // ddd = three leter day of week // dddd+ full day-of-week tokLen = DateTimeUtils.CountRepeat (format, i, ch); if (tokLen <= 2) DateTimeUtils.ZeroPad (result, dfi.Calendar.GetDayOfMonth (dt), tokLen == 1 ? 1 : 2); else if (tokLen == 3) result.Append (dfi.GetAbbreviatedDayName (dfi.Calendar.GetDayOfWeek (dt))); else result.Append (dfi.GetDayName (dfi.Calendar.GetDayOfWeek (dt))); break; case 'M': // Month.m(m?) = month # (with leading 0 if two mm) // mmm = 3 letter name // mmmm+ = full name tokLen = DateTimeUtils.CountRepeat (format, i, ch); int month = dfi.Calendar.GetMonth(dt); if (tokLen <= 2) DateTimeUtils.ZeroPad (result, month, tokLen); else if (tokLen == 3) result.Append (dfi.GetAbbreviatedMonthName (month)); else result.Append (dfi.GetMonthName (month)); break; case 'y': // Year. y(y?) = two digit year, with leading 0 if yy // yyy+ full year with leading zeros if needed. tokLen = DateTimeUtils.CountRepeat (format, i, ch); if (tokLen <= 2) DateTimeUtils.ZeroPad (result, dfi.Calendar.GetYear (dt) % 100, tokLen); else DateTimeUtils.ZeroPad (result, dfi.Calendar.GetYear (dt), tokLen); break; case 'g': // Era name tokLen = DateTimeUtils.CountRepeat (format, i, ch); result.Append (dfi.GetEraName (dfi.Calendar.GetEra (dt))); break; // // Other // case ':': result.Append (dfi.TimeSeparator); tokLen = 1; break; case '/': result.Append (dfi.DateSeparator); tokLen = 1; break; case '\'': case '"': tokLen = DateTimeUtils.ParseQuotedString (format, i, result); break; case '%': if (i >= format.Length - 1) throw new FormatException ("% at end of date time string"); if (format [i + 1] == '%') throw new FormatException ("%% in date string"); // Look for the next char tokLen = 1; break; case '\\': // C-Style escape if (i >= format.Length - 1) throw new FormatException ("\\ at end of date time string"); result.Append (format [i + 1]); tokLen = 2; break; default: // catch all result.Append (ch); tokLen = 1; break; } i += tokLen; } return result.ToString (); }
private static string FormatCustomized(DateTime dateTime, string format, DateTimeFormatInfo dtfi, TimeSpan offset) { int num2; Calendar calendar = dtfi.Calendar; StringBuilder outputBuffer = new StringBuilder(); bool flag = calendar.ID == 8; bool timeOnly = true; for (int i = 0; i < format.Length; i += num2) { int num4; int dayOfMonth; int num8; int month; int year; char patternChar = format[i]; switch (patternChar) { case 'F': case 'f': break; case 'H': { num2 = ParseRepeatPattern(format, i, patternChar); FormatDigits(outputBuffer, dateTime.Hour, num2); continue; } case ':': { outputBuffer.Append(dtfi.TimeSeparator); num2 = 1; continue; } case '/': { outputBuffer.Append(dtfi.DateSeparator); num2 = 1; continue; } case '%': { num4 = ParseNextChar(format, i); if ((num4 < 0) || (num4 == 0x25)) { throw new FormatException(Environment.GetResourceString("Format_InvalidString")); } char ch3 = (char) num4; outputBuffer.Append(FormatCustomized(dateTime, ch3.ToString(), dtfi, offset)); num2 = 2; continue; } case '\'': case '"': { StringBuilder result = new StringBuilder(); num2 = ParseQuoteString(format, i, result); outputBuffer.Append(result); continue; } case 'K': { num2 = 1; FormatCustomizedRoundripTimeZone(dateTime, offset, outputBuffer); continue; } case 'M': num2 = ParseRepeatPattern(format, i, patternChar); month = calendar.GetMonth(dateTime); if (num2 > 2) { goto Label_03D3; } if (!flag) { goto Label_03C7; } HebrewFormatDigits(outputBuffer, month); goto Label_042E; case '\\': { num4 = ParseNextChar(format, i); if (num4 < 0) { throw new FormatException(Environment.GetResourceString("Format_InvalidString")); } outputBuffer.Append((char) num4); num2 = 2; continue; } case 'd': num2 = ParseRepeatPattern(format, i, patternChar); if (num2 > 2) { goto Label_037F; } dayOfMonth = calendar.GetDayOfMonth(dateTime); if (!flag) { goto Label_0373; } HebrewFormatDigits(outputBuffer, dayOfMonth); goto Label_0399; case 'g': { num2 = ParseRepeatPattern(format, i, patternChar); outputBuffer.Append(dtfi.GetEraName(calendar.GetEra(dateTime))); continue; } case 'h': { num2 = ParseRepeatPattern(format, i, patternChar); int num3 = dateTime.Hour % 12; if (num3 == 0) { num3 = 12; } FormatDigits(outputBuffer, num3, num2); continue; } case 's': { num2 = ParseRepeatPattern(format, i, patternChar); FormatDigits(outputBuffer, dateTime.Second, num2); continue; } case 't': { num2 = ParseRepeatPattern(format, i, patternChar); if (num2 != 1) { goto Label_0327; } if (dateTime.Hour >= 12) { goto Label_02FE; } if (dtfi.AMDesignator.Length >= 1) { outputBuffer.Append(dtfi.AMDesignator[0]); } continue; } case 'm': { num2 = ParseRepeatPattern(format, i, patternChar); FormatDigits(outputBuffer, dateTime.Minute, num2); continue; } case 'y': year = calendar.GetYear(dateTime); num2 = ParseRepeatPattern(format, i, patternChar); if (!dtfi.HasForceTwoDigitYears) { goto Label_0466; } FormatDigits(outputBuffer, year, (num2 <= 2) ? num2 : 2); goto Label_04B5; case 'z': { num2 = ParseRepeatPattern(format, i, patternChar); FormatCustomizedTimeZone(dateTime, offset, format, num2, timeOnly, outputBuffer); continue; } default: goto Label_05A4; } num2 = ParseRepeatPattern(format, i, patternChar); if (num2 > 7) { throw new FormatException(Environment.GetResourceString("Format_InvalidString")); } long num5 = dateTime.Ticks % 0x989680L; num5 /= (long) Math.Pow(10.0, (double) (7 - num2)); if (patternChar == 'f') { outputBuffer.Append(((int) num5).ToString(fixedNumberFormats[num2 - 1], CultureInfo.InvariantCulture)); continue; } int num6 = num2; while (num6 > 0) { if ((num5 % 10L) != 0L) { break; } num5 /= 10L; num6--; } if (num6 > 0) { outputBuffer.Append(((int) num5).ToString(fixedNumberFormats[num6 - 1], CultureInfo.InvariantCulture)); } else if ((outputBuffer.Length > 0) && (outputBuffer[outputBuffer.Length - 1] == '.')) { outputBuffer.Remove(outputBuffer.Length - 1, 1); } continue; Label_02FE: if (dtfi.PMDesignator.Length >= 1) { outputBuffer.Append(dtfi.PMDesignator[0]); } continue; Label_0327: outputBuffer.Append((dateTime.Hour < 12) ? dtfi.AMDesignator : dtfi.PMDesignator); continue; Label_0373: FormatDigits(outputBuffer, dayOfMonth, num2); goto Label_0399; Label_037F: num8 = (int) calendar.GetDayOfWeek(dateTime); outputBuffer.Append(FormatDayOfWeek(num8, num2, dtfi)); Label_0399: timeOnly = false; continue; Label_03C7: FormatDigits(outputBuffer, month, num2); goto Label_042E; Label_03D3: if (flag) { outputBuffer.Append(FormatHebrewMonthName(dateTime, month, num2, dtfi)); } else if (((dtfi.FormatFlags & DateTimeFormatFlags.UseGenitiveMonth) != DateTimeFormatFlags.None) && (num2 >= 4)) { outputBuffer.Append(dtfi.internalGetMonthName(month, IsUseGenitiveForm(format, i, num2, 'd') ? MonthNameStyles.Genitive : MonthNameStyles.Regular, false)); } else { outputBuffer.Append(FormatMonth(month, num2, dtfi)); } Label_042E: timeOnly = false; continue; Label_0466: if (calendar.ID == 8) { HebrewFormatDigits(outputBuffer, year); } else if (num2 <= 2) { FormatDigits(outputBuffer, year % 100, num2); } else { string str = "D" + num2; outputBuffer.Append(year.ToString(str, CultureInfo.InvariantCulture)); } Label_04B5: timeOnly = false; continue; Label_05A4: outputBuffer.Append(patternChar); num2 = 1; } return outputBuffer.ToString(); }
public void GetEraName(DateTimeFormatInfo format, int era, string expected) { Assert.Equal(expected, format.GetEraName(era)); }
private static string FormatCustomized(DateTime dateTime, string format, DateTimeFormatInfo dtfi, TimeSpan offset) { Calendar calendar = dtfi.Calendar; StringBuilder stringBuilder = new StringBuilder(); bool flag = calendar.ID == 8; bool timeOnly = true; int i = 0; while (i < format.Length) { char c = format[i]; char c2 = c; int num2; if (c2 <= 'H') { if (c2 <= '\'') { if (c2 != '"') { switch (c2) { case '%': { int num = DateTimeFormat.ParseNextChar(format, i); if (num >= 0 && num != 37) { stringBuilder.Append(DateTimeFormat.FormatCustomized(dateTime, ((char)num).ToString(), dtfi, offset)); num2 = 2; goto IL_5B0; } throw new FormatException(Environment.GetResourceString("Format_InvalidString")); } case '&': { goto IL_5A4; } case '\'': { break; } default: { goto IL_5A4; } } } StringBuilder stringBuilder2 = new StringBuilder(); num2 = DateTimeFormat.ParseQuoteString(format, i, stringBuilder2); stringBuilder.Append(stringBuilder2); } else { if (c2 != '/') { if (c2 != ':') { switch (c2) { case 'F': { goto IL_1BA; } case 'G': { goto IL_5A4; } case 'H': { num2 = DateTimeFormat.ParseRepeatPattern(format, i, c); DateTimeFormat.FormatDigits(stringBuilder, dateTime.Hour, num2); break; } default: { goto IL_5A4; } } } else { stringBuilder.Append(dtfi.TimeSeparator); num2 = 1; } } else { stringBuilder.Append(dtfi.DateSeparator); num2 = 1; } } } else { if (c2 <= 'h') { switch (c2) { case 'K': { num2 = 1; DateTimeFormat.FormatCustomizedRoundripTimeZone(dateTime, offset, stringBuilder); break; } case 'L': { goto IL_5A4; } case 'M': { num2 = DateTimeFormat.ParseRepeatPattern(format, i, c); int month = calendar.GetMonth(dateTime); if (num2 <= 2) { if (flag) { DateTimeFormat.HebrewFormatDigits(stringBuilder, month); } else { DateTimeFormat.FormatDigits(stringBuilder, month, num2); } } else { if (flag) { stringBuilder.Append(DateTimeFormat.FormatHebrewMonthName(dateTime, month, num2, dtfi)); } else { if ((dtfi.FormatFlags & DateTimeFormatFlags.UseGenitiveMonth) != DateTimeFormatFlags.None && num2 >= 4) { stringBuilder.Append(dtfi.internalGetMonthName(month, DateTimeFormat.IsUseGenitiveForm(format, i, num2, 'd') ? MonthNameStyles.Genitive : MonthNameStyles.Regular, false)); } else { stringBuilder.Append(DateTimeFormat.FormatMonth(month, num2, dtfi)); } } } timeOnly = false; break; } default: { if (c2 != '\\') { switch (c2) { case 'd': { num2 = DateTimeFormat.ParseRepeatPattern(format, i, c); if (num2 <= 2) { int dayOfMonth = calendar.GetDayOfMonth(dateTime); if (flag) { DateTimeFormat.HebrewFormatDigits(stringBuilder, dayOfMonth); } else { DateTimeFormat.FormatDigits(stringBuilder, dayOfMonth, num2); } } else { int dayOfWeek = (int)calendar.GetDayOfWeek(dateTime); stringBuilder.Append(DateTimeFormat.FormatDayOfWeek(dayOfWeek, num2, dtfi)); } timeOnly = false; break; } case 'e': { goto IL_5A4; } case 'f': { goto IL_1BA; } case 'g': { num2 = DateTimeFormat.ParseRepeatPattern(format, i, c); stringBuilder.Append(dtfi.GetEraName(calendar.GetEra(dateTime))); break; } case 'h': { num2 = DateTimeFormat.ParseRepeatPattern(format, i, c); int num3 = dateTime.Hour % 12; if (num3 == 0) { num3 = 12; } DateTimeFormat.FormatDigits(stringBuilder, num3, num2); break; } default: { goto IL_5A4; } } } else { int num = DateTimeFormat.ParseNextChar(format, i); if (num < 0) { throw new FormatException(Environment.GetResourceString("Format_InvalidString")); } stringBuilder.Append((char)num); num2 = 2; } break; } } } else { if (c2 != 'm') { switch (c2) { case 's': { num2 = DateTimeFormat.ParseRepeatPattern(format, i, c); DateTimeFormat.FormatDigits(stringBuilder, dateTime.Second, num2); break; } case 't': { num2 = DateTimeFormat.ParseRepeatPattern(format, i, c); if (num2 == 1) { if (dateTime.Hour < 12) { if (dtfi.AMDesignator.Length >= 1) { stringBuilder.Append(dtfi.AMDesignator[0]); } } else { if (dtfi.PMDesignator.Length >= 1) { stringBuilder.Append(dtfi.PMDesignator[0]); } } } else { stringBuilder.Append((dateTime.Hour < 12) ? dtfi.AMDesignator : dtfi.PMDesignator); } break; } default: { switch (c2) { case 'y': { int year = calendar.GetYear(dateTime); num2 = DateTimeFormat.ParseRepeatPattern(format, i, c); if (dtfi.HasForceTwoDigitYears) { DateTimeFormat.FormatDigits(stringBuilder, year, (num2 <= 2) ? num2 : 2); } else { if (calendar.ID == 8) { DateTimeFormat.HebrewFormatDigits(stringBuilder, year); } else { if (num2 <= 2) { DateTimeFormat.FormatDigits(stringBuilder, year % 100, num2); } else { string format2 = "D" + num2; stringBuilder.Append(year.ToString(format2, CultureInfo.InvariantCulture)); } } } timeOnly = false; break; } case 'z': { num2 = DateTimeFormat.ParseRepeatPattern(format, i, c); DateTimeFormat.FormatCustomizedTimeZone(dateTime, offset, format, num2, timeOnly, stringBuilder); break; } default: { goto IL_5A4; } } break; } } } else { num2 = DateTimeFormat.ParseRepeatPattern(format, i, c); DateTimeFormat.FormatDigits(stringBuilder, dateTime.Minute, num2); } } } IL_5B0: i += num2; continue; IL_1BA: num2 = DateTimeFormat.ParseRepeatPattern(format, i, c); if (num2 > 7) { throw new FormatException(Environment.GetResourceString("Format_InvalidString")); } long num4 = dateTime.Ticks % 10000000L; num4 /= (long)Math.Pow(10.0, (double)(7 - num2)); if (c == 'f') { stringBuilder.Append(((int)num4).ToString(DateTimeFormat.fixedNumberFormats[num2 - 1], CultureInfo.InvariantCulture)); goto IL_5B0; } int num5 = num2; while (num5 > 0 && num4 % 10L == 0L) { num4 /= 10L; num5--; } if (num5 > 0) { stringBuilder.Append(((int)num4).ToString(DateTimeFormat.fixedNumberFormats[num5 - 1], CultureInfo.InvariantCulture)); goto IL_5B0; } if (stringBuilder.Length > 0 && stringBuilder[stringBuilder.Length - 1] == '.') { stringBuilder.Remove(stringBuilder.Length - 1, 1); goto IL_5B0; } goto IL_5B0; IL_5A4: stringBuilder.Append(c); num2 = 1; goto IL_5B0; } return stringBuilder.ToString(); }
// Parse an era name. private static int ParseEra(String s, ref int posn, Calendar calendar, DateTimeFormatInfo info) { // Get the list of eras from the calendar. int[] eras = calendar.Eras; // Convert the eras into era names. String[] eraNames = new String [eras.Length]; int index; for(index = 0; index < eras.Length; ++index) { eraNames[index] = info.GetEraName(eras[index]); } // Parse the era value using the strings we just got. return ParseOneOf(s, ref posn, eraNames); }
// // FormatCustomized // // Actions: Format the DateTime instance using the specified format. // private static String FormatCustomized(DateTime dateTime, String format, DateTimeFormatInfo dtfi) { Calendar cal = dtfi.Calendar; StringBuilder result = new StringBuilder(); // This is a flag to indicate if we are format the dates using Hebrew calendar. bool isHebrewCalendar = (cal.ID == Calendar.CAL_HEBREW); // This is a flag to indicate if we are formating hour/minute/second only. bool bTimeOnly = true; int i = 0; int tokenLen, hour12; while (i < format.Length) { char ch = format[i]; int nextChar; switch (ch) { case 'g': tokenLen = ParseRepeatPattern(format, i, ch); result.Append(dtfi.GetEraName(cal.GetEra(dateTime))); break; case 'h': tokenLen = ParseRepeatPattern(format, i, ch); hour12 = dateTime.Hour % 12; if (hour12 == 0) { hour12 = 12; } FormatDigits(result, hour12, tokenLen); break; case 'H': tokenLen = ParseRepeatPattern(format, i, ch); FormatDigits(result, dateTime.Hour, tokenLen); break; case 'm': tokenLen = ParseRepeatPattern(format, i, ch); FormatDigits(result, dateTime.Minute, tokenLen); break; case 's': tokenLen = ParseRepeatPattern(format, i, ch); FormatDigits(result, dateTime.Second, tokenLen); break; case 'f': case 'F': tokenLen = ParseRepeatPattern(format, i, ch); if (tokenLen <= MaxSecondsFractionDigits) { long fraction = (dateTime.Ticks % Calendar.TicksPerSecond); fraction = fraction / (long)Math.Pow(10, 7 - tokenLen); if (ch == 'f') { result.Append(((int)fraction).ToString(fixedNumberFormats[tokenLen - 1], CultureInfo.InvariantCulture)); } else { int effectiveDigits = tokenLen; while (effectiveDigits > 0) { if (fraction % 10 == 0) { fraction = fraction / 10; effectiveDigits--; } else { break; } } if (effectiveDigits > 0) { result.Append(((int)fraction).ToString(fixedNumberFormats[effectiveDigits - 1], CultureInfo.InvariantCulture)); } else { // No fraction to emit, so see if we should remove decimal also. if (result.Length > 0 && result[result.Length - 1] == '.') { result.Remove(result.Length - 1, 1); } } } } else { throw new FormatException(Environment.GetResourceString("Format_InvalidString")); } break; case 't': tokenLen = ParseRepeatPattern(format, i, ch); if (tokenLen == 1) { if (dateTime.Hour < 12) { if (dtfi.AMDesignator.Length >= 1) { result.Append(dtfi.AMDesignator[0]); } } else { if (dtfi.PMDesignator.Length >= 1) { result.Append(dtfi.PMDesignator[0]); } } } else { result.Append((dateTime.Hour < 12 ? dtfi.AMDesignator : dtfi.PMDesignator)); } break; case 'd': // // tokenLen == 1 : Day of month as digits with no leading zero. // tokenLen == 2 : Day of month as digits with leading zero for single-digit months. // tokenLen == 3 : Day of week as a three-leter abbreviation. // tokenLen >= 4 : Day of week as its full name. // tokenLen = ParseRepeatPattern(format, i, ch); if (tokenLen <= 2) { int day = cal.GetDayOfMonth(dateTime); if (isHebrewCalendar) { // For Hebrew calendar, we need to convert numbers to Hebrew text for yyyy, MM, and dd values. HebrewFormatDigits(result, day); } else { FormatDigits(result, day, tokenLen); } } else { int dayOfWeek = (int)cal.GetDayOfWeek(dateTime); result.Append(FormatDayOfWeek(dayOfWeek, tokenLen, dtfi)); } bTimeOnly = false; break; case 'M': // // tokenLen == 1 : Month as digits with no leading zero. // tokenLen == 2 : Month as digits with leading zero for single-digit months. // tokenLen == 3 : Month as a three-letter abbreviation. // tokenLen >= 4 : Month as its full name. // tokenLen = ParseRepeatPattern(format, i, ch); int month = cal.GetMonth(dateTime); if (tokenLen <= 2) { if (isHebrewCalendar) { // For Hebrew calendar, we need to convert numbers to Hebrew text for yyyy, MM, and dd values. HebrewFormatDigits(result, month); } else { FormatDigits(result, month, tokenLen); } } else { if (isHebrewCalendar) { result.Append(FormatHebrewMonthName(dateTime, month, tokenLen, dtfi)); } else { if ((dtfi.FormatFlags & DateTimeFormatFlags.UseGenitiveMonth) != 0 && tokenLen >= 4) { result.Append( dtfi.internalGetMonthName( month, IsUseGenitiveForm(format, i, tokenLen, 'd')? MonthNameStyles.Genitive : MonthNameStyles.Regular, false)); } else { result.Append(FormatMonth(month, tokenLen, dtfi)); } } } bTimeOnly = false; break; case 'y': // Notes about OS behavior: // y: Always print (year % 100). No leading zero. // yy: Always print (year % 100) with leading zero. // yyy/yyyy/yyyyy/... : Print year value. No leading zero. int year = cal.GetYear(dateTime); tokenLen = ParseRepeatPattern(format, i, ch); if (dtfi.HasForceTwoDigitYears) { FormatDigits(result, year, tokenLen <= 2 ? tokenLen : 2); } else if (cal.ID == Calendar.CAL_HEBREW) { HebrewFormatDigits(result, year); } else { if (tokenLen <= 2) { FormatDigits(result, year % 100, tokenLen); } else { String fmtPattern = "D" + tokenLen; result.Append(year.ToString(fmtPattern, CultureInfo.InvariantCulture)); } } bTimeOnly = false; break; case 'z': // // Output the offset of the timezone according to the system timezone setting. // tokenLen = ParseRepeatPattern(format, i, ch); TimeSpan offset; if (bTimeOnly && dateTime.Ticks < Calendar.TicksPerDay) { offset = TimeZone.CurrentTimeZone.GetUtcOffset(DateTime.Now); } else { if (dateTime.Kind == DateTimeKind.Utc) { InvalidFormatForUtc(format, dateTime); offset = TimeZone.CurrentTimeZone.GetUtcOffset(DateTime.SpecifyKind(dateTime, DateTimeKind.Local)); } else { offset = TimeZone.CurrentTimeZone.GetUtcOffset(dateTime); } } switch (tokenLen) { case 1: result.Append((offset.Hours).ToString("+0;-0", CultureInfo.InvariantCulture)); break; case 2: result.Append((offset.Hours).ToString("+00;-00", CultureInfo.InvariantCulture)); break; default: if (offset.Ticks >= 0) { result.Append(String.Format(CultureInfo.InvariantCulture, "+{0:00}:{1:00}", offset.Hours, offset.Minutes)); } else { // When the offset is negative, note that the offset.Minute is also negative. // So use should use -offset.Minute to get the postive value. result.Append(String.Format(CultureInfo.InvariantCulture, "-{0:00}:{1:00}", -offset.Hours, -offset.Minutes)); } break; } break; case 'K': tokenLen = 1; // The objective of this format is to round trip the Kind value and preserve the time zone switch (dateTime.Kind) { case DateTimeKind.Local: // This should output the local offset, e.g. "-07:00" TimeSpan localOffset = TimeZone.CurrentTimeZone.GetUtcOffset(dateTime); if (localOffset.Ticks >= 0) { result.Append(String.Format(CultureInfo.InvariantCulture, "+{0:00}:{1:00}", localOffset.Hours, localOffset.Minutes)); } else { // When the offset is negative, note that the localOffset.Minute is also negative. // So use should use -localOffset.Minute to get the postive value. result.Append(String.Format(CultureInfo.InvariantCulture, "-{0:00}:{1:00}", -localOffset.Hours, -localOffset.Minutes)); } break; case DateTimeKind.Utc: // The 'Z' constant is a marker for a UTC date result.Append("Z"); break; default: // If the kind is unspecified, we output nothing here break; } break; case ':': result.Append(dtfi.TimeSeparator); tokenLen = 1; break; case '/': result.Append(dtfi.DateSeparator); tokenLen = 1; break; case '\'': case '\"': StringBuilder enquotedString = new StringBuilder(); tokenLen = ParseQuoteString(format, i, enquotedString); result.Append(enquotedString); break; case '%': // Optional format character. // For example, format string "%d" will print day of month // without leading zero. Most of the cases, "%" can be ignored. nextChar = ParseNextChar(format, i); // nextChar will be -1 if we already reach the end of the format string. // Besides, we will not allow "%%" appear in the pattern. if (nextChar >= 0 && nextChar != (int)'%') { result.Append(FormatCustomized(dateTime, ((char)nextChar).ToString(), dtfi)); tokenLen = 2; } else { // // This means that '%' is at the end of the format string or // "%%" appears in the format string. // throw new FormatException(Environment.GetResourceString("Format_InvalidString")); } break; case '\\': // nextChar = ParseNextChar(format, i); if (nextChar >= 0) { result.Append(((char)nextChar)); tokenLen = 2; } else { // // This means that '\' is at the end of the formatting string. // throw new FormatException(Environment.GetResourceString("Format_InvalidString")); } break; default: result.Append(ch); tokenLen = 1; break; } i += tokenLen; } return (result.ToString()); }
/*=================================MatchEraName================================== **Action: Parse era name from string starting at str.Index. **Returns: An era value. **Arguments: str: a __DTString. The parsing will start from the ** next character after str.Index. **Exceptions: FormatException if an era name can not be found. ==============================================================================*/ private static bool MatchEraName(__DTString str, DateTimeFormatInfo dtfi, bool isThrowExp, ref int result) { if (str.GetNext()) { int[] eras = dtfi.Calendar.Eras; if (eras != null) { for (int i = 0; i <= eras.Length; i++) { String searchStr = dtfi.GetEraName(eras[i]); if (str.MatchSpecifiedWord(searchStr)) { str.Index += (searchStr.Length - 1); result = eras[i]; return (true); } searchStr = dtfi.GetAbbreviatedEraName(eras[i]); if (str.MatchSpecifiedWord(searchStr)) { str.Index += (searchStr.Length - 1); result = eras[i]; return (true); } } } } return (ParseFormatError(isThrowExp, "Format_BadDateTime")); }
private static String FormatCustomized(DateTime dateTime, String format, DateTimeFormatInfo dtfi) { Calendar cal = dtfi.Calendar; StringBuilder result = new StringBuilder(); // This is a flag to indicate if we are format the dates using Hebrew calendar. bool isHebrewCalendar = (cal.ID == Calendar.CAL_HEBREW); // This is a flag to indicate if we are formating hour/minute/second only. bool bTimeOnly = true; int i = 0; int tokenLen, hour12; while (i < format.Length) { char ch = format[i]; int nextChar; switch (ch) { case 'g': tokenLen = ParseRepeatPattern(format, i, ch); result.Append(dtfi.GetEraName(cal.GetEra(dateTime))); break; case 'h': tokenLen = ParseRepeatPattern(format, i, ch); hour12 = dateTime.Hour % 12; if (hour12 == 0) { hour12 = 12; } FormatDigits(result, hour12, tokenLen); break; case 'H': tokenLen = ParseRepeatPattern(format, i, ch); FormatDigits(result, dateTime.Hour, tokenLen); break; case 'm': tokenLen = ParseRepeatPattern(format, i, ch); FormatDigits(result, dateTime.Minute, tokenLen); break; case 's': tokenLen = ParseRepeatPattern(format, i, ch); FormatDigits(result, dateTime.Second, tokenLen); break; case 'f': tokenLen = ParseRepeatPattern(format, i, ch); if (tokenLen <= MaxSecondsFractionDigits) { long fraction = (dateTime.Ticks % Calendar.TicksPerSecond); fraction = fraction / (long)Math.Pow(10, 7 - tokenLen); result.Append(((int)fraction).ToString((new String('0', tokenLen)))); } else { throw new FormatException(Environment.GetResourceString("Format_InvalidString")); } break; case 't': tokenLen = ParseRepeatPattern(format, i, ch); if (tokenLen == 1) { if (dateTime.Hour < 12) { if (dtfi.AMDesignator.Length >= 1) { result.Append(dtfi.AMDesignator[0]); } } else { if (dtfi.PMDesignator.Length >= 1) { result.Append(dtfi.PMDesignator[0]); } } } else { result.Append((dateTime.Hour < 12 ? dtfi.AMDesignator : dtfi.PMDesignator)); } break; case 'd': // // tokenLen == 1 : Day of month as digits with no leading zero. // tokenLen == 2 : Day of month as digits with leading zero for single-digit months. // tokenLen == 3 : Day of week as a three-leter abbreviation. // tokenLen >= 4 : Day of week as its full name. // tokenLen = ParseRepeatPattern(format, i, ch); if (tokenLen <= 2) { int day = cal.GetDayOfMonth(dateTime); if (isHebrewCalendar) { // For Hebrew calendar, we need to convert numbers to Hebrew text for yyyy, MM, and dd values. HebrewFormatDigits(result, day); } else { FormatDigits(result, day, tokenLen); } } else { int dayOfWeek = (int)cal.GetDayOfWeek(dateTime); result.Append(FormatDayOfWeek(dayOfWeek, tokenLen, dtfi)); } bTimeOnly = false; break; case 'M': // // tokenLen == 1 : Month as digits with no leading zero. // tokenLen == 2 : Month as digits with leading zero for single-digit months. // tokenLen == 3 : Month as a three-letter abbreviation. // tokenLen >= 4 : Month as its full name. // tokenLen = ParseRepeatPattern(format, i, ch); int month = cal.GetMonth(dateTime); if (tokenLen <= 2) { if (isHebrewCalendar) { // For Hebrew calendar, we need to convert numbers to Hebrew text for yyyy, MM, and dd values. HebrewFormatDigits(result, month); } else { FormatDigits(result, month, tokenLen); } } else { if (isHebrewCalendar) { result.Append(FormatHebrewMonthName(dateTime, month, tokenLen, dtfi)); } else { result.Append(FormatMonth(month, tokenLen, dtfi)); } } bTimeOnly = false; break; case 'y': int year = cal.GetYear(dateTime); tokenLen = ParseRepeatPattern(format, i, ch); switch (cal.ID) { // Add a special case for Japanese. // For Japanese calendar, always use two digit (with leading 0) case (Calendar.CAL_JAPAN): FormatDigits(result, year, 2); break; case (Calendar.CAL_HEBREW): HebrewFormatDigits(result, year); break; default: if (tokenLen <= 2) { FormatDigits(result, year % 100, tokenLen); } else { String fmtPattern = "D" + tokenLen; result.Append(year.ToString(fmtPattern)); } break; } bTimeOnly = false; break; case 'z': // // Output the offset of the timezone according to the system timezone setting. // tokenLen = ParseRepeatPattern(format, i, ch); TimeSpan offset; if (bTimeOnly && dateTime.Ticks < Calendar.TicksPerDay) { offset = TimeZone.CurrentTimeZone.GetUtcOffset(DateTime.Now); } else { offset = TimeZone.CurrentTimeZone.GetUtcOffset(dateTime); } switch (tokenLen) { case 1: result.Append((offset.Hours).ToString("+0;-0")); break; case 2: result.Append((offset.Hours).ToString("+00;-00")); break; default: if (offset.Hours > 0) { result.Append(String.Format("+{0:00}:{1:00}", offset.Hours, offset.Minutes)); } else { // When the offset is negative, note that the offset.Minute is also negative. // So use should use -offset.Minute to get the postive value. result.Append(String.Format("-{0:00}:{1:00}", -offset.Hours, -offset.Minutes)); } break; } break; case ':': result.Append(dtfi.TimeSeparator); tokenLen = 1; break; case '/': result.Append(dtfi.DateSeparator); tokenLen = 1; break; case '\'': case '\"': StringBuilder enquotedString = new StringBuilder(); tokenLen = ParseQuoteString(format, i, enquotedString); result.Append(enquotedString); break; case '%': // Optional format character. // For example, format string "%d" will print day of month // without leading zero. Most of the cases, "%" can be ignored. nextChar = ParseNextChar(format, i); // nextChar will be -1 if we already reach the end of the format string. // Besides, we will not allow "%%" appear in the pattern. if (nextChar >= 0 && nextChar != (int)'%') { result.Append(FormatCustomized(dateTime, ((char)nextChar).ToString(), dtfi)); tokenLen = 2; } else { // // This means that '%' is at the end of the format string or // "%%" appears in the format string. // throw new FormatException(Environment.GetResourceString("Format_InvalidString")); } break; case '\\': // Escaped character. Can be used to insert character into the format string. // For exmple, "\d" will insert the character 'd' into the string. // // NOTENOTE : we can remove this format character if we enforce the enforced quote // character rule. // That is, we ask everyone to use single quote or double quote to insert characters, // then we can remove this character. // nextChar = ParseNextChar(format, i); if (nextChar >= 0) { result.Append(((char)nextChar)); tokenLen = 2; } else { // // This means that '\' is at the end of the formatting string. // throw new FormatException(Environment.GetResourceString("Format_InvalidString")); } break; default: // NOTENOTE : we can remove this rule if we enforce the enforced quote // character rule. // That is, if we ask everyone to use single quote or double quote to insert characters, // then we can remove this default block. result.Append(ch); tokenLen = 1; break; } i += tokenLen; } return (result.ToString()); }