public static bool TryConvert(object value, bool isDate1904, CultureInfo culture, out ExcelDateTime result) { if (value is double doubleValue) { result = new ExcelDateTime(doubleValue, isDate1904); return(true); } if (value is int intValue) { result = new ExcelDateTime(intValue, isDate1904); return(true); } if (value is short shortValue) { result = new ExcelDateTime(shortValue, isDate1904); return(true); } else if (value is DateTime dateTimeValue) { result = new ExcelDateTime(dateTimeValue); return(true); } result = null; return(false); }
static public string Format(object value, Section node, CultureInfo culture, bool isDate1904) { switch (node.Type) { case SectionType.Number: // Hide sign under certain conditions and section index var number = Convert.ToDouble(value, culture); if ((node.SectionIndex == 0 && node.Condition != null) || node.SectionIndex == 1) { number = Math.Abs(number); } return(FormatNumber(number, node.Number, culture)); case SectionType.Date: if (ExcelDateTime.TryConvert(value, isDate1904, culture, out var excelDateTime)) { return(FormatDate(excelDateTime, node.GeneralTextDateDurationParts, culture)); } else { throw new FormatException("Unexpected date value"); } case SectionType.Duration: if (value is TimeSpan ts) { return(FormatTimeSpan(ts, node.GeneralTextDateDurationParts, culture)); } else { var d = Convert.ToDouble(value); return(FormatTimeSpan(TimeSpan.FromDays(d), node.GeneralTextDateDurationParts, culture)); } case SectionType.General: case SectionType.Text: return(FormatGeneralText(CompatibleConvert.ToString(value, culture), node.GeneralTextDateDurationParts)); case SectionType.Exponential: return(FormatExponential(Convert.ToDouble(value, culture), node, culture)); case SectionType.Fraction: return(FormatFraction(Convert.ToDouble(value, culture), node, culture)); default: throw new InvalidOperationException("Unknown number format section"); } }
private static string FormatDate(ExcelDateTime date, List <string> tokens, CultureInfo culture) { var containsAmPm = ContainsAmPm(tokens); var result = new StringBuilder(); for (var i = 0; i < tokens.Count; i++) { var token = tokens[i]; if (token.StartsWith("y", StringComparison.OrdinalIgnoreCase)) { // year var digits = token.Length; if (digits < 2) { digits = 2; } if (digits == 3) { digits = 4; } var year = date.Year; if (digits == 2) { year = year % 100; } result.Append(year.ToString("D" + digits)); } else if (token.StartsWith("m", StringComparison.OrdinalIgnoreCase)) { // If "m" or "mm" code is used immediately after the "h" or "hh" code (for hours) or immediately before // the "ss" code (for seconds), the application shall display minutes instead of the month. if (LookBackDatePart(tokens, i - 1, "h") || LookAheadDatePart(tokens, i + 1, "s")) { var digits = token.Length; result.Append(date.Minute.ToString("D" + digits)); } else { var digits = token.Length; if (digits == 3) { result.Append(culture.DateTimeFormat.AbbreviatedMonthNames[date.Month - 1]); } else if (digits == 4) { result.Append(culture.DateTimeFormat.MonthNames[date.Month - 1]); } else if (digits == 5) { result.Append(culture.DateTimeFormat.MonthNames[date.Month - 1][0]); } else { result.Append(date.Month.ToString("D" + digits)); } } } else if (token.StartsWith("d", StringComparison.OrdinalIgnoreCase)) { var digits = token.Length; if (digits == 3) { // Sun-Sat result.Append(culture.DateTimeFormat.AbbreviatedDayNames[(int)date.DayOfWeek]); } else if (digits == 4) { // Sunday-Saturday result.Append(culture.DateTimeFormat.DayNames[(int)date.DayOfWeek]); } else { result.Append(date.Day.ToString("D" + digits)); } } else if (token.StartsWith("h", StringComparison.OrdinalIgnoreCase)) { var digits = token.Length; if (containsAmPm) { result.Append(((date.Hour + 11) % 12 + 1).ToString("D" + digits)); } else { result.Append(date.Hour.ToString("D" + digits)); } } else if (token.StartsWith("s", StringComparison.OrdinalIgnoreCase)) { var digits = token.Length; result.Append(date.Second.ToString("D" + digits)); } else if (token.StartsWith("g", StringComparison.OrdinalIgnoreCase)) { var era = culture.DateTimeFormat.Calendar.GetEra(date.AdjustedDateTime); var digits = token.Length; if (digits < 3) { result.Append(culture.DateTimeFormat.GetAbbreviatedEraName(era)); } else { result.Append(culture.DateTimeFormat.GetEraName(era)); } } else if (string.Compare(token, "am/pm", StringComparison.OrdinalIgnoreCase) == 0) { var ampm = date.ToString("tt", CultureInfo.InvariantCulture); result.Append(ampm.ToUpperInvariant()); } else if (string.Compare(token, "a/p", StringComparison.OrdinalIgnoreCase) == 0) { var ampm = date.ToString("%t", CultureInfo.InvariantCulture); if (char.IsUpper(token[0])) { result.Append(ampm.ToUpperInvariant()); } else { result.Append(ampm.ToLowerInvariant()); } } else if (token.StartsWith(".0")) { var value = date.Millisecond; var digits = token.Length - 1; result.Append("." + value.ToString("D" + digits)); } else if (token == "/") { #if NETSTANDARD1_0 result.Append(DateTime.MaxValue.ToString("/d", culture)[0]); #else result.Append(culture.DateTimeFormat.DateSeparator); #endif } else if (token == ",") { while (i < tokens.Count - 1 && tokens[i + 1] == ",") { i++; } result.Append(","); } else { FormatLiteral(token, result); } } return(result.ToString()); }