Suppression du décalage horaire de DateTimeOffset. Suppression du décalage horaire de DateTimeOffset Serveur SQL de décalage de date nul

DateTimeOffset testDateAndTime = new DateTimeOffset(2008, 5, 1, 8, 6, 32, new TimeSpan(1, 0, 0)); //NETTOYER L'HEURE ET LA DATE testDateAndTime = testDateAndTime.DateTime.Date; var datesTableEntry = db.DatesTable.First(dt => dt.Id == someTestId); datesTableEntry.test= testDateAndTime ; db.SaveChangesAsync();

RÉSULTAT DANS LA BASE DE DONNÉES : 2008-05-01 00:00:00.0000000 -04:00

Comment activer -4h00 à +00h00 (à partir du code avant l'enregistrement) ?

J'ai essayé:

Tâche publique SetTimeZoneOffsetToZero(DateTimeOffset dateTimeOffSetObj) ( TimeSpan zeroOffsetTimeSpan = new TimeSpan(0, 0, 0, 0, 0); return dateTimeOffSetObj.ToOffset(zeroOffsetTimeSpan); )

Il ne fait rien.

L’objectif final est simplement d’avoir une date sans décalage horaire ni fuseau horaire. JE NE veux PAS convertir l'heure dans un autre fuseau horaire (c'est-à-dire 00:00:00.0000000). Je ne veux pas qu'il soustrait 4 heures à l'heure 00:00:00.0000000 et que 00:00:00.0000000 décale l'heure réglée de +00. :00 , je veux juste qu'il définisse le décalage sur +00:00). Je veux la date actuelle avec un décalage nul.

Modifier:

Voici ce que vous pouvez proposer ailleurs :

DateTimeOffset testDateAndTime = new DateTimeOffset(2008, 5, 1, 8, 6, 32, new TimeSpan(1, 0, 0)); testDateAndTime = testDateAndTime.DateTime.Date ; // Mettre à zéro la partie temporelle testDateAndTime = DateTime.SpecifyKind(testDateAndTime.Date, DateTimeKind.Utc); //Partie de décalage « Zéro sortie »

J'étais sûr que SpecifyKind spécifierait mon dateTimeOffset, comme changer à la fois le décalage de l'heure et du fuseau horaire, mais une fois testé, il semble simplement changer le décalage du fuseau horaire, ce que je veux. Y a-t-il un probleme avec ca?

1 réponse

Le problème n'a rien à voir avec la base de données. Si vous définissez un point d'arrêt ou enregistrez une sortie quelque part, vous devriez voir le décalage être lié peu de temps après ce code :

TestDateAndTime = testDateAndTime.DateTime.Date ;

Décomposons-le :

  • Vous avez commencé avec DateTimeOffset 2008-05-01T08:06:32+01:00
  • Vous avez ensuite appelé .DateTime , ce qui a donné une valeur DateTime de 2008-05-01T08:06:32 avec DateTimeKind.Unspecified .
  • Vous avez ensuite appelé .Date , ce qui a abouti à une valeur DateTime de 2008-05-01T00:00:00 avec DateTimeKind.Unspecified .
  • Vous renvoyez le résultat dans testDateAndTime qui est de type DateTimeOffset . Cela provoque une conversion implicite de DateTime en DateTimeOffset qui applique le fuseau horaire local. Dans votre cas, il semble que le décalage de cette valeur dans votre fuseau horaire local soit -04:00 , donc la valeur résultante est DateTimeOffset 2008-05-01T00:00:00-04:00 comme vous l'avez décrit,

Vous avez dit:

L’objectif final est simplement d’avoir une date sans décalage horaire ni fuseau horaire.

Eh bien, il n’existe actuellement aucun type de données C# natif qui soit simplement une date sans heure. Il existe un type Date pur dans le package System.Time de corefxlab, mais il n'est pas tout à fait prêt pour une application de production typique. Il y a LocalDate dans la bibliothèque de temps de Noda, que vous pouvez utiliser aujourd'hui, mais vous devrez toujours le reconvertir en type natif avant de l'enregistrer dans la base de données. En attendant, le mieux que vous puissiez faire est de :

  • Modifiez votre serveur SQL pour utiliser le type de date dans ce champ.
  • Dans votre code .NET, utilisez DateTime avec l'heure 00:00:00 et DateTimeKind.Unspecified. Il faut penser à ignorer la partie horaire (puisqu'il existe effectivement des dates sans minuit local dans certains fuseaux horaires).
  • Remplacez l'alerte de test par DateTime plutôt que DateTimeOffset.

En général, même si DateTimeOffset convient à un grand nombre de scénarios (tels que les événements d'horodatage), il ne convient pas aux valeurs de date uniquement.

Je veux la date actuelle avec un décalage nul.

Si vous le voulez vraiment comme DateTimeOffset, vous feriez :

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

Cependant, je déconseille cela. En faisant cela, vous prenez la date locale de la valeur d'origine et affirmez qu'elle est en UTC. Si le décalage d'origine est autre que zéro, ce sera une fausse déclaration. Cela entraînera par la suite d'autres erreurs puisque vous parlez en réalité d'un moment différent (avec potentiellement une date différente) de celui que vous avez créé.

Concernant la question supplémentaire posée dans votre modification, la spécification de DateTimeKind.Utc modifie le comportement de la distribution implicite. Au lieu d'utiliser le fuseau horaire local, l'heure UTC est utilisée, qui présente toujours un décalage zéro. Le résultat est le même que le point de vue plus explicite que j'ai donné ci-dessus. Je déconseille toujours cela pour les mêmes raisons.

Regardons l'exemple du démarrage à partir du 2016-12-31T22:00:00-04:00. Selon votre approche, vous devez enregistrer 2016-12-31T00:00:00+00:00 dans la base de données. Cependant, ce sont deux moments différents. Le premier, normalisé en UTC, serait 2017-01-01T02:00:00+00:00, et le second, converti dans un autre fuseau horaire, serait 2016-12-30T20:00:00-04:00. Veuillez noter le changement de dates dans la conversion. Ce n'est probablement pas le comportement que vous souhaiteriez dans votre application.

L'option humaine ([vous devez vous inscrire pour voir le lien]).

L'essence du problème est la suivante.. Si vous avez accidentellement déployé une base de données sur un serveur SQL avec un « décalage de date » de 0, alors un problème survient lorsque la base de données contient un attribut de type TIME, c'est-à-dire cet attribut est défini sur 01. /01/0001 10:30:00 ou date enregistrée vide 01.01.0001 00:00:00. Lors de l'enregistrement de tels détails, ils ne sont pas enregistrés.
Sur Internet, ils suggèrent de créer une nouvelle base de données avec un décalage de 2000.
Mais je n’avais pas vraiment envie de créer une nouvelle base. Et modifiez le chemin d'accès à la base de données pour tous les utilisateurs.
Ensuite, j'ai suivi le chemin pour savoir où cette valeur est stockée dans SQL. Je l'ai trouvé et je l'ai changé en 2000 et tout allait bien.
Et maintenant, étape par étape, où changer.

Expulsez tous les utilisateurs.

ATTENTION!!!

1. Tout d'abord, faites une copie de sauvegarde à l'aide des outils 1C, c'est-à-dire téléchargez-le sur *.dt
Cela doit être fait avant de modifier le « décalage »
Si cela n'est pas fait, alors dans toute votre base de données il y aura des références, des documents, etc.
où y a-t-il une condition requise, la date sera disons 02.10.0009
CE QUI N'EST PAS AUTORISÉ...
Vous avez donc téléchargé sur *.dt

2. Accédez à SQL Server Management Studio
Trouvez votre base dans la liste et appuyez sur le signe plus.
Recherchez-y le dossier « Tables » et ouvrez-le.
Un tas de tables s'ouvriront, allez tout en bas, trouvez la table
_YearOffset, placez-vous dessus et sélectionnez l'élément « Ouvrir la table » avec le bouton droit, voir Fig. 1
Changez la valeur 0 en 2000
Fermer SQL Server Management Studio

3. Accédez au configurateur et chargez la base de données précédemment enregistrée.

Si cela n’est pas fait, alors toutes les dates seront avec l’année 0009.
Une fois la base de données chargée... Vous pouvez accéder à 1C et vous assurer que les dates sont normales.
Le résultat est que nous avons changé le « décalage de date de 0 à 2000 »

Il arrive parfois que cette option ne puisse pas être utilisée pour une raison ou une autre. Ensuite, il existe une option plus hardcore ([vous devez vous inscrire pour voir le lien]) :

Déclarez le curseur TablesAndFields pour

SELECT objets.nom comme nom de table, colonnes.nom comme nom de colonne
DE dbo.sysobjects comme objets
rejoindre à gauche dbo.syscolumns en tant que colonnes sur objects.id = columns.id
où objets.xtype = "U" et colonnes.xtype = 61

ouvrir TablesEtFields

PENDANT que @@FETCH_STATUS = 0
COMMENCER Exécuteur(" mise à jour"+ @NomTable + "
ensemble " + @NomColonne + " = ""2000- 01- 01 00:00:00" "
où " + @NomColonne + " > ""3999- 12- 31 23:59:59" "")

Ceci est exécuté tant que la récupération précédente réussit.
RÉCUPÉRER NEXT FROM TablesAndFields dans @TableName, @ColumnName
FIN

fermer TablesEtFields
deallocateTablesAndFields
aller

Avant toute manipulation, n'oubliez pas de faire des copies des bases de données !

Le problème n'a rien à voir avec la base de données. Si vous définissez un point d'arrêt ou entrez une sortie quelque part, vous devriez pouvoir voir le décalage être capturé peu de temps après ce code :

TestDateAndTime = testDateAndTime.DateTime.Date ;

Décomposons-le :

  • Vous avez commencé avec la valeur DateTimeOffset 2008-05-01T08:06:32+01:00
  • Vous avez ensuite appelé .DateTime , ce qui a donné la valeur DateTime 2008-05-01T08:06:32 avec DateTimeKind.Unspecified .
  • Vous avez ensuite appelé .Date , ce qui a abouti à une valeur DateTime de 2008-05-01T00:00:00 avec DateTimeKind.Unspecified .
  • Vous attribuez le résultat à testDateAndTime , qui est de type DateTimeOffset . Cela provoque une conversion implicite de DateTime en DateTimeOffset - , qui s'applique locale Fuseau horaire. Dans votre cas, il semble que le décalage de cette valeur dans votre fuseau horaire local soit -04:00 , donc la valeur résultante est DateTimeOffset de 2008-05-01T00:00:00-04:00 comme vous l'avez décrit.

Vous avez dit:

Le but ultime est simplement d’avoir une date sans décalage horaire ni fuseau horaire.

Eh bien, il y a actuellement pas un type de données C# natif, qui est juste une date sans heure. Il existe un type Date pur dans Le temps du système package dans corefxlab, mais il n'est pas encore tout à fait prêt pour une application de production typique. Il existe un LocalDate dans la bibliothèque Noda Time que vous pouvez utiliser aujourd'hui, mais vous devrez toujours le reconvertir en un type natif avant de l'enregistrer dans la base de données. En attendant, le mieux que vous puissiez faire est de :

  • Modifiez votre serveur SQL pour utiliser le type de date dans le champ.
  • Dans votre code .NET, utilisez DateTime avec l'heure 00:00:00 et DateTimeKind.Unspecified. Il faut penser à ignorer la partie horaire (puisqu'il existe effectivement des dates sans minuit local dans certains fuseaux horaires).
  • Modifiez l'accessoire de test pour qu'il soit un DateTime plutôt qu'un DateTimeOffset.

En général, même si DateTimeOffset convient à un grand nombre de scénarios (par exemple horodatagesévénements), cela ne convient pas bien aux valeurs de date uniquement.

Je veux la date actuelle avec un décalage nul.

Si tu vraiment envie c'est comme DateTimeOffset , vous pouvez faire :

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

Cependant, je ne recommande pas de faire cela. En faisant cela, vous prenez locale la date de la valeur d'origine et affirmez qu'elle est en UTC. Si le décalage d'origine est autre que zéro, ce sera une fausse déclaration. Cela entraînera par la suite d'autres erreurs puisque vous parlez en réalité d'un moment différent (avec potentiellement une date différente) de celui que vous avez créé.

Concernant la question supplémentaire posée à votre conseil d'administration. La spécification de DateTimeKind.Utc modifie le comportement de la distribution implicite. Au lieu d'utiliser le fuseau horaire local, l'heure UTC est utilisée, qui présente toujours un décalage zéro. Le résultat est le même que le point de vue plus explicite que j'ai donné ci-dessus. Je déconseille toujours cela pour les mêmes raisons.

Prenons un exemple commençant par 2016-12-31T22:00:00-04:00. Selon votre approche, vous devez enregistrer 2016-12-31T00:00:00+00:00 dans la base de données. Cependant, ce sont deux moments différents. Le premier, normalisé en UTC, serait 2017-01-01T02:00:00+00:00, et le second, converti dans un autre fuseau horaire, serait 2016-12-30T20:00:00-04:00. Veuillez noter le changement de dates dans la conversion. Ce n'est probablement pas le comportement que vous souhaiteriez dans votre application.

Publications sur le sujet