2009-08-13 27 views
17

Tengo un escenario en el que tengo un desplazamiento de zona horaria (en minutos) y necesito determinar la zona horaria para él. Sé que todos los datos no están disponibles (por ejemplo, puede haber varias zonas horarias con un desplazamiento de -240 minutos), pero una "mejor conjetura" es aceptable.¿Cómo puedo determinar una zona horaria por el desplazamiento UTC?

Mi primer paso era la siguiente:

foreach (var info in TimeZoneInfo.GetSystemTimeZones()) 
{ 
    if (info.BaseUtcOffset.TotalMinutes == timezoneOffset) 
    { 
     // do something here if this is a valid timezone 
    } 
} 

Este sorta funciona, pero tengo que dar cuenta de los cambios de horario que me está arrojando un poco. He añadido esta terrible truco:

foreach (var info in TimeZoneInfo.GetSystemTimeZones()) 
{ 
    var extra = info.IsDaylightSavingTime(DateTime.Now) ? 60 : 0; 
    if (info.BaseUtcOffset.TotalMinutes + extra == timezoneOffset) 
    { 
     // do something here if this is a valid timezone 
    } 
} 

Esto funciona "bastante bien" en el que puedo mostrar al usuario el tiempo correcto para ellos cuando no es el horario de verano, en efecto, y estoy cerca del 70% correcta durante el horario de verano. Aún así ... este es un código horrible para mis ojos.

¿Hay una mejor manera de hacerlo? Más elegancia sería buena, y más precisión sería aún mejor.

actualización

Técnicamente tengo acceso a cualquier información Javascript puede obtener con respecto a la fecha. Tengo una página en la que coloqué un campo oculto llamado "desplazamiento". Tengo una función JQuery que rellena el campo de desplazamiento con DateTime(). GetTimezoneOffset(). Si bien no veo nada en el objeto DateTime que pueda ayudar, quizás esto abra otras vías para obtener ideas.

+0

@Sailing Judo: He agregado un código a mi respuesta, que permite a Javascript convertir una marca de tiempo universal en una local. – Kip

Respuesta

16

Respuesta corta: no se puede.

El horario de verano es imposible. Por ejemplo, no hay forma de determinar, únicamente a partir del desplazamiento UTC, la diferencia entre Arizona y California en el verano, o Arizona y Nuevo México en el invierno (ya que Arizona no observa el horario de verano).

También existe la cuestión de a qué hora diferentes países observan el horario de verano. Por ejemplo, en los Estados Unidos, el horario de verano comienza antes y finaliza más tarde que en Europa.

Se puede hacer una aproximación aproximada (es decir, +/- una hora), pero si la está utilizando para mostrar la hora a los usuarios, inevitablemente se mostrará el momento incorrecto para algunos de ellos.


actualización: A partir de los comentarios, parece que su objetivo principal es mostrar una marca de tiempo en la zona horaria local del usuario. Si eso es lo que desea hacer, debe enviar la hora como una marca de tiempo UTC, y luego simplemente reescribirla en el navegador del usuario con Javascript. En el caso de que no tengan Javascript habilitado, aún verían una marca de tiempo UTC utilizable. Aquí hay una función que se me ocurrió en this question, que utilicé en this Greasemonkey script. Es posible que desee ajustarlo para satisfacer sus necesidades.

//@param timestamp An ISO-8601 timestamp in the form YYYY-MM-DDTHH:MM:SS±HH:MM 
//Note: Some other valid ISO-8601 timestamps are not accepted by this function 
function parseISO8601(timestamp) 
{ 
    var regex = new RegExp("^([\\d]{4})-([\\d]{2})-([\\d]{2})T([\\d]{2}):([\\d]{2}):([\\d]{2})([\\+\\-])([\\d]{2}):([\\d]{2})$"); 
    var matches = regex.exec(timestamp); 
    if(matches != null) 
    { 
    var offset = parseInt(matches[8], 10) * 60 + parseInt(matches[9], 10); 
    if(matches[7] == "-") 
     offset = -offset; 

    return new Date(
     Date.UTC(
     parseInt(matches[1], 10), 
     parseInt(matches[2], 10) - 1, 
     parseInt(matches[3], 10), 
     parseInt(matches[4], 10), 
     parseInt(matches[5], 10), 
     parseInt(matches[6], 10) 
    ) - offset*60*1000 
    ); 
    } 
    return null; 
} 

Aquí es una función que uso en mi blog para mostrar una marca de tiempo analizado en la zona horaria local del usuario. De nuevo, puede ajustarlo al formato que desee.

var weekDays = new Array("Sunday", "Monday", "Tuesday", "Wednesday", 
     "Thursday", "Friday", "Saturday"); 
var months = new Array("January", "February", "March", "April", "May", "June", 
     "July", "August", "September", "October", "November", "December"); 

function toLocalTime(date) 
{ 
    var hour = date.getHours(); 
    var ampm = (hour < 12 ? "am" : "pm"); 
    hour = (hour + 11)%12 + 1; 

    var minutes = date.getMinutes(); 
    if(minutes < 10) 
    minutes = "0" + minutes; 

    return weekDays[date.getDay()] + ", " 
     + months[date.getMonth()] + " " 
     + date.getDate()   + ", " 
     + date.getFullYear()  + " at " 
     + hour     + ":" 
     + minutes     + " " 
     + ampm; 
} 
+0

Esto es cierto, un desplazamiento solo no es información suficiente para determinar la zona horaria. ¿Alguna otra información a la que tiene acceso? ¿Puedes pedirle a un usuario un huso horario? –

+0

@Matt: Técnicamente, puedo tener acceso a todo lo que Javascript pueda decirme, pero no veo nada en el objeto DateTime de javascript que volverá si el cliente se encuentra actualmente en horario de verano o no. –

+0

@Matt: Además, todo este ejercicio es un intento de NO molestar al usuario por información si de alguna manera puedo obtenerlo para mí. Como el usuario de una zona horaria es el último recurso absoluto. De hecho, tener una * mayor * precisión exacta en la zona horaria es mejor que pedir directamente (en mi caso). –

5

Conociendo solo el desplazamiento de UTC, no puede decir en qué zona horaria se encuentra, debido a DST. Podría considerar buscar en el tiempo parte del tiempo para tratar de adivinar si el horario de verano estuvo vigente entonces o no, pero las consideraciones políticas lo hacen casi imposible, ya que las diferentes jurisdicciones cambian la definición de horario de verano.

1

Con algunos trucos puede estar en lo correcto el 99% del tiempo y cerrar el otro 1%. Consulte jstimezonedetect para una implementación extremadamente completa.

El enfoque de un pobre sería mapear manualmente cada posible compensación de zona horaria reportada a su mejor estimación. ¡Ya que estás adivinando, podrías ser explícito al respecto!

Cuestiones relacionadas