/// <summary> /// Constructs a CuiDate object, uses CuiDate.ParseExact to create a new temporary CuiDate object for the given string /// and copies the property values from the temporary CuiDate object to the new CuiDate object. /// </summary> /// <param name="date">The date value.</param> public CuiDate(string date) { CuiDate nd = CuiDate.ParseExact(date, CultureInfo.InvariantCulture); this.DateValue = nd.DateValue; this.DateType = nd.DateType; this.Month = nd.Month; this.Year = nd.Year; this.NullIndex = nd.NullIndex; }
/// <summary> /// Parses a string that represents a date and returns a corresponding CuiDate object, with the culture /// used to parse the string specified. /// </summary> /// <param name="date">The date to be parsed.</param> /// <param name="cultureInfo">The culture that should be used to parse the string. If a string is culture-agnostic, /// this should be CultureInfo.InvariantCulture. Defaults to CurrentCulture.</param> /// <returns>A new CuiDate object. </returns> /// <exception cref="System.ArgumentNullException">Date is null. </exception> /// <exception cref="System.FormatException">Date is not in a recognised format.</exception> public static CuiDate ParseExact(string date, CultureInfo cultureInfo) { CuiDate result; if (!CuiDate.TryParseExact(date, out result, cultureInfo)) { throw new FormatException(Resources.CuiDateResources.ParseCalledWithBadFormat); } return(result); }
/// <summary> /// Determines whether the add instruction operand has a valid value. /// </summary> /// <param name="value">The string used to check whether the add instruction operand has a valid value. </param> /// <returns>True if the add instruction operand has a valid value; otherwise, false. </returns> /// <remarks> /// The test performed is not dependent on the current setting of <see cref="P:Microsoft.Cui.Controls.Common.DateAndTime.CuiDate.DateType">DateType</see>. /// This means true is returned if the operand is valid, even if <see cref="P:Microsoft.Cui.Controls.Common.DateAndTime.CuiDate.DateType">DateType</see> is not Exact or Approximate. /// </remarks> public static bool IsAddValid(string value) { if (value == null) { throw new ArgumentNullException("value"); } Regex shortcut = new Regex(CuiDate.ResolveAddInstructionRegExTokens(), RegexOptions.IgnoreCase); Match match = shortcut.Match(value.Replace(" ", string.Empty)); return(match.Success); }
/// <summary> /// Adds a number of months, weeks, days or years to a date. /// </summary> /// <param name="instruction">Add instructions such as +2w to add 2 weeks or -3m to subtract 3 months.</param> /// <remarks> /// The operand can be positive or negative; if the operand is not included, it is assumed to be positive. /// </remarks> /// <exception cref="System.ArgumentNullException">Instruction is null.</exception> public void Add(string instruction) { this.DateValue = CuiDate.Add(this, instruction).DateValue; }
/// <summary> /// Adds a number of months, weeks, days or years to a date. /// </summary> /// <param name="sourceDate">The date to be added to. </param> /// <param name="instruction">Add instructions such as +2w to add 2 weeks or -3m to subtract 3 months. </param> /// <remarks> /// The operand can be positive or negative; if the operand is not included, it is assumed to be positive. /// </remarks> /// <exception cref="System.ArgumentNullException">If either argument is null. /// </exception> /// <exception cref="System.InvalidOperationException">If <see cref="P:Microsoft.Cui.Controls.Common.DateAndTime.CuiDate.DateType">DateType</see> /// is null. </exception> /// <exception cref="System.ArgumentException">If <see cref="P:Microsoft.Cui.Controls.Common.DateAndTime.CuiDate.DateType">DateType</see> /// is <see cref="P:Microsoft.Cui.Controls.Common.DateAndTime.CuiDate.Year">Year</see> and the unit in the instruction is /// not DateArithmeticResources.YearsUnit. Or if <see cref="P:Microsoft.Cui.Controls.Common.DateAndTime.CuiDate.DateType">DateType</see> /// is YearMonth and the unit in the instruction is /// not DateArithmeticResources.YearsUnit or DateArithmeticResources.MonthsUnit. Or if the instruction is not /// of the expected format.</exception> /// <exception cref="Microsoft.Cui.Controls.Common.DateAndTime.InvalidArithmeticSetException">If the set of letters in /// the DateArithmeticResources is not unique or if values are not each a single character long. /// </exception> /// <returns>A new CuiDate object. </returns> public static CuiDate Add(CuiDate sourceDate, string instruction) { if (instruction == null) { throw new ArgumentNullException("instruction"); } if (sourceDate == null) { throw new ArgumentNullException("sourceDate"); } // check the set of resource strings used by this method are // valid if (!CheckArithmeticSetResources()) { throw new InvalidArithmeticSetException(Resources.CuiDateResources.ArithmeticSetInvalidResources); } if (sourceDate.DateType == DateType.NullIndex) { throw new InvalidOperationException(Resources.CuiDateResources.AddNotAllowedForDateType); } if (CuiDate.IsAddValid(instruction) == false) { throw new ArgumentException(Resources.CuiDateResources.AddInstructionInvalidFormat, "instruction"); } Regex shortcut = new Regex(CuiDate.ResolveAddInstructionRegExTokens(), RegexOptions.IgnoreCase); Match match = shortcut.Match(instruction.Replace(" ", string.Empty)); if (match.Success == true) { // We need to skip the first group because with this RegEx it is always the complete string int groupNumber = 0; foreach (Group g in match.Groups) { if (groupNumber > 0) { foreach (Capture c in g.Captures) { int increment; if (int.TryParse(c.Value.Substring(0, c.Value.Length - 1), out increment)) { if (c.Value.EndsWith(Resources.CuiDateResources.MonthsUnit, StringComparison.OrdinalIgnoreCase) == true) { if (sourceDate.DateType == DateType.Exact || sourceDate.DateType == DateType.Approximate) { sourceDate.DateValue = sourceDate.DateValue.AddMonths(increment); } else if (sourceDate.DateType == DateType.YearMonth) { sourceDate.Year += increment / 12; sourceDate.Month += increment % 12; } else { throw new ArgumentException( string.Format(CultureInfo.CurrentCulture, Resources.CuiDateResources.AddInstructionNotAllowedForDateType, "Month", sourceDate.DateType), "instruction"); } } else if (c.Value.EndsWith(Resources.CuiDateResources.WeeksUnit, StringComparison.OrdinalIgnoreCase) == true) { if (sourceDate.DateType == DateType.Exact || sourceDate.DateType == DateType.Approximate) { // Add weeks using AddDays and multiplying number of weeks to add by 7 sourceDate.DateValue = sourceDate.DateValue.AddDays(increment * 7); } else { throw new ArgumentException( string.Format(CultureInfo.CurrentCulture, Resources.CuiDateResources.AddInstructionNotAllowedForDateType, "Week", sourceDate.DateType), "instruction"); } } else if (c.Value.EndsWith(Resources.CuiDateResources.DaysUnit, StringComparison.OrdinalIgnoreCase) == true) { if (sourceDate.DateType == DateType.Exact || sourceDate.DateType == DateType.Approximate) { sourceDate.DateValue = sourceDate.DateValue.AddDays(increment); } else { throw new ArgumentException( string.Format(CultureInfo.CurrentCulture, Resources.CuiDateResources.AddInstructionNotAllowedForDateType, "Day", sourceDate.DateType), "instruction"); } } else if (c.Value.EndsWith(Resources.CuiDateResources.YearsUnit, StringComparison.OrdinalIgnoreCase) == true) { if (sourceDate.DateType == DateType.Exact || sourceDate.DateType == DateType.Approximate) { sourceDate.DateValue = sourceDate.DateValue.AddYears(increment); } else if (sourceDate.DateType == DateType.Year || sourceDate.DateType == DateType.YearMonth) { sourceDate.Year += increment; } else { throw new ArgumentException( string.Format(CultureInfo.CurrentCulture, Resources.CuiDateResources.AddInstructionNotAllowedForDateType, "Year", sourceDate.DateType), "instruction"); } } } } } groupNumber++; } } return(sourceDate); }
/// <summary> /// Parses a string that represents a date. /// </summary> /// <param name="date">A string containing the value to be converted. </param> /// <param name="result">A container for a successfully-parsed date. </param> /// <param name="cultureInfo">The culture that should be used to parse the string.</param> /// <returns>True if the date string was successfully parsed; otherwise, false. </returns> /// <remarks> /// If the string can be parsed, /// the result parameter is set to an CuiDate object corresponding to /// the parsed dateString. If the string cannot be parsed, the result parameter is set to DateTime.MinValue. /// </remarks> public static bool TryParseExact(string date, out CuiDate result, CultureInfo cultureInfo) { // check for true null if (string.IsNullOrEmpty(date)) { result = new CuiDate(); result.DateType = DateType.Null; return(true); } // first check for numeric year month as this can be confused as a date Regex numericYearMonthRegEx = new Regex("^(?<Month>0?[1-9]|10|11|12)[-\\s/](?<Year>\\d{4}|\\d{2})$"); Match numericYearMonthRegExResults = numericYearMonthRegEx.Match(date); if (numericYearMonthRegExResults.Success) { result = new CuiDate(); result.DateType = DateType.YearMonth; result.Month = int.Parse(numericYearMonthRegExResults.Groups["Month"].Value, cultureInfo); result.Year = CuiDate.ParseYear(numericYearMonthRegExResults.Groups["Year"].Value, cultureInfo); return(true); } // check to see if approx indicator is present bool approxIndicatorPresent = (date.IndexOf(Resources.CuiDateResources.Approximate, StringComparison.CurrentCultureIgnoreCase) >= 0); if (approxIndicatorPresent) { date = date.Replace(Resources.CuiDateResources.Approximate, string.Empty).Trim(); } // try datetime parse with our standard formats GlobalizationService gs = new GlobalizationService(); string[] standardFormats = new string[] { gs.ShortDatePattern, gs.ShortDatePatternWithDayOfWeek, }; DateTime parsedDateTime; if (DateTime.TryParseExact(date, standardFormats, cultureInfo, DateTimeStyles.None, out parsedDateTime)) { result = new CuiDate(parsedDateTime); result.DateType = (approxIndicatorPresent ? DateType.Approximate : DateType.Exact); return(true); } // Check if 'date' is a year and a month Regex yearMonthRegEx = BuildMonthYearRegEx(cultureInfo); Match yearMonthMatch = yearMonthRegEx.Match(date); // Regex doesn't take care of year as zero if (yearMonthMatch.Success && CuiDate.ParseYear(yearMonthMatch.Groups["Year"].Value, cultureInfo) > 0) { int month = GetMonthNumberFromMonthName(yearMonthMatch.Groups["Month"].Value, cultureInfo); int year = CuiDate.ParseYear(yearMonthMatch.Groups["Year"].Value, cultureInfo); result = new CuiDate(year, month); return(true); } // Check if 'date' is a year Regex yearRegEx = new Regex(@"^(\d{4}|\d{2})$"); // Regex doesn't take care of year as zero if (yearRegEx.IsMatch(date) && CuiDate.ParseYear(date, cultureInfo) > 0) { result = new CuiDate(CuiDate.ParseYear(date, cultureInfo)); return(true); } // Check if 'date' is a Null date Regex nullDateRegEx = new Regex(@"^Null:(?<Index>-?\d+)$", RegexOptions.IgnoreCase); Match match = nullDateRegEx.Match(date); if (match.Success) { // Pull the numeric Index text and see if it is in range int nullIndex; if (int.TryParse(match.Groups[1].Captures[0].Value, out nullIndex)) { if (nullIndex >= MinimumNullIndex && nullIndex <= MaximumNullIndex) { result = new CuiDate(); result.NullIndex = nullIndex; result.DateType = DateType.NullIndex; return(true); } } } // try alternative formats string[] alternativeFormats = new string[] { "d-MMM-yyyy", "d-M-yyyy", "d-MM-yyyy", "d-MMMM-yyyy", "d/MMM/yyyy", "d/M/yyyy", "d/MM/yyyy", "d/MMMM/yyyy", "d MMM yyyy", "d M yyyy", "d MM yyyy", "d MMMM yyyy", "ddd d-MMM-yyyy", "ddd d-M-yyyy", "ddd d-MM-yyyy", "ddd d-MMMM-yyyy", "ddd d/MMM/yyyy", "ddd d/M/yyyy", "ddd d/MM/yyyy", "ddd d/MMMM/yyyy", "ddd d MMM yyyy", "ddd d M yyyy", "ddd d MM yyyy", "ddd d MMMM yyyy", "d-MMM-yy", "d-M-yy", "d-MM-yy", "d-MMMM-yy", "d/MMM/yy", "d/M/yy", "d/MM/yy", "d/MMMM/yy", "d MMM yy", "d M yy", "d MM yy", "d MMMM yy", "ddd d-MMM-yy", "ddd d-M-yy", "ddd d-MM-yy", "ddd d-MMMM-yy", "ddd d/MMM/yy", "ddd d/M/yy", "ddd d/MM/yy", "ddd d/MMMM/yy", "ddd d MMM yy", "ddd d M yy", "ddd d MM yy", "ddd d MMMM yy" }; if (DateTime.TryParseExact(date, alternativeFormats, cultureInfo, DateTimeStyles.None, out parsedDateTime)) { result = new CuiDate(parsedDateTime); result.DateType = (approxIndicatorPresent ? DateType.Approximate : DateType.Exact); return(true); } // no match result = null; return(false); }
/// <summary> /// Parses a string that represents a date. /// </summary> /// <param name="date">A string containing the value to be parsed. </param> /// <param name="result">A container for a successfully-parsed date. </param> /// <returns>True if the date string was successfully parsed; otherwise, false.</returns> /// <remarks> /// If the string can be parsed, /// the result parameter is set to an CuiDate object corresponding to /// the parsed dateString. If the string cannot be parsed, the result parameter is set to DateTime.MinValue. /// </remarks> public static bool TryParseExact(string date, out CuiDate result) { return(CuiDate.TryParseExact(date, out result, CultureInfo.InvariantCulture)); }
/// <summary> /// Parses a string that represents a date and returns a corresponding CuiDate object. /// </summary> /// <param name="date">The date to be parsed. </param> /// <returns>A new CuiDate object. </returns> /// <exception cref="System.ArgumentNullException">Date is null. </exception> /// <exception cref="System.FormatException">Date is not in a recognised format. </exception> public static CuiDate ParseExact(string date) { return(CuiDate.ParseExact(date, CultureInfo.CurrentCulture)); }