Je stocke toutes mes dates au format UTC dans ma base de données. Je demande à l'utilisateur son fuseau horaire et je veux utiliser son fuseau horaire plus ce que je suppose, c'est le temps du serveur pour comprendre l'UTC pour lui.
Une fois que je l'ai, je veux faire une recherche pour voir ce qui est dans la base de données en utilisant leur date UTC nouvellement convertie.
mais je reçois toujours cette exception.
System.ArgumentException was unhandled by user code
Message="The conversion could not be completed because the
supplied DateTime did not have the Kind property set correctly.
For example, when the Kind property is DateTimeKind.Local,
the source time zone must be TimeZoneInfo.Local.
Parameter name: sourceTimeZone"
Je ne sais pas pourquoi je reçois ça.
J'ai essayé 2 façons
TimeZoneInfo zone = TimeZoneInfo.FindSystemTimeZoneById(id);
// I also tried DateTime.UtcNow
DateTime now = DateTime.SpecifyKind(DateTime.Now, DateTimeKind.Local);
var utc = TimeZoneInfo.ConvertTimeToUtc(now , zone );
Cela a échoué alors je suis fatigué
DateTime now = DateTime.SpecifyKind(DateTime.Now, DateTimeKind.Local);
var utc = TimeZoneInfo.ConvertTimeBySystemTimeZoneId(now,
ZoneId, TimeZoneInfo.Utc.Id);
Cela a également échoué avec la même erreur. Qu'est-ce que je fais mal?
Modifier cela fonctionnerait-il?
DateTime localServerTime = DateTime.SpecifyKind(DateTime.Now, DateTimeKind.Local);
TimeZoneInfo info = TimeZoneInfo.FindSystemTimeZoneById(id);
var usersTime = TimeZoneInfo.ConvertTime(localServerTime, info);
var utc = TimeZoneInfo.ConvertTimeToUtc(usersTime, userInfo);
Modifier 2 @ Jon Skeet
Oui, je pensais juste que je n'aurais peut-être même pas besoin de faire tout ça. Le temps me déroute en ce moment, c'est pourquoi le message n'est peut-être pas aussi clair qu'il devrait l'être. Je ne sais jamais ce que diable DateTime.Now obtient (j'ai essayé de changer mon fuseau horaire en un autre fuseau horaire et il a continué à obtenir mon heure locale).
C'est ce que je voulais que mes trucs fassent. L'utilisateur vient sur le site ajoute une alerte et il est maintenant enregistré en tant qu'utc (avant c'était DateTime.Maintenant, quelqu'un a suggéré de stocker tout UTC).
Donc, avant qu'un utilisateur ne vienne sur mon site et en fonction de l'emplacement de mon serveur d'hébergement, cela pourrait être le lendemain. Donc, si l'alerte devait être affichée le 30 août (leur heure) mais avec le décalage horaire du serveur, ils pourraient venir le 29 août et l'alerte serait affichée.
Je voulais donc combattre cela. Alors maintenant, je ne sais pas si je dois simplement stocker leur heure locale, puis utiliser ce truc de décalage? Ou enregistrez simplement l'heure UTC. Le simple fait de stocker l'heure UTC pourrait toujours être faux, car l'utilisateur penserait probablement à l'heure locale et je ne sais pas comment UTC fonctionne vraiment, il pourrait encore y avoir une différence de temps.
Modifier3
var info = TimeZoneInfo.FindSystemTimeZoneById(id)
DateTimeOffset usersTime = TimeZoneInfo.ConvertTime(DataBaseUTCDate,
TimeZoneInfo.Utc, info);
La structure DateTime
ne prend en charge que deux fuseaux horaires:
Jetez un œil à la structure DateTimeOffset .
var info = TimeZoneInfo.FindSystemTimeZoneById("Tokyo Standard Time");
DateTimeOffset localServerTime = DateTimeOffset.Now;
DateTimeOffset usersTime = TimeZoneInfo.ConvertTime(localServerTime, info);
DateTimeOffset utc = localServerTime.ToUniversalTime();
Console.WriteLine("Local Time: {0}", localServerTime);
Console.WriteLine("User's Time: {0}", usersTime);
Console.WriteLine("UTC: {0}", utc);
Production:
Local Time: 30.08.2009 20:48:17 +02:00
User's Time: 31.08.2009 03:48:17 +09:00
UTC: 30.08.2009 18:48:17 +00:00
Vous devez définir Kind
sur Unspecified
, comme ceci:
DateTime now = DateTime.SpecifyKind(DateTime.Now, DateTimeKind.Unspecified);
var utc = TimeZoneInfo.ConvertTimeToUtc(now , zone);
DateTimeKind.Local
signifie le fuseau horaire local, et aucun autre fuseau horaire. C'est pourquoi vous obtenez l'erreur.
Comme le dit dtb, vous devez utiliser DateTimeOffset
si vous souhaitez stocker une date/heure avec un fuseau horaire spécifique.
Cependant, il n'est pas du tout clair de votre message que vous en avez vraiment besoin. Vous donnez uniquement des exemples en utilisant DateTime.Now
et vous dites que vous devinez que vous utilisez l'heure du serveur. Quelle heure voulez-vous réellement? Si vous voulez simplement l'heure actuelle en UTC, utilisez DateTime.UtcNow
ou DateTimeOffset.UtcNow
. Vous n'avez pas besoin de connaître le fuseau horaire pour connaître l'heure UTC actuelle, précisément parce qu'il est universel.
Si vous obtenez une date/heure de l'utilisateur d'une autre manière, veuillez donner plus d'informations - de cette façon, nous serons en mesure de déterminer ce que vous devez faire. Sinon, nous devinons juste.
La réponse de tous les autres semble trop complexe. J'avais une exigence spécifique et cela a bien fonctionné pour moi:
void Main()
{
var startDate = DateTime.Today;
var StartDateUtc = TimeZoneInfo.ConvertTimeBySystemTimeZoneId(DateTime.SpecifyKind(startDate.Date, DateTimeKind.Unspecified), "Eastern Standard Time", "UTC");
startDate.Dump();
StartDateUtc.Dump();
}
Quelles sorties (de linqpad) ce que j'attendais:
20/12/2013 12:00:00 AM
20/12/2013 05:00:00 AM
Props to Slaks pour l'astuce non spécifiée. C'est ce qui me manquait. Mais tout le discours sur le fait qu'il n'y a que deux types de dates (locales et UTC) vient embrouiller le problème pour moi.
Pour info - la machine sur laquelle je l'ai exécuté était dans le fuseau horaire central et l'heure d'été n'était pas en vigueur.
UTC est juste un fuseau horaire que tout le monde a convenu comme fuseau horaire standard. Plus précisément, c'est un fuseau horaire qui contient Londres, en Angleterre. [~ # ~] modifier [~ # ~] : Notez que ce n'est pas exactement le même fuseau horaire; par exemple, UTC n'a pas d'heure d'été. (Merci, Jon Skeet)
La seule particularité de l'UTC est qu'il est beaucoup plus facile à utiliser dans .Net que tout autre fuseau horaire (DateTime.UtcNow
, DateTime.ToUniversalTime
Et autres membres).
Par conséquent, comme d'autres l'ont mentionné, la meilleure chose à faire est de stocker toutes les dates en UTC dans votre base de données, puis de les convertir en heure locale de l'utilisateur (en écrivant TimeZoneInfo.ConvertTime(time, usersTimeZone)
avant de l'afficher.
Si vous voulez être plus amateur, vous pouvez géolocaliser les adresses IP de vos utilisateurs pour deviner automatiquement leurs fuseaux horaires.