/// <summary> /// Extracts data from a date time text given a potision and a date time format part. This data is then assigned to the /// given result. /// </summary> private static bool TryGetDataFromDateTime(char[] dateTimeArray, int startPosition, IDateTimeFormatPartTO part, IDateTimeResultTO result, bool passAsTime, out int resultLength, out string error) { bool nothingDied = true; error = ""; resultLength = 0; bool dataFound = false; if (part.Isliteral) { string forwardLookupResult = ForwardLookup(dateTimeArray, startPosition, part.Value.Length); if (forwardLookupResult != part.Value) { nothingDied = false; error = string.Concat("Literal expressed from index ", startPosition, " doesn't match what is specified in the input format."); } else { resultLength = forwardLookupResult.Length; } } else { // // Get the possible options for part // List<IDateTimeFormatPartOptionTO> partOptions; if (passAsTime) { if (!TimeFormatPartOptions.TryGetValue(part.Value, out partOptions)) { nothingDied = false; error = string.Concat("Unrecognised format part '", part.Value, "'."); } } else { if (!DateTimeFormatPartOptions.TryGetValue(part.Value, out partOptions)) { nothingDied = false; error = string.Concat("Unrecognised format part '", part.Value, "'."); } } if (nothingDied) { int partOptionsCount = 0; // // Try get a value for each option // while (partOptionsCount < partOptions.Count) { IDateTimeFormatPartOptionTO partOption = partOptions[partOptionsCount]; string forwardLookupResult; bool predicateRun; //Added by Massimo.Guerrera - For Bug 9494 to let the input format to be more forgiving if (partOption.Length != partOption.ResultLength) { forwardLookupResult = ForwardLookup(dateTimeArray, startPosition, partOption.ResultLength); predicateRun = partOption.Predicate(forwardLookupResult, passAsTime); if (!predicateRun) { forwardLookupResult = ForwardLookup(dateTimeArray, startPosition, partOption.Length); predicateRun = partOption.Predicate(forwardLookupResult, passAsTime); } } else { forwardLookupResult = ForwardLookup(dateTimeArray, startPosition, partOption.Length); predicateRun = partOption.Predicate(forwardLookupResult, passAsTime); } // // Check length of forward lookup is correct // if ((forwardLookupResult.Length == partOption.Length || forwardLookupResult.Length == partOption.ResultLength) && (partOption.Predicate == null || predicateRun)) { // // Set exit and result length // partOptionsCount = partOptions.Count; resultLength = forwardLookupResult.Length; dataFound = true; // // Decide on the correct value to use // IConvertible value; if (partOption.ActualValue != null) { value = partOption.ActualValue; } else if (partOption.IsNumeric) { value = Convert.ToInt32(forwardLookupResult); } else { value = forwardLookupResult; } // // Assign the value to the result // if (partOption.AssignAction != null) { partOption.AssignAction(result, passAsTime, value); } } partOptionsCount++; } // // If no viable data was found set error // if (!dataFound) { nothingDied = false; error = string.Concat("Unexpected value at index ", startPosition, "."); } } } return nothingDied; }
/// <summary> /// Extracts data from a date time text given a potision and a date time format part. This data is then assigned to the /// given result. /// </summary> private static bool TryGetDataFromDateTime(char[] dateTimeArray, int startPosition, IDateTimeFormatPartTO part, IDateTimeResultTO result, bool passAsTime, out int resultLength, out string error) { bool nothingDied = true; error = ""; resultLength = 0; bool dataFound = false; if (part.Isliteral) { string forwardLookupResult = ForwardLookup(dateTimeArray, startPosition, part.Value.Length); if (forwardLookupResult != part.Value) { nothingDied = false; error = string.Concat("Literal expressed from index ", startPosition, " doesn't match what is specified in the input format."); } else { resultLength = forwardLookupResult.Length; } } else { // // Get the possible options for part // List <IDateTimeFormatPartOptionTO> partOptions; if (passAsTime) { if (!_timeFormatPartOptions.TryGetValue(part.Value, out partOptions)) { nothingDied = false; error = string.Format(ErrorResource.UnrecognisedFormatPart, part.Value); } } else { if (!_dateTimeFormatPartOptions.TryGetValue(part.Value, out partOptions)) { nothingDied = false; error = string.Format(ErrorResource.UnrecognisedFormatPart, part.Value); } } if (nothingDied) { int partOptionsCount = 0; // // Try get a value for each option // while (partOptionsCount < partOptions.Count) { IDateTimeFormatPartOptionTO partOption = partOptions[partOptionsCount]; string forwardLookupResult; bool predicateRun; if (partOption.Length != partOption.ResultLength) { forwardLookupResult = ForwardLookup(dateTimeArray, startPosition, partOption.ResultLength); predicateRun = partOption.Predicate(forwardLookupResult, passAsTime); if (!predicateRun) { forwardLookupResult = ForwardLookup(dateTimeArray, startPosition, partOption.Length); predicateRun = partOption.Predicate(forwardLookupResult, passAsTime); } } else { forwardLookupResult = ForwardLookup(dateTimeArray, startPosition, partOption.Length); predicateRun = partOption.Predicate(forwardLookupResult, passAsTime); } // // Check length of forward lookup is correct // if ((forwardLookupResult.Length == partOption.Length || forwardLookupResult.Length == partOption.ResultLength) && (partOption.Predicate == null || predicateRun)) { // // Set exit and result length // partOptionsCount = partOptions.Count; resultLength = forwardLookupResult.Length; dataFound = true; // // Decide on the correct value to use // IConvertible value; if (partOption.ActualValue != null) { value = partOption.ActualValue; } else if (partOption.IsNumeric) { value = Convert.ToInt32(forwardLookupResult); } else { value = forwardLookupResult; } partOption.AssignAction?.Invoke(result, passAsTime, value); } partOptionsCount++; } // // If no viable data was found set error // if (!dataFound) { nothingDied = false; error = string.Format(ErrorResource.UnexpectedValueAtIndex, startPosition); } } } return(nothingDied); }
/// <summary> /// Converts a date from one format to another. If a valid time modifier is specified then the date is adjusted /// accordingly before being returned. /// </summary> public bool TryFormat(IDateTimeOperationTO dateTimeTO, out string result, out string error) { result = ""; IDateTimeParser dateTimeParser = DateTimeConverterFactory.CreateParser(); bool nothingDied = true; IDateTimeResultTO dateTimeResultTO; //2013.05.06: Ashley Lewis - Bug 9300 - trim should allow null input format dateTimeTO.InputFormat = dateTimeTO.InputFormat != null?dateTimeTO.InputFormat.Trim() : null; //2013.02.12: Ashley Lewis - Bug 8725, Task 8840 - Added trim to data if (dateTimeParser.TryParseDateTime(dateTimeTO.DateTime.Trim(), dateTimeTO.InputFormat, out dateTimeResultTO, out error)) { // // Parse time, if present // DateTime tmpDateTime = dateTimeResultTO.ToDateTime(); if (!string.IsNullOrWhiteSpace(dateTimeTO.TimeModifierType)) { //2012.09.27: massimo.guerrera - Added for the new functionality for the time modification Func <DateTime, int, DateTime> funcToExecute; if (TimeModifiers.TryGetValue(dateTimeTO.TimeModifierType, out funcToExecute) && funcToExecute != null) { tmpDateTime = funcToExecute(tmpDateTime, dateTimeTO.TimeModifierAmount); } } // // If nothing has gone wrong yet // // ReSharper disable ConditionIsAlwaysTrueOrFalse if (nothingDied) // ReSharper restore ConditionIsAlwaysTrueOrFalse { // // If there is no output format use the input format // string outputFormat = string.IsNullOrWhiteSpace(dateTimeTO.OutputFormat) ? dateTimeTO.InputFormat : dateTimeTO.OutputFormat; if (string.IsNullOrWhiteSpace(outputFormat)) { //07.03.2013: Ashley Lewis - Bug 9167 null to default string shortPattern = CultureInfo.CurrentCulture.DateTimeFormat.ShortDatePattern; string longPattern = CultureInfo.CurrentCulture.DateTimeFormat.LongTimePattern; string finalPattern = shortPattern + " " + longPattern; if (finalPattern.Contains("ss")) { outputFormat = finalPattern.Insert(finalPattern.IndexOf("ss", StringComparison.Ordinal) + 2, ".fff"); outputFormat = dateTimeParser.TranslateDotNetToDev2Format(outputFormat, out error); } } // // Format to output format // List <IDateTimeFormatPartTO> formatParts; // // Get output format parts // nothingDied = DateTimeParser.TryGetDateTimeFormatParts(outputFormat, out formatParts, out error); if (nothingDied) { int count = 0; while (count < formatParts.Count && nothingDied) { IDateTimeFormatPartTO formatPart = formatParts[count]; if (formatPart.Isliteral) { result += formatPart.Value; } else { Func <IDateTimeResultTO, DateTime, string> func; if (DateTimeFormatParts.TryGetValue(formatPart.Value, out func)) { result += func(dateTimeResultTO, tmpDateTime); } else { nothingDied = false; error = string.Concat("Unrecognized format part '", formatPart.Value, "'."); } } count++; } } } } else { nothingDied = false; } return(nothingDied); }
/// <summary> /// Parses the given data using the specified format /// </summary> private bool TryParse(string data, string inputFormat, bool parseAsTime, out IDateTimeResultTO result, out string error) { bool nothingDied = true; result = new DateTimeResultTO(); error = ""; int culturesTried = 0; const int MaxAttempts = 8; if (string.IsNullOrWhiteSpace(data)) { data = DateTime.Now.ToShortDateString() + " " + DateTime.Now.ToLongTimeString(); } if (string.IsNullOrWhiteSpace(inputFormat)) { inputFormat = TranslateDotNetToDev2Format( GlobalConstants.Dev2DotNetDefaultDateTimeFormat.Replace("ss", "ss.fff"), out error); } else { culturesTried = MaxAttempts; } while (culturesTried <= MaxAttempts) { char[] dateTimeArray = data.ToArray(); List <IDateTimeFormatPartTO> formatParts; int position = 0; nothingDied = TryGetDateTimeFormatParts(inputFormat, _dateTimeFormatForwardLookups, _dateTimeFormatPartOptions, out formatParts, out error); if (!string.IsNullOrEmpty(error)) { return(false); } if (nothingDied) { int count = 0; while (count < formatParts.Count && nothingDied && position < dateTimeArray.Length) { IDateTimeFormatPartTO formatPart = formatParts[count]; int resultLength; if (TryGetDataFromDateTime(dateTimeArray, position, formatPart, result, parseAsTime, out resultLength, out error)) { position += resultLength; } else { //clear invalid result! result = new DateTimeResultTO(); nothingDied = false; } count++; } if (!nothingDied) { inputFormat = MatchInputFormatToCulture(ref error, culturesTried); if (culturesTried >= MaxAttempts) { if (!IsBlankResult(result)) { //Return the result if it isn't blank nothingDied = true; } else { //no result, throw error error = string.Format(ErrorResource.CannorParseInputDateTimeWithGivenFormat, error); } } else { nothingDied = true; } culturesTried++; } else { //Stop trying different formats culturesTried = MaxAttempts + 1; } } else { culturesTried++; } } return(nothingDied); }