/// <summary> /// Handles the time zone for a date time column /// </summary> /// <param name="dataObject">The data object.</param> /// <param name="columnInfo">The column information.</param> /// <param name="reader">The reader.</param> /// <returns></returns> protected DateTime HandleTimeZone(DateTime dataObject, [NotNull] WriterColumn columnInfo, [NotNull] IDataRecord reader) { if (columnInfo is null) { throw new ArgumentNullException(nameof(columnInfo)); } if (reader is null) { throw new ArgumentNullException(nameof(reader)); } if (columnInfo.ColumnOrdinalTimeZone > -1) { var destinationTimeZoneId = reader.GetString(columnInfo.ColumnOrdinalTimeZone); if (string.IsNullOrEmpty(destinationTimeZoneId)) { HandleWarning(columnInfo.Name, "Time zone is empty, value not converted"); } else { // ReSharper disable once PossibleInvalidOperationException return(FunctionalDI.AdjustTZExport(dataObject, destinationTimeZoneId, Columns.IndexOf(columnInfo), (columnNo, msg) => HandleWarning(Columns[columnNo].Name, msg)).Value); } } else if (!string.IsNullOrEmpty(columnInfo.ConstantTimeZone)) { // ReSharper disable once PossibleInvalidOperationException return(FunctionalDI.AdjustTZExport(dataObject, columnInfo.ConstantTimeZone, Columns.IndexOf(columnInfo), (columnNo, msg) => HandleWarning(Columns[columnNo].Name, msg)).Value); } return(dataObject); }
protected string TextEncodeField([NotNull] IFileFormat fileFormat, object dataObject, [NotNull] WriterColumn columnInfo, bool isHeader, [CanBeNull] IDataReader reader, [CanBeNull] Func <string, DataType, IFileFormat, string> handleQualify) { if (columnInfo is null) { throw new ArgumentNullException(nameof(columnInfo)); } if (fileFormat.IsFixedLength && columnInfo.FieldLength == 0) { throw new FileWriterException("For fix length output the length of the columns needs to be specified."); } string displayAs; if (isHeader) { if (dataObject is null) { throw new ArgumentNullException(nameof(dataObject)); } displayAs = dataObject.ToString(); } else { try { if (dataObject == null || dataObject is DBNull) { displayAs = columnInfo.ValueFormat.DisplayNullAs; } else { switch (columnInfo.ValueFormat.DataType) { case DataType.Integer: displayAs = Convert.ToInt64(dataObject).ToString(columnInfo.ValueFormat.NumberFormat, CultureInfo.InvariantCulture).Replace( CultureInfo.InvariantCulture.NumberFormat.NumberGroupSeparator, columnInfo.ValueFormat.GroupSeparator); break; case DataType.Boolean: displayAs = (bool)dataObject ? columnInfo.ValueFormat.True : columnInfo.ValueFormat.False; break; case DataType.Double: displayAs = StringConversion.DoubleToString( dataObject is double d ? d : Convert.ToDouble(dataObject.ToString(), CultureInfo.InvariantCulture), columnInfo.ValueFormat); break; case DataType.Numeric: displayAs = StringConversion.DecimalToString( dataObject is decimal @decimal ? @decimal : Convert.ToDecimal(dataObject.ToString(), CultureInfo.InvariantCulture), columnInfo.ValueFormat); break; case DataType.DateTime: displayAs = reader == null ? StringConversion.DateTimeToString((DateTime)dataObject, columnInfo.ValueFormat) : StringConversion.DateTimeToString(HandleTimeZone((DateTime)dataObject, columnInfo, reader), columnInfo.ValueFormat); break; case DataType.Guid: // 382c74c3-721d-4f34-80e5-57657b6cbc27 displayAs = ((Guid)dataObject).ToString(); break; case DataType.String: case DataType.TextToHtml: case DataType.TextToHtmlFull: case DataType.TextPart: displayAs = dataObject.ToString(); if (columnInfo.ValueFormat.DataType == DataType.TextToHtml) { displayAs = HTMLStyle.TextToHtmlEncode(displayAs); } // a new line of any kind will be replaced with the placeholder if set if (fileFormat.NewLinePlaceholder.Length > 0) { displayAs = StringUtils.HandleCRLFCombinations(displayAs, fileFormat.NewLinePlaceholder); } if (fileFormat.DelimiterPlaceholder.Length > 0 && fileFormat.FieldDelimiterChar != '\0') { displayAs = displayAs.Replace(fileFormat.FieldDelimiterChar.ToStringHandle0(), fileFormat.DelimiterPlaceholder); } if (fileFormat.QuotePlaceholder.Length > 0 && fileFormat.FieldQualifierChar != '\0') { displayAs = displayAs.Replace(fileFormat.FieldQualifierChar.ToStringHandle0(), fileFormat.QuotePlaceholder); } break; default: displayAs = string.Empty; break; } } } catch (Exception ex) { // In case a cast did fail (eg.g trying to format as integer and providing a text, use the // original value displayAs = dataObject?.ToString() ?? string.Empty; if (string.IsNullOrEmpty(displayAs)) { HandleError(columnInfo.Name, ex.Message); } else { HandleWarning(columnInfo.Name, "Value stored as: " + displayAs + $"\nExpected {columnInfo.ValueFormat.DataType} but was {dataObject?.GetType()}" + ex.Message); } } } // Adjust the output in case its is fixed length if (fileFormat.IsFixedLength) { if (displayAs.Length <= columnInfo.FieldLength || columnInfo.FieldLength <= 0) { return(displayAs.PadRight(columnInfo.FieldLength, ' ')); } HandleWarning(columnInfo.Name, $"Text with length of {displayAs.Length} has been cut off after {columnInfo.FieldLength} character"); return(displayAs.Substring(0, columnInfo.FieldLength)); } // Qualify text if required if (fileFormat.FieldQualifierChar != '\0' && handleQualify != null) { return(handleQualify(displayAs, columnInfo.ValueFormat.DataType, fileFormat)); } return(displayAs); }
/// <summary> /// Gets the column information based on the SQL Source, but overwritten with the definitions /// </summary> /// <param name="generalFormat"> /// general value format for not explicitly specified columns format /// </param> /// <param name="columnDefinitions"></param> /// <param name="sourceSchemaDataReader">The reader for the source.</param> /// <returns></returns> /// <exception cref="ArgumentNullException">reader</exception> public static IEnumerable <IColumn> GetColumnInformation(IValueFormat generalFormat, IReadOnlyCollection <IColumn> columnDefinitions, DataTable schemaTable) { if (schemaTable == null) { throw new ArgumentNullException(nameof(schemaTable)); } var result = new List <WriterColumn>(); var colName = new BiDirectionalDictionary <int, string>(); // Make names unique and fill the dictionary foreach (DataRow schemaRow in schemaTable.Rows) { var colNo = (int)schemaRow[SchemaTableColumn.ColumnOrdinal]; var newName = StringUtils.MakeUniqueInCollection(colName.Values, schemaRow[SchemaTableColumn.ColumnName].ToString()); colName.Add(colNo, newName); } foreach (DataRow schemaRow in schemaTable.Rows) { var colNo = (int)schemaRow[SchemaTableColumn.ColumnOrdinal]; var column = columnDefinitions.FirstOrDefault(x => x.Name.Equals(colName[colNo], StringComparison.OrdinalIgnoreCase)); if (column != null && column.Ignore) { continue; } // Based on the data Type in the reader defined and the general format create the value format var valueFormat = column?.ValueFormat ?? new ImmutableValueFormat( ((Type)schemaRow[SchemaTableColumn.DataType]).GetDataType(), generalFormat.DateFormat, generalFormat.DateSeparator, generalFormat.TimeSeparator, generalFormat.NumberFormat, generalFormat.GroupSeparator, generalFormat.DecimalSeparator, generalFormat.True, generalFormat.False, generalFormat.DisplayNullAs); var fieldLength = Math.Max((int)schemaRow[SchemaTableColumn.ColumnSize], 0); switch (valueFormat.DataType) { case DataType.Integer: fieldLength = 10; break; case DataType.Boolean: { var lenTrue = valueFormat.True.Length; var lenFalse = valueFormat.False.Length; fieldLength = lenTrue > lenFalse ? lenTrue : lenFalse; break; } case DataType.Double: case DataType.Numeric: fieldLength = 28; break; case DataType.DateTime: fieldLength = valueFormat.DateFormat.Length; break; case DataType.Guid: fieldLength = 36; break; case DataType.String: case DataType.TextToHtml: case DataType.TextToHtmlFull: case DataType.TextPart: break; default: throw new ArgumentOutOfRangeException(); } var constantTimeZone = string.Empty; var columnOrdinalTimeZoneReader = -1; // the timezone information if (column != null) { var tz = column.TimeZonePart; if (!string.IsNullOrEmpty(tz)) { var tzInfo = tz.GetPossiblyConstant(); if (tzInfo.Item2) { constantTimeZone = tzInfo.Item1; } else { if (colName.TryGetByValue(tzInfo.Item1, out var ordinal)) { columnOrdinalTimeZoneReader = ordinal; } } } } var ci = new WriterColumn(colName[colNo], colNo, valueFormat, fieldLength, constantTimeZone, columnOrdinalTimeZoneReader); result.Add(ci); // add an extra column for the time, reading columns they get combined, writing them they // get separated again if (column == null || string.IsNullOrEmpty(column.TimePart) || colName.ContainsValue(column.TimePart)) { continue; } if (ci.ValueFormat.DateFormat.IndexOfAny(new[] { 'h', 'H', 'm', 's' }) != -1) { Logger.Warning( $"'{ci.Name}' will create a separate time column '{column.TimePart}' but seems to write time itself '{ci.ValueFormat.DateFormat}'"); } // In case we have a split column, add the second column (unless the column is also present result.Add(new WriterColumn(column.TimePart, colNo, new ImmutableValueFormat(DataType.DateTime, column.TimePartFormat, timeSeparator: column.ValueFormat.TimeSeparator), column.TimePartFormat.Length, constantTimeZone, columnOrdinalTimeZoneReader)); } return(result); }