Eliminando el desplazamiento de zona horaria de DateTimeOffset. Eliminación del desplazamiento de zona horaria de DateTimeOffset Servidor SQL con desplazamiento de fecha nula

DateTimeOffset testDateAndTime = nuevo DateTimeOffset(2008, 5, 1, 8, 6, 32, nuevo TimeSpan(1, 0, 0)); //HORA Y FECHA DE LIMPIEZA testDateAndTime = testDateAndTime.DateTime.Date; var fechasTableEntry = db.DatesTable.First(dt => dt.Id == someTestId); fechasTableEntry.test= testDateAndTime; db.SaveChangesAsync();

RESULTADO EN BASE DE DATOS: 2008-05-01 00:00:00.0000000 -04:00

¿Cómo habilitar -4:00 a +00:00 (desde el código antes de guardar)?

Yo he tratado:

Tarea pública SetTimeZoneOffsetToZero(DateTimeOffset dateTimeOffSetObj) ( TimeSpan zeroOffsetTimeSpan = new TimeSpan(0, 0, 0, 0, 0); devuelve dateTimeOffSetObj.ToOffset(zeroOffsetTimeSpan); )

Él no hace nada.

El objetivo final es simplemente tener una fecha sin hora ni zona horaria compensada. NO quiero convertir la hora a otra zona horaria (es decir, 00:00:00.0000000. No quiero que reste 4 horas de la hora 00:00:00.0000000 y 00:00:00.0000000 compense la hora establecida en +00 :00, solo quiero que establezca el desplazamiento en +00:00). Quiero la fecha actual con compensación cero.

Editar:

Esto es lo que puede ofrecer en otros lugares:

DateTimeOffset testDateAndTime = nuevo DateTimeOffset(2008, 5, 1, 8, 6, 32, nuevo TimeSpan(1, 0, 0)); testDateAndTime = testDateAndTime.DateTime.Date; // Poner a cero la porción de tiempo testDateAndTime = DateTime.SpecifyKind(testDateAndTime.Date, DateTimeKind.Utc); //Parte de compensación "puesta a cero"

Estaba seguro de que SpecifyKind especificaría mi dateTimeOffset, como cambiar TANTO la hora como el desplazamiento de la zona horaria, pero cuando se prueba, parece que solo cambia el desplazamiento de la zona horaria, que es lo que quiero. ¿Hay algún problema con esto?

1 respuesta

El problema no tiene nada que ver con la base de datos. Si estableció un punto de interrupción o registró una salida en algún lugar, debería ver el desplazamiento vinculado poco después de este código:

TestDateAndTime = testDateAndTime.DateTime.Date;

Vamos a desglosarlo:

  • Empezaste con DateTimeOffset 2008-05-01T08:06:32+01:00
  • Luego llamó a .DateTime, lo que resultó en un valor de DateTime de 2008-05-01T08:06:32 con DateTimeKind.Unspecified.
  • Luego llamó a .Date, lo que resultó en un valor DateTime de 2008-05-01T00:00:00 con DateTimeKind.Unspecified.
  • Devuelve el resultado en testDateAndTime que es de tipo DateTimeOffset . Esto provoca una conversión implícita de DateTime a DateTimeOffset que aplica la zona horaria local. En su caso, parece que el desplazamiento de este valor en su zona horaria local es -04:00 , por lo que el valor resultante es DateTimeOffset 2008-05-01T00:00:00-04:00 como lo describió,

Usted dijo:

El objetivo final es simplemente tener una fecha sin hora ni zona horaria desplazada.

Bueno, actualmente no existe ningún tipo de datos nativo de C# que sea solo una fecha sin hora. Hay un tipo de fecha puro en el paquete System.Time en corefxlab, pero no está listo para una aplicación de producción típica. Hay LocalDate en la biblioteca de tiempo de Noda, que puede usar hoy, pero aún tendrá que volver a convertirlo a un tipo nativo antes de guardarlo en la base de datos. Mientras tanto, lo mejor que puedes hacer es:

  • Cambie su SQL Server para usar el tipo de fecha en este campo.
  • En su código .NET, use DateTime con hora 00:00:00 y DateTimeKind.Unspecified. Debes recordar ignorar la parte horaria (ya que, de hecho, hay fechas sin medianoche local en ciertas zonas horarias).
  • Cambie la alerta de prueba a DateTime en lugar de DateTimeOffset.

En general, si bien DateTimeOffset es adecuado para una gran cantidad de escenarios (como eventos de marca de tiempo), no es adecuado para valores de solo fecha.

Quiero la fecha actual con compensación cero.

Si realmente lo quieres como DateTimeOffset, harías:

TestDateAndTime = nuevo DateTimeOffset(testDateAndTime.Date, TimeSpan.Zero);

Sin embargo, desaconsejo esto. Al hacer esto, toma la fecha local del valor original y afirma que está en UTC. Si el desplazamiento original es distinto de cero, será una afirmación falsa. Posteriormente, provocará otros errores, ya que en realidad estás hablando de un momento diferente (con una fecha potencialmente diferente) al que creaste.

Con respecto a la pregunta adicional formulada en su edición, especificar DateTimeKind.Utc cambia el comportamiento de la conversión implícita. En lugar de utilizar la zona horaria local, se utiliza la hora UTC, que siempre tiene un desplazamiento cero. El resultado es el mismo que el de la vista más explícita que proporcioné anteriormente. Todavía lo recomiendo en contra por las mismas razones.

Veamos el ejemplo de comenzar desde 2016-12-31T22:00:00-04:00. Según su enfoque, debe guardar 2016-12-31T00:00:00+00:00 en la base de datos. Sin embargo, estos son dos momentos diferentes en el tiempo. El primero, normalizado a UTC, sería 2017-01-01T02:00:00+00:00, y el segundo, convertido a otra zona horaria, sería 2016-12-30T20:00:00-04:00. Tenga en cuenta el cambio de fechas en la conversión. Probablemente este no sea el comportamiento que desearía en su aplicación.

La opción humana ([debes registrarte para ver el enlace]).

La esencia del problema es esta: Si accidentalmente implementó una base de datos en un servidor SQL con un "desplazamiento de fecha" de 0, entonces surge un problema cuando la base de datos contiene un atributo con el tipo TIME, es decir, este atributo está establecido en 01 /01/0001 10:30:00 o fecha registrada vacía 01.01.0001 00:00:00. Al registrar tales detalles, no se registra.
En Internet sugieren crear una nueva base de datos con un offset de 2000.
Pero realmente no quería crear una nueva base. Y cambie la ruta a la base de datos para todos los usuarios.
Luego seguí la ruta de dónde se almacena este valor en SQL. Lo encontré y lo cambié a 2000 y todo estaba bien.
Y ahora paso a paso dónde cambiar.

Expulsar a todos los usuarios.

¡¡¡ATENCIÓN!!!

1. Primero, haga una copia de seguridad utilizando las herramientas 1C, es decir. subirlo a *.dt
Esto debe hacerse antes de cambiar el “offset”
Si no se hace esto, en toda su base de datos habrá referencias, documentos, etc.
¿Dónde hay un requisito? La fecha será, por ejemplo, 02.10.0009.
LO QUE NO ESTÁ PERMITIDO...
Entonces lo has subido a *.dt

2. Vaya a SQL Server Management Studio
Encuentra tu base en la lista y presiona el signo más.
Busque la carpeta "Tablas" allí y ábrala.
Se abrirán un montón de tablas, ve al final y busca la tabla.
_YearOffset, párese sobre él y seleccione el elemento "Abrir mesa" con el botón derecho, consulte la Fig. 1
Cambiar el valor 0 a 2000
Cerrar SQL Server Management Studio

3. Vaya al configurador y cargue la base de datos previamente guardada.

Si no se hace esto, todas las fechas serán del año 0009.
Una vez cargada la base de datos... Puede ir a 1C y asegurarse de que las fechas sean normales.
El resultado es que cambiamos el "desfase de fecha de 0 a 2000"

A veces sucede que esta opción no se puede utilizar por un motivo u otro. Luego hay una opción más extrema ([debes registrarte para ver el enlace]):

Declarar el cursor TablesAndFields para

SELECCIONE objetos.nombre como nombre de tabla, columnas.nombre como nombre de columna
DESDE dbo.sysobjects como objetos
unión izquierda dbo.syscolumns como columnas en object.id = columns.id
donde objetos.xtype = "U" y columnas.xtype = 61

abrir tablas y campos

MIENTRAS @@FETCH_STATUS = 0
COMENZAR Ejecutivo(" actualizar"+ @NombreTabla + "
colocar " + @NombreDeColumna + " = ""2000- 01- 01 00:00:00" "
dónde " + @NombreDeColumna + " > ""3999- 12- 31 23:59:59" "")

Esto se ejecuta siempre que la búsqueda anterior tenga éxito.
BUSCAR SIGUIENTE DE TablesAndFields en @TableName, @ColumnName
FIN

cerrar Tablas y campos
DesasignarTablesAndFields
ir

¡Antes de cualquier manipulación, no olvides hacer copias de las bases de datos!

El problema no tiene nada que ver con la base de datos. Si establece un punto de interrupción o ingresa una salida en algún lugar, debería poder ver el desplazamiento ajustado poco después de este código:

TestDateAndTime = testDateAndTime.DateTime.Date;

Vamos a desglosarlo:

  • Comenzó con el valor DateTimeOffset 2008-05-01T08:06:32+01:00
  • Luego llamó a .DateTime, lo que resultó en el valor DateTime 2008-05-01T08:06:32 con DateTimeKind.Unspecified.
  • Luego llamó a .Date, lo que resultó en un valor DateTime de 2008-05-01T00:00:00 con DateTimeKind.Unspecified.
  • Asigna el resultado a testDateAndTime , que es de tipo DateTimeOffset . Esto provoca una conversión implícita de DateTime a DateTimeOffset. , que se aplica local Zona horaria. En su caso, parece que el desplazamiento para este valor en su zona horaria local es -04:00, por lo que el valor resultante es DateTimeOffset de 2008-05-01T00:00:00-04:00 como lo describió.

Usted dijo:

El objetivo final es simplemente tener una fecha sin hora ni zona horaria compensada.

Bueno, hay actualmente no es un tipo de datos nativo de C#, que es simplemente una fecha sin hora. Hay un tipo de fecha puro en Hora del sistema paquete en corefxlab, pero aún no está listo para una aplicación de producción típica. Hay un LocalDate en la biblioteca de Noda Time que puede usar hoy, pero aún tendrá que volver a convertirlo a un tipo nativo antes de guardarlo en la base de datos. Mientras tanto, lo mejor que puedes hacer es:

  • Cambie su SQL Server para usar el tipo de fecha en el campo.
  • En su código .NET, use DateTime con hora 00:00:00 y DateTimeKind.Unspecified. Debes recordar ignorar la parte horaria (ya que, de hecho, hay fechas sin medianoche local en ciertas zonas horarias).
  • Cambie el accesorio de prueba para que sea DateTime en lugar de DateTimeOffset.

En general, si bien DateTimeOffset es adecuado para una gran cantidad de escenarios (por ejemplo, marcas de tiempo eventos), no se ajusta bien a valores de solo fecha.

Quiero la fecha actual con compensación cero.

Si usted Realmente quiero es como DateTimeOffset, podrías hacer:

TestDateAndTime = nuevo DateTimeOffset(testDateAndTime.Date, TimeSpan.Zero);

Sin embargo, no recomiendo hacer esto. Al hacer esto tomas local la fecha del valor original y afirmar que está en UTC. Si el desplazamiento original es distinto de cero, será una afirmación falsa. Posteriormente, provocará otros errores, ya que en realidad estás hablando de un momento diferente (con una fecha potencialmente diferente) al que creaste.

Respecto a la pregunta adicional planteada a su junta directiva. Especificar DateTimeKind.Utc cambia el comportamiento de la conversión implícita. En lugar de utilizar la zona horaria local, se utiliza la hora UTC, que siempre tiene un desplazamiento cero. El resultado es el mismo que el de la vista más explícita que proporcioné anteriormente. Todavía lo recomiendo en contra por las mismas razones.

Considere un ejemplo que comienza con 2016-12-31T22:00:00-04:00. Según su enfoque, debe guardar 2016-12-31T00:00:00+00:00 en la base de datos. Sin embargo, estos son dos momentos diferentes en el tiempo. El primero, normalizado a UTC, sería 2017-01-01T02:00:00+00:00, y el segundo, convertido a otra zona horaria, sería 2016-12-30T20:00:00-04:00. Tenga en cuenta el cambio de fechas en la conversión. Probablemente este no sea el comportamiento que desearía en su aplicación.

Publicaciones sobre el tema.