2017-10-12 7 views
2

私はDateTime型のプロパティを持つモデルを持っています。このプロパティから、csvファイルに書き込むときとcsvファイルthourgh CsvHelperから読み込むときに、秒とマイクロ秒を文字列に含めたいと思います。カスタムDateTimeカバレッジがnullを返していますか?

だから私はこちらのモデルは、この

public class MyModel 
{ 
    // ..... removed other properties 
    public DateTime MyDateTime {get; set}; 
} 

のように見え、CsvClassMapperこの

public sealed class CsvMap : CsvClassMap<MyModel> 
{ 
    public CsvMap() 
    { 
     Map(m => m.MyDateTime).TypeConverter<CsvDateTimeConverter>(); 
    } 
} 
のように見えます DefaultTypeConverter

public class CsvDateTimeConverter : DefaultTypeConverter 
{ 
    private const string DateStringFormat = "MM/dd/yyyy HH:mm:ss.fff"; 

    public override object ConvertFromString(TypeConverterOptions options, string text) 
    { 
     if (string.IsNullOrEmpty(text)) return null; 

     return Convert.ToDateTime(text); 
    } 

    public override string ConvertToString(TypeConverterOptions options, object value) 
    { 
     if (value == null) return ""; 

     var dateTime = (DateTime) value; 

     return dateTime.ToString(DateStringFormat); 
    } 
} 

を拡張することにより、溶液のところに来ていますか

私はクラスmを登録しました読者と作家にp。しかし、問題は:

私は正常にコンバータを使用してcsvファイルに書き込むことができますが、私はcsvファイルから読み取ろうとすると、他のプロパティを読み取ることができますが、DateTimeプロパティのnullを返します。

私は何が欠けていますか?

EDITED:

それは場合に役立ちます:

using (TextReader reader = new StreamReader(filePath)) 
{ 
    var csv = new CsvReader(reader); 
    csv.Configuration.RegisterClassMap<CsvMap>(); 

    csv.Configuration.Encoding = Encoding.UTF8; 

    return csv.GetRecords<MyModel>().ToList(); 
} 
+0

Convert.ToDateTime(text)をDateTime.ParseExact()に置き換え、 "MM/dd/yyyy HH:mm:ss.fff"の形式を使用します。 – jdweng

+0

カスタムDateTimeコンバータは何ですか?これは何も変換しません、それは 'Convert.ToDateTime(text)'への単純な呼び出しです。これは現在のロケールのフォーマットを使用します –

+0

'CsvDateTimeConverter'のコードが(私が直接呼び出すと)正しく動作するようです。たぶんそれはコンバータの登録に問題がありますか? [C#Fiddle](https://dotnetfiddle.net/ypQ5Nt)を参照してください。 –

答えて

4

カスタム型コンバータを指定する必要はありません。これはミリ秒が追加されたUSスタイルのDateTime形式です。あなたが必要とするのは、正しい文化と、おそらく、使用される形式を指定することだけです。

1つのオプションは、米国の文化にConfiguration.CultureInfoプロパティを設定することです:

reader.Configuration.CultureInfo = CultureInfo.GetCultureInfo("en-US"); 

次のコードは、米国を生成し、読み込みますミリ秒なしをさかのぼり:

 using (var file = new StreamWriter("test.csv")) 
     { 
      var writer = new CsvWriter(file); 
      writer.Configuration.CultureInfo = CultureInfo.GetCultureInfo("en-US"); 
      writer.WriteRecords(items); 
     } 

     using (var file = new StreamReader("test.csv")) 
     { 
      var reader= new CsvReader(file); 
      reader.Configuration.CultureInfo = CultureInfo.GetCultureInfo("en-US"); 
      var models=reader.GetRecords<MyModel>().ToArray(); 
      Console.WriteLine(models[0]);     
     } 

あなたは別のを指定することができますフィールドのフォーマットをクラスマップのTypeConverterOptionsメソッドを使用して変更します。

public sealed class CsvMap : CsvHelper.Configuration.CsvClassMap<MyModel> 
{ 
    public CsvMap() 
    { 
     Map(m => m.Date).TypeConverterOption("MM/dd/yyyy HH:mm:ss.fff"); 
     Map(m => m.ID); 
    } 
} 

だけのクラスマップを追加し、次のコードは、米国を生成します(ミリ秒)と日付:

 using (var file = new StreamWriter("test.csv")) 
     { 
      var writer = new CsvWriter(file); 
      writer.Configuration.CultureInfo = CultureInfo.GetCultureInfo("en-US"); 
      writer.Configuration.RegisterClassMap<CsvMap>(); 
      writer.WriteRecords(items); 
     } 

     using (var file = new StreamReader("test.csv")) 
     { 
      var reader= new CsvReader(file); 
      reader.Configuration.CultureInfo = CultureInfo.GetCultureInfo("en-US"); 
      reader.Configuration.RegisterClassMap<CsvMap>();     
      var models=reader.GetRecords<MyModel>().ToArray(); 
      Console.WriteLine(models[0]);     
     } 

Date,ID 
10/12/2017 11:56:11.016,1 
10/11/2017 11:56:11.021,2 

あなたが文化を設定したくない場合は、同様TypeConverterOptionとしてのCultureInfoを指定することができますファイル全体のために:

public CsvMap() 
    { 
     Map(m => m.Date).TypeConverterOption("MM/dd/yyyy HH:mm:ss.fff") 
         .TypeConverterOption(CultureInfo.GetCultureInfo("en-US")); 
     Map(m => m.ID); 
    } 

NOTE

CsvHelperは、最近のメジャーアップデート(3.0)をリリース(今週のように)。先週はそこにいませんでした!現在のバージョンは3.2.0です。このバージョンで

CsvClassMapCsvMapなり、TypeConverterOptions方法はMapMemberを返すメソッドを持つオブジェクトになります:

public CsvMap() 
    { 
     string format="MM/dd/yyyy HH:mm:ss.fff"; 
     var enUS=CultureInfo.GetCultureInfo("en-US"); 

     Map(m => m.Date).TypeConverterOption.Format(format) 
         .TypeConverterOption.CultureInfo(enUS); 
     Map(m => m.ID); 
    } 

Type Convertersはるかに少ないTypeConverterOptionsのためのドキュメントはまだありません。私はthis Github issueの方法を見つけました。

もう1つの方法はthe source codeをチェックすることです。

+0

は魅力的な作品です。Merci beaucoup – ash

0
public override object ConvertFromString(TypeConverterOptions options, string text) 
{ 
    if (string.IsNullOrEmpty(text)) return null; 

    return Convert.ToDateTime(text); 
} 

あなたはおそらくここにあなたの特別なフォーマットが欠落しています

これは、CSVファイルから読み込むためのコードです。私はDateTime.TryConvert(...)のファンです - 自分自身Convert.XXXXが好きではありません。タイプ固有の変換方法を使用する理由はありますか?

+0

いいえ 'Convert.'メソッドはフォーマット文字列を受け入れません。これは、各タイプの 'ParseExact'メソッドによって提供されます。 –

-1

この方法

Convert.ToDateTime(text); 

ここで指定しなければならない形式で受け取るオーバーロードがあります。そのようにしてみてください。

enter image description here

EDIT:あなたのConvertFromString方法で

は、これを追加します。

public override object ConvertFromString(TypeConverterOptions options, string text) 
{ 
    if (string.IsNullOrEmpty(text)) return null; 

    DateTimeFormatInfo info = new DateTimeFormatInfo() { FullDateTimePattern = DateStringFormat }; 

    return Convert.ToDateTime(text, info); 
} 
+0

画像を注意深く見てください。これは、フォーマットの文字列ではなく、 'CultureInfo'のためのものです –

+0

DateTimeFormatInfoにDatePatternを定義しておらず、指定されたメソッドで使用されませんか? – Rob

+0

@Rob:「private const string DateStringFormat = "MM/dd/yyyy HH:mm:ss.fff";」という行はあなたとは明らかに同意しないと考えるかもしれません。そして、一般的には、あなたが望むものがすべて日付形式であるときに、なぜ「CultureInfo」を作成するか見つけ出すのかは分かりません。日付の書式を明確にしておくと(この例のように)、書式が何であるべきかについて疑問がないことを意味します。使用する書式を探すために文化を探す必要はありません。 – Chris

関連する問題