2009-08-13 9 views
17

Ho uno scenario in cui ho uno sfasamento del fuso orario (in minuti) e ho bisogno di determinare il fuso orario per esso. So che tutti i dati non sono disponibili (ad esempio, potrebbero esserci diversi fusi orari con un offset di -240 minuti) ma una "ipotesi migliore" è accettabile.Come posso determinare un fuso orario in base all'offset UTC?

mio primo passaggio si presentava così:

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

Questa sorta funziona, ma ho bisogno di spiegare legale che mi sta gettando via un po '. Ho aggiunto questa terribile mod:

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 
    } 
} 

Questo funziona "abbastanza bene" nel senso che posso mostrare all'utente il momento giusto per loro quando l'ora legale non è a tutti gli effetti e sono circa il 70% corretto durante l'ora legale. Comunque ... questo è un codice terribile per i miei occhi.

C'è un modo migliore per farlo? Più eleganza sarebbe buona, e più precisione sarebbe ancora meglio.

Aggiornamento

Tecnicamente ho accesso a tutte le informazioni Javascript può ottenere per quanto riguarda la data. Ho una pagina in cui ho inserito un campo nascosto chiamato "offset". Ho una funzione JQuery che popola il campo offset con DateTime(). GetTimezoneOffset(). Mentre non vedo nulla sull'oggetto DateTime che possa essere d'aiuto, forse questo aprirà altre strade per le idee.

+0

@Sailing Judo: ho aggiunto del codice alla mia risposta, che consente a Javascript di convertire un timestamp universale in uno locale. – Kip

risposta

16

Risposta breve: non è possibile.

L'ora legale lo rende impossibile. Ad esempio, non vi è alcun modo per determinare, esclusivamente con offset UTC, la differenza tra Arizona e California in estate, o Arizona e New Mexico in inverno (poiché l'Arizona non osserva l'ora solare).

C'è anche il problema dell'ora in cui i diversi paesi osservano l'ora legale. Ad esempio, nel DST statunitense inizia prima e termina più tardi che in Europa.

Un'ipotesi vicina è possibile (vale a dire +/- un'ora), ma se la si utilizza per visualizzare il tempo per gli utenti, si visualizzerà inevitabilmente il momento sbagliato per alcuni di essi.


aggiornamento: Dai commenti, sembra che il vostro obiettivo primario è quello di visualizzare un timestamp nel fuso orario locale dell'utente. Se questo è ciò che vuoi fare, devi inviare l'ora come timestamp UTC, e poi semplicemente riscriverlo sul browser dell'utente con Javascript. Nel caso in cui non abbiano Javascript abilitato, vedrebbero comunque un timestamp UTC utilizzabile. Ecco una funzione che ho trovato in this question, che ho usato in this Greasemonkey script. Si consiglia di modificarlo in base alle proprie esigenze.

//@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; 
} 

Ecco una funzione che utilizzo sul mio blog per visualizzare un timestamp analizzato nel fuso orario locale dell'utente. Di nuovo, puoi modificarlo nel formato che desideri.

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

Questo è vero, un offset da solo non è abbastanza informazioni per determinare il fuso orario. Qualche altra informazione a cui hai accesso? Puoi chiedere a un utente un fuso orario? –

+0

@Matt: tecnicamente posso avere accesso a qualsiasi cosa Javascript possa dirmelo ma non vedo nulla sull'oggetto javascript DateTime che verrà restituito se il client è attualmente in DST o meno. –

+0

@Matt: Inoltre, questo intero esercizio è un tentativo di NON infastidire l'utente per informazioni se posso in qualche modo ottenerlo per me stesso. Poiché l'utente per un fuso orario è l'ultima risorsa assoluta. In effetti, avere un'ipotesi * per lo più * accurata al fuso orario è meglio che chiedere esplicitamente (nel mio caso). –

5

Conoscendo solo l'offset da UTC, non si può dire che cosa fuso orario ci si trova, a causa della DST. Potresti considerare di considerare la parte temporale del tempo per cercare di indovinare se la DST fosse o meno in vigore, ma le considerazioni politiche lo rendono quasi impossibile, poiché le diverse giurisdizioni modificano la definizione di DST.

1

Con alcuni trucchetti è possibile correggere il 99% delle volte e chiudere l'altro 1%. Controlla jstimezonedetect per un'implementazione estremamente completa.

L'approccio di un uomo povero sarebbe quello di mappare manualmente ogni offset di fuso orario riportato possibile secondo la tua ipotesi migliore. Dal momento che stai indovinando potresti anche essere esplicito a riguardo!

Problemi correlati