2011-08-03 13 views
8

Tengo un problema cuando estoy escribiendo un DataSet en XML que tiene una columna de tipo DateTime y quiero controlar el formato de salida.Formatos personalizados de DateTime al usar DataSet.WriteXml en .NET

DataSet data = LoadDataSet(); 
data.Tables[0].Rows[0]["MyDate"] = DateTime.Now; 
data.WriteXml(myFile); 

Por defecto, el formato de la Fecha y hora en el XML parece ser como sigue:

2011-08-02T17:39:00-07:00 

me gustaría utilizar un formato de fecha personalizado, o por lo menos despojar a la zona horaria información.

¿Hay alguna forma de controlar el formato de las columnas DateTime en el XML de mi conjunto de datos?

Mi instinto dice que no, ya que supongo que se hace de esta manera para facilitar la conversión de datos en zonas horarias, pero he notado que puedo leer DataSet XML incluso si las etiquetas de la columna DateTime omiten los datos de la zona horaria, así que esperaba Puedo hacer algo análogo cuando escribo en XML.

+1

he visto algunos desarrolladores utilizan trucos como la adición de otra columna llamada ["MyDateString"] donde usan DateTime.Now.ToShortDateString(), sin decir que sea ideal, pero lo he visto de primera mano en las clases de serialización para algunos mensajes que intercambiamos con otros socios :) – kd7

+0

Sí, acabo de mencionar eso a un colega Ese será probablemente nuestro plan de respaldo. –

+0

¿Puede definir el esquema XSLT y aplicarlo a XML, o sería una exageración en su caso? – sll

Respuesta

-1

Hay un formato estándar para DateTime en XML. Ese es el formato que usará WriteXml. Si necesita un formato diferente, entonces no necesita usar DateTime. Como han dicho otros, use String en su lugar.

+0

Es un área gris, no hay referencia de esquema en los archivos generados, por lo que no hay nada que obligue explícitamente a las etiquetas DateTime de WriteXml a ser del tipo xsd: date. Estoy de acuerdo con que xsd: date tiene un formato estricto, pero no estoy seguro de que esté necesariamente en uso aquí. –

+0

Su idea requeriría que 'WriteXml' genere datos en un formato que el esquema de' WriteXmlSchema' no validaría. Eso parece poco probable. –

1

Aplicar transformación XSLT para conjunto de datos: (de MSDN) (creo que se encuentra ejemplo XSLT para convertir el formato de DateTime, o ver post on SO regarding XSLT and DateTIme formats)

DataSet custDS = new DataSet("CustomerDataSet"); 
XmlDataDocument xmlDoc = new XmlDataDocument(custDS); 

XslTransform xslTran = new XslTransform(); 
xslTran.Load("transform.xsl"); 

XmlTextWriter writer = new XmlTextWriter("xslt_output.html", 
    System.Text.Encoding.UTF8); 

xslTran.Transform(xmlDoc, null, writer); 
writer.Close(); 
+0

en realidad lo estamos transformando a través de XSLT después del hecho (para la integración con un sistema de terceros), pero al formato de salida le importa AM/PM, por ahora solo estamos escribiendo lógica condicional XSLT para analizar la fecha de 24 horas formatee y conviértalo en un formato AM/PM de 12 horas. Un poco desordenado, pero hará el truco. –

11

Esta solución alternativa puede ser adecuada si puede vivir solo con la información de la zona horaria que se elimina. El valor predeterminado para la propiedad DateTimeMode de las columnas DateTime en DataSets es UnspecifiedLocal. Podría establecer explícitamente el modo de fecha y hora como no especificado, lo que significa que la parte de la zona de tiempo no se serializa.

p. Ej.

Se puede utilizar una función como esta:

public static void RemoveTimezoneForDataSet(DataSet ds) 
    { 
     foreach (DataTable dt in ds.Tables) 
     { 
      foreach (DataColumn dc in dt.Columns) 
      { 

       if (dc.DataType == typeof(DateTime)) 
       { 
        dc.DateTimeMode = DataSetDateTime.Unspecified; 
       } 
      } 
     } 
    } 

Ejemplo de uso:

DataSet ds = new DataSet(); 
    DataTable dt = new DataTable("t1"); 
    dt.Columns.Add("ID", typeof(int)); 
    dt.Columns.Add("DT", typeof(DateTime)); 
    dt.Rows.Add(new object[] { 1, new DateTime(2009, 1, 1) }); 
    dt.Rows.Add(new object[] { 2, new DateTime(2010, 12, 23) }); 

    ds.Tables.Add(dt); 

    ds.WriteXml("c:\\Standard.xml"); 

    RemoveTimezoneForDataSet(ds); 

    ds.WriteXml("c:\\WithoutTimezone.xml"); 

Salida:

Standard.xml:

<?xml version="1.0" standalone="yes"?> 
<NewDataSet> 
    <t1> 
    <ID>1</ID> 
    <DT>2009-01-01T00:00:00+11:00</DT> 
    </t1> 
    <t1> 
    <ID>2</ID> 
    <DT>2010-12-23T00:00:00+11:00</DT> 
    </t1> 
</NewDataSet> 

WithoutTimezone.xml :

<?xml version="1.0" standalone="yes"?> 
<NewDataSet> 
    <t1> 
    <ID>1</ID> 
    <DT>2009-01-01T00:00:00</DT> 
    </t1> 
    <t1> 
    <ID>2</ID> 
    <DT>2010-12-23T00:00:00</DT> 
    </t1> 
</NewDataSet> 

Si no te gusta la idea de modificar las DataColumns del conjunto de datos original, se puede hacer una copia de la misma, a continuación, llamar a la función en la copia.

+0

Excelente. Gracias. Parecería que solo DataSetDateTime.Unspecified funcionará porque recibo un mensaje de error tratando de usar LocalTime: el modo no se puede cambiar si la tabla ya tiene datos. –

-1

Si el archivo es regular, y el XML exportado parece que sí, puede simplemente reescribirlo utilizando un bucle simple. Solución fácil y rápida.Use un poco de mi código si desea:

private void rewriteXML(string oldFile, string newFile, int startPos, int strLength) 
     { 
      try 
      { 
       File.Delete(newFile); 
      } 
      catch { Console.WriteLine("File didn't existed."); } 
      StreamReader SR = new StreamReader(oldFile); 
      string data; 
      StreamWriter SW = new StreamWriter(newFile); 
      while ((data = SR.ReadLine()) != null) 
      { 
       if (data.Contains("<start>")) 
       { 
        string ln_tmp = data.Replace(" ", ""); 
        string newline = " <start>" + ln_tmp.Substring(startPos, strLength) + "</start>"; 
        SW.WriteLine(newline); 
       } 
       else 
        SW.WriteLine(data); 
      } 
      SR.Close(); 
      SW.Close(); 
     } 

La salida es como:

<start>19:34</start> 

En lugar de:

<start>2013-03-17T19:34:00+01:00</start> 
+0

El código no implementa bloques 'using', y ese bloque try/catch ocultará excepciones que no sean archivos no encontrados. –

Cuestiones relacionadas