2012-04-25 16 views
3

私が与えられた奇妙なタスクは、XMLシリアル化を使用してLARGEオブジェクトをシリアル化することです。このオブジェクトには、複数のDateTimeフィールドを持つ複数のネストされたUserDefinedクラスが含まれています。 DateTimeデータの要件は、データを最初に作成して設定したユーザーのTimeZoneに常に表示する必要があることです。したがって、デシリアライズされたときは同じではないため、UTCまたはローカル時間を使用することはできません。また、UTCで値を表示することはできません。ローカル時間で表示する必要があります。私が必要とするのは、「絶対ローカル時間」の概念を表す奇妙なシリアル化形式です...「TimeZoneなしのローカル時間」です。シリアル化されたDateTimeオブジェクトからTimeZoneをシリアライズしない、または削除しない

Regexを使って日付文字列からTZを取り除くことは簡単です。私が扱っているオブジェクトの大きさのせいで、OutOfMemoryExceptionが発生することがよくあります。私はデバッグを一度も実行せず、使用中のメモリは動作中に100kから800kにスパイクされているのを見ました。よくない。それは小さなファイルの一つでした。

Doc.DocumentElement.InnerXML = Regex.Replace(Doc.DocumentElement.InnerXML, "(\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2})(\\+|-)(\\d{2}:\\d{2})", "$1") 

はこれまでのところ、私が見てきた唯一のオプションは、すべての日時フィールドの複製を作成することで、DTは「XmlIgnore()」として自分自身をフィールドに設定した後、手動でシリアライズされた文字列データから、すべての日付を復元docが再ロードされた後これも実用的ではありません。 Custom DateTime XML Serialization

TimeZoneデータなしでシリアル化エンジンでDateTimeオブジェクトをシリアル化する方法はありますか。オブジェクト内のすべてのDTプロパティに個々に適用する必要のない一般的なものが望ましいでしょうか?

!! EDIT !!

私は部分的な解決策を見つけたかもしれません。それは少なくとも前進を助けるかもしれない。 DateTimeKind.Unspecifiedは、シリアル化されても、TimeZoneデータが接続されていないようです。これは私が探している解決策ですか? DateTime.SpecifyKindを使用して、すべてのDateTimeデータを強制的にキャストしますか?

public DateTime? StartDate 
    { 
     get 
     { return _StartDate; } 
     set 
     { 
      if (_StartDate == value) 
       return; 

      if (value != null) 
       _StartDate = DateTime.SpecifyKind(value.Value, DateTimeKind.Unspecified); 
      else 
       _StartDate = value; 

      OnPropertyChanged("StartDate"); 
     } 
    } 
+0

タイムゾーン(「最初に作成したユーザーのタイムゾーンに表示されます」)を保存し、同時に削除したいですか?あなたが望むものを選んでください...あなたが望む方法でタイムゾーンを処理するための表示コードを修正するのがより簡単なようです。 –

+1

TimeZoneを保持することは目に見える効果です。私が本当にやりたいことは、TimeZoneのデータを完全に無視することです。 TimeZoneがシリアル化されたデータに含まれていない場合は、デシリアライズされたときに格納されたdateTime値に影響しません。 – Nevyn

+0

したがって、ユーザーに「2011年5月5日午前9時」と入力させ、タイムゾーンに関係なく午前9時を過ぎないようにしますか? (朝起きる目覚まし時計に似ています)インドの半時間帯のタイムゾーンに9AMを入力/シリアル化し、米国のタイムゾーン(ほぼ12時間離れていてラウンドアワーの1つ)でデシリアライズされても、それはまだ9AMと表示されますか? –

答えて

0

答えが見つかりました。これは正確に私が探していたものではありませんが、効果的な回避策として役立ちます。

private static readonly Regex DTCheck = new Regex(@"(\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2})([\+|-]\d{2}:\d{2})"); 

    /// <summary> 
    /// Removes any instances of the TimeZoneOffset from the RigX after it has been serialized into an XMLString ++ Called from the "Save" process 
    /// </summary> 
    /// <param name="rigx"></param> 
    /// <returns>StringReader referencing the re-formatted XML String</returns> 
    private static StringReader RemoveTZOffsetFromRigX(RigX rigx) 
    { 
     StringBuilder sb = new StringBuilder(); 
     StringWriter sw = new StringWriter(sb); 
     XmlSerializer ser = new XmlSerializer(typeof(RigX)); 

     ser.Serialize(sw, rigx); 

     string xmlText = sb.ToString(); 

     if (DTCheck.IsMatch(xmlText)) 
      xmlText = DTCheck.Replace(xmlText, "$1"); 

     StringReader Sreader = new StringReader(xmlText); 

     return Sreader; 
    } 

    /// <summary> 
    /// Removes the TimeZone offset from a RigX as referenced by stream. Returns a reader linked to the new stream ++ Called from the "Load" process 
    /// </summary> 
    /// <param name="stream">stream containing the initial RigX XML String</param> 
    /// <returns>StringReader referencing the re-formatted XML String</returns> 
    private StringReader RemoveTZOffsetFromXML(MemoryStream stream) 
    { 
     stream.Position = 0; 
     StreamReader reader = new StreamReader(stream, Encoding.UTF8); 

     string xmlText = reader.ReadToEnd(); 
     reader.Close(); 
     stream.Close(); 

     if (DTCheck.IsMatch(xmlText)) 
      xmlText = DTCheck.Replace(xmlText, "$1"); 

     StringReader Sreader = new StringReader(xmlText); 

     return Sreader; 
    } 

ファイルからXMLで読み取った後、シリアライザを通してそれを実行する前に、オフセットを除去するために裸のXMLテキストに正規表現を実行します。この関数は、変更されたXML文字列に対して実行される文字列リーダを返します。この文字列リーダは、オブジェクトへの非直列化によって実行されます。

シリアライザを使用して出力ストリームに直接XMLを保存するのではなく、stringBuilderを使用してシリアル化されたxmlをインターセプトできます。その後、ロード処理中と同じプロセスを使用して、RegularExpressionを介してTimeZoneオフセットを削除し、変更されたテキストにリンクされたStringReaderを返します。このとき、データはファイルに書き戻されます。

ややハック感がありますが効果的です。大量のメモリが必要ですが、可能であれば直接関数のデバッグを避けてください。文字列を評価しないようにしてください。最後にVSインスタンスを完全にクラッシュさせてしまいました。

3

要件や前提条件を再評価する必要があると思います。

あなたが書いた:

をdatetimeデータのための要件は、それは常に最初に作成したユーザーのタイムゾーンで表示され、データを設定しなければならないということです。したがって、私はUTCまたはローカルタイムを使用することはできません。なぜなら、デシリアライズされていないと、同じではないからです。

私はあなたの分析が正しいとは思いません。私には、ストレージへのシリアライゼーションを不必要にユーザーに「表示」されていると思われるようです。しかし、これらの2つの事柄は関連してはならない。私が理解している必要条件は次のとおりです。

  • さまざまな時間値をシリアル化してデシリアライズする必要があります。
  • これらの時刻を「表示」すると、ディスプレイに元のタイムゾーンが使用されます。

これらは明確な要件です。

のDateTimeをシリアル化することは時間の瞬間を保存していますが、タイムゾーン情報を失うことになります。私は、XMLドキュメントごとに一度、タイムゾーン情報を別々にシリアル化する必要があるようです。それを行うと時間の逆シリアル化が自動的に行われます。は、元々というストレージに保存したストレージのを返します。

と表示されている場合は、XMLドキュメントに別途保存されているタイムゾーン情報を使用してください。 TimeZoneを含むプロパティが元のオブジェクトに存在しない場合は、オブジェクトモデルがアプリケーションの要件にあまり適していないように見えます。この場合、オブジェクト定義を変更する必要があります。 TimeZone。 (http://msdn.microsoft.com/en-us/library/system.timezoneinfo.aspxを参照してください)

メモリ不足エラーに関しては、それは無関係の問題かもしれません。また、大きなXmlDocumentオブジェクトを使用しているために発生している可能性があります。これは、Xmlシリアル化を使用する場合は不要です。

+0

異なる要件については正しいですか。私はすでに、オブジェクト(およびそのdateTimes)のシリアル化を行っています。 2番目のポイントは若干再記入する必要があります。 DateTime情報を表示するとき、私はTimeZoneを完全に無視しているはずです。 TimeZoneのアイデアは決して最初の方程式に入ってはいけません。 – Nevyn

+0

2つの数量を保管しない限り、これはできません。タイムゾーンを考慮せずに時刻を正確にシリアル化および逆シリアル化するには、UTCが必要です。特別な表示要件を追加すると、「タイムゾーンフリー」時刻、または時刻が常に表示されるはずの元のタイムゾーンのいずれかで、情報の追加ビットを保存またはシリアル化する必要があることは明らかです。私はあなたの要件についてもう少し考える必要があるかもしれないと思います。 – Cheeso

+0

"静的な"データが必要です。変更しないでください。 目標。中国のJimmyはすべてのデータを入力し、シリアル化されたオブジェクトをデータ転送システム経由でニューヨークのBobに送信します。データの分析とボーナス計算を行うには、シリアル化されていません。ボブは、ジミーがデータに入ったときにニューヨークにいた時は気にしない。 – Nevyn

0

このような日付を保持するカスタムタイプを作成することをお勧めします。それは、あなたが必要とする任意の方法でシリアル化を扱うことができます。より簡単なアプローチとして、ISO8601形式(2012-05-04-26T12:57)の文字列として保存することを検討してください(この場合はタイムゾーンなし)。

シリアル化されたデータからタイムゾーンを削除することは、実際に絶対時間を節約する必要があるとすぐに面白い問題を引き起こす可能性があるため、お勧めできません。特にコードが共有されている場合。

関連する問題