c# - specifykind - findsystemtimezonebyid mexico
Tengo problemas para convertir mi DateTime a UTC (5)
Como dice dtb, debe usar DateTimeOffset
si desea almacenar una fecha / hora con un huso horario específico.
Sin embargo, no está del todo claro por tu publicación que realmente lo necesites. Solo da ejemplos usando DateTime.Now
y dice que está adivinando que está usando la hora del servidor. ¿A qué hora realmente quieres? Si solo desea la hora actual en UTC, use DateTime.UtcNow
o DateTimeOffset.UtcNow
. No necesita saber la zona horaria para conocer la hora UTC actual, precisamente porque es universal.
Si obtiene una fecha / hora del usuario de alguna otra manera, brinde más información, de esa manera podremos determinar qué necesita hacer. De lo contrario, solo estamos adivinando.
Estoy almacenando todas mis fechas en formato UTC en mi base de datos. Le pregunto al usuario por su zona horaria y quiero usar su zona horaria más lo que supongo que es la hora del servidor para averiguar el UTC para ellos.
Una vez que tenga eso, quiero hacer una búsqueda para ver cuál es el rango en la base de datos usando su fecha UTC recién convertida.
pero siempre obtengo esta excepción.
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"
No sé por qué estoy recibiendo esto.
Intenté 2 maneras
TimeZoneInfo zone = TimeZoneInfo.FindSystemTimeZoneById(id);
// I also tried DateTime.UtcNow
DateTime now = DateTime.SpecifyKind(DateTime.Now, DateTimeKind.Local);
var utc = TimeZoneInfo.ConvertTimeToUtc(now , zone );
Esto falló así que me cansé
DateTime now = DateTime.SpecifyKind(DateTime.Now, DateTimeKind.Local);
var utc = TimeZoneInfo.ConvertTimeBySystemTimeZoneId(now,
ZoneId, TimeZoneInfo.Utc.Id);
Esto también falló con el mismo error. ¿Qué estoy haciendo mal?
¿Editar esto funcionaría?
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);
Editar 2 @ Jon Skeet
Ya estaba pensando que quizás ni siquiera necesite hacer todo esto. Las cosas del tiempo me confunden ahora, así que es por eso que la publicación puede no ser tan clara como debería ser. Nunca sé qué diablos está recibiendo DateTime.Now (Intenté cambiar mi zona horaria a otra zona horaria y seguía obteniendo mi hora local).
Esto es lo que quería que hiciera mi trabajo. El usuario llega al sitio agrega un poco de alerta y ahora se guarda como utc (antes de que fuera DateTime.Now y luego alguien sugirió almacenar todo UTC).
Entonces, antes de que un usuario ingresara a mi sitio y dependiendo de dónde estaba mi servidor de hosting, podría ser al día siguiente. Entonces, si se dijo que la alerta se mostraría el 30 de agosto (su hora), pero con la diferencia horaria del servidor, podrían aparecer el 29 de agosto y se mostraría la alerta.
Así que quería combatir eso. Entonces, ¿no estoy seguro de si solo debo almacenar su hora local y luego usar estas cosas de compensación? O simplemente almacene la hora UTC. Con solo almacenar el tiempo UTC podría ser incorrecto ya que el usuario aún estaría pensando en la hora local y no estoy seguro de cómo realmente funciona el UTC, pero podría terminar una diferencia de tiempo.
Edit3
var info = TimeZoneInfo.FindSystemTimeZoneById(id)
DateTimeOffset usersTime = TimeZoneInfo.ConvertTime(DataBaseUTCDate,
TimeZoneInfo.Utc, info);
La estructura DateTime
solo admite dos zonas horarias:
- La zona horaria local en la que se está ejecutando la máquina
- y UTC.
Eche un vistazo a la estructura 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);
Salida:
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
La respuesta de todos los demás parece demasiado compleja. Tenía un requisito específico y esto funcionó bien para mí:
void Main()
{
var startDate = DateTime.Today;
var StartDateUtc = TimeZoneInfo.ConvertTimeBySystemTimeZoneId(DateTime.SpecifyKind(startDate.Date, DateTimeKind.Unspecified), "Eastern Standard Time", "UTC");
startDate.Dump();
StartDateUtc.Dump();
}
Que salidas (de linqpad) lo que esperaba:
20/12/2013 12:00:00 a.m.
20/12/2013 5:00:00 a.m.
Apoyos a Slaks para la sugerencia de tipo no especificado. Eso es lo que me estaba perdiendo. Pero todo lo que se dice sobre el hecho de que solo hay dos clases de fechas (local y UTC) simplemente me confundió el problema.
FYI - la máquina con la que ejecuté esto estaba en la zona horaria central y el horario de verano no estaba en efecto.
Necesita configurar el Kind
a No Unspecified
, así:
DateTime now = DateTime.SpecifyKind(DateTime.Now, DateTimeKind.Unspecified);
var utc = TimeZoneInfo.ConvertTimeToUtc(now , zone);
DateTimeKind.Local
significa la zona horaria local y no cualquier otra zona horaria. Es por eso que estabas recibiendo el error.
UTC es solo una zona horaria en la que todos estuvieron de acuerdo como zona horaria estándar. Específicamente, es una zona horaria que contiene Londres, Inglaterra. EDITAR : tenga en cuenta que no es exactamente la misma zona horaria; por ejemplo, UTC no tiene horario de verano. (Gracias, Jon Skeet)
Lo único especial de UTC es que es mucho más fácil de usar en .Net que cualquier otra zona horaria ( DateTime.UtcNow
, DateTime.ToUniversalTime
y otros miembros).
Por lo tanto, como otros lo han mencionado, lo mejor que puede hacer es almacenar todas las fechas en UTC dentro de su base de datos y luego convertirlas a la hora local del usuario (escribiendo TimeZoneInfo.ConvertTime(time, usersTimeZone)
antes de mostrarlas.
Si quieres ser más elegante, puedes geolocate las direcciones IP de tus usuarios para adivinar automáticamente sus zonas horarias.