/// <summary> /// Converts a vague date composed of separate start and end date strings into a timespan in days since 30/12/1899. /// </summary> /// <param name="startDateString">Start date string.</param> /// <param name="endDateString">End date string.</param> /// <param name="dateType">Two-letter date format code as generated by the GetFormat method.</param> /// <param name="outputFormat">One of the output formats in the HLU.Date.DateType enumeration.</param> /// <returns></returns> public static int ToTimeSpanDays(string startDateString, string endDateString, string dateType, DateType outputFormat) { if (String.IsNullOrEmpty(dateType) || (dateType == VagueDate.ToCode(VagueDateTypes.Unknown))) { return(DateUnknown); } try { DateTimeFormatInfo dtFormatInfo = CultureInfo.CurrentCulture.DateTimeFormat; DateTime startDate; bool startDateOk = DateTime.TryParse(startDateString, dtFormatInfo, DateTimeStyles.AllowWhiteSpaces | DateTimeStyles.AssumeLocal | DateTimeStyles.NoCurrentDateDefault, out startDate); DateTime endDate; bool endDateOk = DateTime.TryParse(endDateString, dtFormatInfo, DateTimeStyles.AllowWhiteSpaces | DateTimeStyles.AssumeLocal | DateTimeStyles.NoCurrentDateDefault, out endDate); int year; string formatString = String.Empty; switch (outputFormat) { case DateType.Start: if (dateType.Length > 0) { formatString = dateType.Substring(0, 1); } switch (VagueDate.FromCode(formatString)) { case VagueDateTypes.StartDate: // "D" if (startDateOk) { return(startDate.Subtract(BaseDate).Days); } break; case VagueDateTypes.StartMonthAndYear: // "O" if (startDateOk) { return(startDate.Subtract(BaseDate).Days); } break; case VagueDateTypes.Year: // "Y" if (startDateOk) { return(new DateTime(startDate.Year, 1, 1).Subtract(BaseDate).Days); } else if (Int32.TryParse(startDateString, out year)) { return(new DateTime(year, 1, 1).Subtract(BaseDate).Days); } break; case VagueDateTypes.Season: // "P" if (!String.IsNullOrEmpty(startDateString)) { string[] splitArray = Regex.Split(startDateString, @"\s+"); if ((splitArray.Length != 2) || !Int32.TryParse(splitArray[1], out year)) { return(DateUnknown); // 9999; } var q = SeasonNames.Where(s => s.ToLower() == splitArray[0].ToLower()); if (q.Count() > 0) { string season = q.ElementAt(0); int seasonIx = System.Array.IndexOf(SeasonNames, season); if (seasonIx != -1) { return(SeasonStart(splitArray[0], year).Subtract(BaseDate).Days); } } } break; case VagueDateTypes.Unknown: // "U" default: return(DateUnknown); } break; case DateType.End: if (dateType.Length > 1) { formatString = dateType.Substring(dateType.Length - 1, 1); } switch (VagueDate.FromCode(formatString)) { case VagueDateTypes.StartDate: // "D" if (endDateOk) { return(endDate.Subtract(BaseDate).Days); } break; case VagueDateTypes.StartMonthAndYear: // "O" if (endDateOk) { return(endDate.Subtract(BaseDate).Days); } break; case VagueDateTypes.Year: // "Y" if (endDateOk) { return(new DateTime(endDate.Year, 1, 1).Subtract(BaseDate).Days); } else if (Int32.TryParse(endDateString, out year)) { return(new DateTime(year, 1, 1).Subtract(BaseDate).Days); } break; case VagueDateTypes.Season: // "P" if (!String.IsNullOrEmpty(endDateString)) { string[] splitArray = Regex.Split(endDateString, @"\s+"); if ((splitArray.Length != 2) || !Int32.TryParse(splitArray[1], out year)) { return(DateUnknown); // 9999; } var q = SeasonNames.Where(s => s.ToLower() == splitArray[0].ToLower()); if (q.Count() > 0) { string season = q.ElementAt(0); int seasonIx = System.Array.IndexOf(SeasonNames, season); return(SeasonEnd(season, year).Subtract(BaseDate).Days); } } break; case VagueDateTypes.Unknown: // "U" default: return(DateUnknown); } break; } } catch { } return(DateUnknown); // 9999 }
/// <summary> /// Reads one portion, either start or end, of an unformatted vague date string (i.e. after splitting). /// </summary> /// <param name="dateString">Start or end portion of a vague date string.</param> /// <param name="endYear">A single integer could be both a year or a month, /// and the start part of date ranges may not include the year, the end date part /// of a vague date string is read first and the year found is passed into this method.</param> /// <param name="formattedDate">Formatted version of userDateString.</param> /// <returns>Single letter format string for one portion of a vague date.</returns> private static string ReadDateString(string dateString, string endYear, out string formattedDate) { formattedDate = dateString; try { if (String.IsNullOrEmpty(dateString)) { return(String.Empty); } if (dateString.ToLower() == "unknown") { return(VagueDateTypes.Unknown.ToString()); } DateTimeFormatInfo dtFormatInfo = CultureInfo.CurrentCulture.DateTimeFormat; string[] splitArray = Regex.Split(dateString, @"[\s+" + dtFormatInfo.DateSeparator + "]"); int year = Int32.MinValue; int month = Int32.MinValue; string currYear = String.IsNullOrEmpty(endYear) ? DateTime.Now.Year.ToString() : endYear; string userYear; switch (splitArray.Length) { case 1: if (Int32.TryParse(splitArray[0], out year)) { if (String.IsNullOrEmpty(endYear) || (year > 12) || (year < 0)) { // year ("2007" or "7") formattedDate = new DateTime(year, 1, 1).Year.ToString(); return(VagueDate.ToCode(VagueDateTypes.Year)); // "Y"; } else { // first part of a month range ("1-3/7") formattedDate = String.Format("{0} {1}", dtFormatInfo.MonthNames[year - 1], endYear); return(VagueDate.ToCode(VagueDateTypes.StartMonthAndYear)); // "O"; } } else if (dtFormatInfo.MonthNames.Count(s => s.ToLower() == splitArray[0].ToLower()) == 1) { // full month ("January") formattedDate = String.Format("{0} {1}", dtFormatInfo.MonthNames.Single(s => s.ToLower() == splitArray[0].ToLower()), currYear); return(VagueDate.ToCode(VagueDateTypes.StartMonthAndYear)); // "O"; } else if (dtFormatInfo.AbbreviatedMonthNames.Count(s => s.ToLower() == splitArray[0].ToLower()) == 1) { // abbreviated month ("Jan") formattedDate = String.Format("{0} {1}", dtFormatInfo.MonthNames[System.Array.IndexOf( dtFormatInfo.AbbreviatedMonthNames, dtFormatInfo.AbbreviatedMonthNames.Single( s => s.ToLower() == splitArray[0].ToLower()))], currYear); return(VagueDate.ToCode(VagueDateTypes.StartMonthAndYear)); // "O"; } else if (SeasonNames.Count(s => s.ToLower() == splitArray[0].ToLower()) == 1) { // season formattedDate = String.Format("{0} {1}", SeasonNames.Single(s => s.ToLower() == splitArray[0].ToLower()), currYear); return(VagueDate.ToCode(VagueDateTypes.Season)); // "P"; } break; case 2: if (!Int32.TryParse(splitArray[1], out year)) { throw new ArgumentException("Invalid date string.", "userDateString"); } userYear = new DateTime(year, 1, 1).Year.ToString(); if (Int32.TryParse(splitArray[0], out month)) { formattedDate = String.Format("{0} {1}", dtFormatInfo.MonthNames[month - 1], userYear); return(VagueDate.ToCode(VagueDateTypes.StartMonthAndYear)); // "O"; } else if (dtFormatInfo.MonthNames.Count(s => s.ToLower() == splitArray[0].ToLower()) == 1) { // full month and year ("January 2007") formattedDate = String.Format("{0} {1}", dtFormatInfo.MonthNames.Single(s => s.ToLower() == splitArray[0].ToLower()), userYear); return(VagueDate.ToCode(VagueDateTypes.StartMonthAndYear)); // "O"; } else if (dtFormatInfo.AbbreviatedMonthNames.Count(s => s.ToLower() == splitArray[0].ToLower()) == 1) { // abbreviated month and year("Jan 2007") formattedDate = String.Format("{0} {1}", dtFormatInfo.MonthNames[System.Array.IndexOf( dtFormatInfo.AbbreviatedMonthNames, dtFormatInfo.AbbreviatedMonthNames.Single( s => s.ToLower() == splitArray[0].ToLower()))], userYear); return(VagueDate.ToCode(VagueDateTypes.StartMonthAndYear)); // "O"; } else if (SeasonNames.Count(s => s.ToLower() == splitArray[0].ToLower()) == 1) { // season formattedDate = String.Format("{0} {1}", SeasonNames.Single(s => s.ToLower() == splitArray[0].ToLower()), userYear); return(VagueDate.ToCode(VagueDateTypes.Season)); // "P"; } break; } DateTime testDate; if (DateTime.TryParse(dateString, dtFormatInfo, DateTimeStyles.AllowWhiteSpaces | DateTimeStyles.AssumeLocal | DateTimeStyles.NoCurrentDateDefault, out testDate) && (testDate.Year != 1)) { return(VagueDate.ToCode(VagueDateTypes.StartDate)); // "D" // normal date } } catch { } return(String.Empty); }
/// <summary> /// Creates a vague date string of a specified format from start and end dates. /// </summary> /// <param name="startDate">Start date.</param> /// <param name="endDate">End date.</param> /// <param name="dateType">Two-letter date format code as generated by the GetFormat method.</param> /// <param name="outputFormat">One of the output formats in the HLU.Date.DateType enumeration.</param> /// <returns>A vague date string in the format specified in the dateType parameter.</returns> public static string FromDate(DateTime startDate, DateTime endDate, string dateType, DateType outputFormat) { if (String.IsNullOrEmpty(dateType) || (dateType == VagueDate.ToCode(VagueDateTypes.Unknown))) { return(VagueDateTypes.Unknown.ToString()); } try { DateTimeFormatInfo dtFormatInfo = CultureInfo.CurrentCulture.DateTimeFormat; string formatString = String.Empty; switch (outputFormat) { case DateType.Start: if (dateType.Length > 0) { formatString = dateType.Substring(0, 1); } switch (VagueDate.FromCode(formatString)) { case VagueDateTypes.StartDate: // "D" return(startDate.ToShortDateString()); case VagueDateTypes.StartMonthAndYear: // "O" return(String.Format("{0} {1}", dtFormatInfo.MonthNames[startDate.Month - 1], startDate.Year)); case VagueDateTypes.Year: // "Y" return(startDate.Year.ToString()); case VagueDateTypes.Season: // "P" return(String.Format("{0}{1}", SeasonString(startDate), Delimiter)); case VagueDateTypes.Unknown: // "U" return(VagueDateTypes.Unknown.ToString()); } break; case DateType.End: if (dateType.Length > 1) { formatString = dateType.Substring(dateType.Length - 1, 1); } switch (VagueDate.FromCode(formatString)) { case VagueDateTypes.StartDate: // "D" return(endDate.ToShortDateString()); case VagueDateTypes.StartMonthAndYear: // "O" return(String.Format("{0} {1}", dtFormatInfo.MonthNames[endDate.Month - 1], endDate.Year)); case VagueDateTypes.Year: // "Y" return(endDate.Year.ToString()); case VagueDateTypes.Season: // "P" return(String.Format("{0}{1}", Delimiter, SeasonString(endDate))); case VagueDateTypes.Unknown: // "U" return(VagueDateTypes.Unknown.ToString()); } break; case DateType.Vague: if (dateType.Length > 0) { formatString = dateType.Substring(0, 1); } StringBuilder returnString = new StringBuilder(); switch (VagueDate.FromCode(formatString)) { case VagueDateTypes.StartDate: // "D" returnString.Append(startDate.ToShortDateString()); break; case VagueDateTypes.StartMonthAndYear: // "O" returnString.Append(String.Format("{0} {1}", dtFormatInfo.MonthNames[startDate.Month - 1], startDate.Year)); break; case VagueDateTypes.Year: // "Y" returnString.Append(startDate.Year.ToString()); break; case VagueDateTypes.Season: // "P" returnString.Append(SeasonString(startDate)); break; case VagueDateTypes.Unknown: // "U" break; } if ((endDate == startDate) || (dateType.Length < 2)) { return(returnString.ToString()); } formatString = dateType.Substring(dateType.Length - 1, 1); switch (VagueDate.FromCode(formatString)) { case VagueDateTypes.StartDate: // "D" return(returnString.Append(Delimiter).Append(endDate.ToShortDateString()).ToString()); case VagueDateTypes.StartMonthAndYear: // "O" return(returnString.Append(Delimiter).Append(String.Format("{0} {1}", dtFormatInfo.MonthNames[endDate.Month - 1], endDate.Year)).ToString()); case VagueDateTypes.Year: // "Y" return(returnString.Append(Delimiter).Append(endDate.Year).ToString()); case VagueDateTypes.Season: // "P" return(returnString.Append(Delimiter).Append(SeasonString(endDate)).ToString()); case VagueDateTypes.Unknown: // "U" if (returnString.Length == 0) { return(VagueDateTypes.Unknown.ToString()); } else { return(returnString.Append(Delimiter).ToString()); } } break; } } catch { } return(VagueDateTypes.Unknown.ToString()); }
/// <summary> /// Determines the format of a vague date string and standardizes its format. /// </summary> /// <param name="userDateString">Date string to be </param> /// <param name="formattedDate">Formatted version of userDateString.</param> /// <returns>Format string that describes the format of the date passed in: /// "D": start date /// "DD": start date + end date /// "D-": start date range /// "-D": end date range /// "O": start month and year /// "OO": start month and year + end month and year /// "O-": start month range /// "-O": end month range /// "Y": year /// "YY": start year + end year /// "Y-": start year range /// "-Y": end year range /// "P": season /// "PP": start season + end season /// "P-": start season range /// "-P": end season range /// "U": unknown /// An empty string is returned if userDateString is null or empty. Unknown if an error occurs. /// </returns> public static string GetType(string userDateString, out string formattedDate) { formattedDate = userDateString; if (String.IsNullOrEmpty(userDateString)) { return(String.Empty); } string startDateString; string endDateString; SplitDateString(userDateString, out startDateString, out endDateString); string formatString1 = String.Empty; if (String.IsNullOrEmpty(endDateString)) { if (IsUnknownDate(startDateString)) { formattedDate = VagueDateTypes.Unknown.ToString(); return(VagueDate.ToCode(VagueDateTypes.Unknown)); } else { return(ReadDateString(startDateString, String.Empty, out formattedDate)); } } else { string formatString2 = ReadDateString(endDateString, String.Empty, out endDateString); string endYearStr = String.Empty; int endYear = -1; if ((endDateString.Length >= 4) && Int32.TryParse(endDateString.Substring(endDateString.Length - 4, 4), out endYear)) { endYearStr = endYear.ToString(); } formatString1 = ReadDateString(startDateString, endYearStr, out startDateString); if ((formatString1 == VagueDate.ToCode(VagueDateTypes.Unknown)) && (formatString2 != VagueDate.ToCode(VagueDateTypes.Unknown))) { formatString1 = String.Empty; } else if ((formatString1 != VagueDate.ToCode(VagueDateTypes.Unknown)) && (formatString2 == VagueDate.ToCode(VagueDateTypes.Unknown))) { formatString2 = String.Empty; } if ((formatString1 == VagueDate.ToCode(VagueDateTypes.Unknown)) && (formatString2 == VagueDate.ToCode(VagueDateTypes.Unknown))) { formattedDate = VagueDateTypes.Unknown.ToString(); return(VagueDate.ToCode(VagueDateTypes.Unknown)); } if (!String.IsNullOrEmpty(formatString1) && String.IsNullOrEmpty(formatString2)) { formattedDate = startDateString + Delimiter; return(formatString1 + Delimiter); } else if (String.IsNullOrEmpty(formatString1) && !String.IsNullOrEmpty(formatString2)) { formattedDate = Delimiter + endDateString; return(Delimiter + formatString2); } else if (startDateString != endDateString) { formattedDate = startDateString + Delimiter + endDateString; return(formatString1 + formatString2); } else { formattedDate = startDateString; return(formatString1); } } }