/// <summary> /// Handle getting the most appropriate culture of a given data type /// </summary> /// <typeparam name="T">The type of data expected to be passed in (but passed in as a string representation)</typeparam> /// <param name="data">The data we need to detect the culture info for</param> /// <returns>The culture information recognised or null if none could be determined (or none required)</returns> public static CultureCheck FieldCulture <T>(String data) { CultureCheck response = new CultureCheck() { }; // What type of data is this? switch (typeof(T).ToShortName()) { // Date Time Data Type case "datetime": // Loop the cultures in terms of likelihood foreach (CultureInfo culture in CultureList) { try { // Try and cast the date using the culture to see if it // is of the right type DateTime casted = DateTime.Parse(data, culture); // Ok, it didn't die, this must be the right culture so use this one response.Culture = culture; // Now just check to see if the result could be ambiguous response.AmbigiousResult = (casted.Day <= 12 && casted.Month <= 12); break; // All done, exit .. } catch { } } break; } // Return the culture return(response); }
/// <summary> /// Analyse some raw data and work out how /// </summary> /// <param name="rawData"></param> /// <returns></returns> public static DataItemDefinition AnalyseText(AnalyseRequest <String> request) { // Start with a blank definition DataItemDefinition result = new DataItemDefinition() { Culture = CultureInfo.InvariantCulture }; Boolean ambigiousCulture = true; // Raw data has something to convert? if ((request.Data ?? "") != "") { // Open up a text reader to stream the data to the CSV Reader using (TextReader textReader = new StringReader(request.Data)) { // Create an instance of the CSV Reader #warning "This no longer works as we need a definition by default, Might be worth gettig a default reader somehow" using (CsvReader csvReader = SetupReader(textReader, request.Connection, null)) { // Can we read from the stream? Int32 headerId = 0; if (csvReader.Read()) { // Read in the "headers", this may not actually be the headers // but is a quick way for us to seperate the amount of columns csvReader.ReadHeader(); // Parse the header records so that they do not include enclosing quotes headerId = 0; while (headerId < csvReader.Context.HeaderRecord.Length) { // Clean the header csvReader.Context.HeaderRecord[headerId] = DataFormatHelper.CleanString( csvReader.Context.HeaderRecord[headerId], csvReader.Configuration.Quote); // Add a new property to the definition result.ItemProperties.Add(new DataItemProperty() { Calculation = "", DataType = typeof(String), Description = $"Column {headerId.ToString()}", Name = csvReader.Context.HeaderRecord[headerId], Key = false, OrdinalPosition = headerId, Path = csvReader.Context.HeaderRecord[headerId], Pattern = "", Size = 0, PropertyType = DataItemPropertyType.Property }); headerId++; // Move to the next header } } // Now we have the base columns, let's find out what their actual data type // is and what culture the data is in (if we have dates etc.) Int32 sampleCount = 0; while (csvReader.Read() && sampleCount < request.SampleSize) { // For each of the properties that we found result.ItemProperties.ForEach(property => { // Try and get the raw value for this column if (GetField <String>(csvReader, property, out String rawValue)) { // Deriver the data type Type gatheredType = DataFormatHelper.CalculateType( DataFormatHelper.CleanString( rawValue, csvReader.Configuration.Quote)); // If the type that we just gathered from the // data source different to one that we have currently // found (headers will default to text anyway) if (gatheredType != property.DataType && gatheredType != typeof(String)) { // Set the new property type property.DataType = gatheredType; // Is the culture still ambigious? Keep checking specific data points // to determine the culture if (ambigiousCulture) { switch (property.DataType.ToShortName()) { case "datetime": // Attempt to get the culture of the date field CultureCheck gatheredCulture = DataFormatHelper.FieldCulture <DateTime>(rawValue); if (gatheredCulture.Culture != CultureInfo.InvariantCulture && !gatheredCulture.AmbigiousResult && gatheredCulture.Culture != result.Culture) { result.Culture = gatheredCulture.Culture; if (ambigiousCulture) { ambigiousCulture = false; } } break; } } } } ; }); // Move to the next sample item (if possible) sampleCount++; } } } } return(result); // Send the definition back }