Berechnen Sie den Zeitzonen-Offset nur für eine bestimmte Zeitzone

Lesezeit: 10 Minuten

Berechnen Sie den Zeitzonen Offset nur fur eine bestimmte Zeitzone
Petar Karagenov

Ich versuche, eine App für eine Person zu erstellen, die online unterrichtet und in Deutschland ansässig ist. Ich möchte den Zeitplan der Person in einer Reihe von Terminstartzeiten speichern. Zum Beispiel:

let schedule = [
  new Date(`${currentDate}T07:00:00Z`),
  new Date(`${currentDate}T08:00:00Z`),
  new Date(`${currentDate}T09:00:00Z`)
  ...
]

Das Problem ist, dass es in manchen Ländern, wie Deutschland, Standart- und Sommerzeiten gibt. Während also im Sommer die Startzeiten in Deutschland 9:00, 10:00 und 11:00 Uhr wären, verschiebt man sich im Winter eine Stunde früher. Gleichzeitig bleiben sie in Ländern wie Singapur gleich: 15:00, 16:00, 17:00 … Was muss ich tun, damit die Startzeiten in Deutschland das ganze Jahr über stabil bleiben und sich anderswo ändern bzw:

if (summerTimeInGermany) {
  schedule = [
    new Date(`${currentDate}T07:00:00Z`), // 9:00 in Germany
    new Date(`${currentDate}T08:00:00Z`), // 10:00
    new Date(`${currentDate}T09:00:00Z`) // 11:00
    ...
  ]
} else {
  schedule = [
    new Date(`${currentDate}T08:00:00Z`), // 9:00
    new Date(`${currentDate}T09:00:00Z`), // 10:00
    new Date(`${currentDate}T10:00:00Z`) // 11:00
    ...
  ]
}

Diese Terminliste benötige ich, um sie mit der Liste der Termine pro Tag, die ich aus Google Calender hole, abzugleichen und die bereits vergebenen auszuschließen.

  • Es ist nicht wirklich ein Duplikat Ihrer Frage, aber die Antwort auf diese Frage sollte Ihnen helfen, Ihr Problem zu lösen: stackoverflow.com/questions/11887934/…

    – Eiswürfel

    22. April 2020 um 9:51 Uhr

  • Ich hatte diesen Beitrag schon einmal überprüft, konnte aber nicht herausfinden, wie ich ihn verwenden sollte. Das Problem ist, dass ich unabhängig vom Offset das gleiche Ergebnis für Deutschland brauche.

    – Petar Karagenow

    22. April 2020 um 10:01 Uhr

  • @icecub – diese Antwort (Wie überprüfe ich, ob die Sommerzeit (DST) in Kraft ist und ob es sich um einen Offset handelt?) bezieht sich darauf, wo der Code auf einem lokalen Computer ausgeführt wird. Soweit ich das OP verstehe, besteht die Anforderung darin, eine UTC-Zeichenfolge zu generieren, die eine bestimmte Zeit in einer anderen Zeitzone darstellt, also unabhängig von den Hosteinstellungen.

    – RobG

    22. April 2020 um 22:16 Uhr


1647123309 763 Berechnen Sie den Zeitzonen Offset nur fur eine bestimmte Zeitzone
RobG

Ich denke, Sie versuchen, einen UTC-Zeitstempel basierend auf einem Zeitstempel in einer anderen Zeitzone und unter Angabe des repräsentativen IANA-Standorts zu generieren.

Eine Möglichkeit, dies zu tun, besteht darin, ein Datum für den Standort mit dem Zeitstempel als UTC zu generieren und zu sehen, wie der Unterschied in Stunden und Minuten ist. Das sollte der Ausgleich sein. Wenden Sie dann den Offset auf den ursprünglichen Zeitstempel an. Dadurch sollte dann ein Zeitstempel mit dem erforderlichen Datum und der erforderlichen Uhrzeit für den Zielort generiert werden, wenn der Zeitzonenoffset angewendet wird.

Die folgende Funktion implementiert diesen Algorithmus unter Verwendung von Intl.DateTimeFormat und dem repräsentativen IANA-Standort. Es wurde nur leicht getestet, also bitte weiter testen. Es führt eine Schleife für die Anpassungen aus, um zu überprüfen, ob das Anwenden des Offsets das Datum nicht über eine DST-Grenze verschiebt und daher das Offset neu anpassen muss.

Standardmäßig gibt es einen ISO 8601 UTC-Zeitstempel für die entsprechende Zeit zurück, falls dies optional ist RückgabeOffset Parameter eingestellt ist truegibt es stattdessen den Offset zurück.

Ich habe Beispiele für Standard- und Sommerzeitstempel sowohl östlich als auch westlich von GMT bereitgestellt (aber nicht viele). Bitte gründlich testen und nach Bedarf anpassen.

/* @param {string} isoString - ISO 8601 timestamp without timezone
**                             e.g. YYYY-MM-DDTHH:mm:ss or YYYY-MM-DD HH:mm:ss
** @param {string} loc - IANA representateive location
**                       e.g. Europe/Berlin
** @param {boolean} returnOffset - if true, return the offset instead of timestamp
** @returns {string} if returnOffset is true, offset is ±HH:mm[:ss] (seconds only if not zero)
**                   if returnOffset is false, equivalent ISO 8601 UTC timestamp
*/
let getUTCTime = (function() {

  let n = 'numeric';
  let formatterOpts = {year:n, month:n, day:n, hour:n, minute:n, second:n, hour12: false};

  // Parse YYYY-MM-DDTHH:mm:ss as UTC (T can be space)
  function parse (isoString) {
    let [Y,M,D,H,m,s] = isoString.split(/[\DT\s]/);
    return new Date(Date.UTC(Y,M-1,D,H,m,s));
  }
  
  // Get date parts, use supplied formatter
  function toParts(date, formatter) {
    return formatter.formatToParts(date).reduce((acc, part) => {
      acc[part.type] = part.value;
      return acc;
    }, Object.create(null));
  }

  return function (isoString, loc, returnOffset = false) {
 
    // Update formatter options with loc so get target loc values
    formatterOpts.timeZone = loc;
    // Formatter
    let formatter = new Intl.DateTimeFormat('en', formatterOpts);
  
    // Parse input string as UTC
    let oDate = parse(isoString);
    // Date to adjust to wanted values
    let utcDate = new Date(oDate);

    // maxLoops limits do..while in dilemma zone, ensures sensible value
    let maxLoops = 3,
        p, diff;

    // Adjust utcDate so it generates required local date values
    // Adjustment may shift over DST boundary so may need 2nd adjustment
    // Limit number of loops (shouldn't be required but just in case...)
    do {
      // Get date parts in target timezone
      p = toParts(utcDate, formatter);
   
      // Get difference between local and adjusted values
      diff = new Date(Date.UTC(p.year, p.month-1, p.day, p.hour, p.minute, p.second)) - oDate;
   
      // If necessary, adjust utcDate so it generates required values when shifted
      if (diff) {
        utcDate.setTime(utcDate.getTime() - diff);
      }
    // Loop until generated values match original or maxLoops
    } while (diff && maxLoops--)
    
    // If maxLoops is -1, hit DST dilemma zone: time doesn't exist on that date
    // E.g. going into daylight saving at 02:00, then 02:30 doesn't exist
    // and loop will flip in/out of DST until stopped by maxLoops
    // So generate valid date and offset in DST period
    let dDiff = null;
    if (maxLoops < 0) {
      p = toParts(utcDate, formatter);
      dDiff = Date.UTC(p.year, p.month - 1, p.day, p.hour, p.minute, p.second) - utcDate;
      let msg = isoString + ' does not exist at ' + loc + ' due to ' +
                'daylight saving change-over, shifting into DST';
      // console.log(msg);
      // throw new RangeError(msg);
    }

    // Convert diff between local and adjusted to get ±HH:mm offset
    // Use dilemma diff (dDiff) if has been set
    let oDiff = dDiff || oDate - utcDate;
    let sign = oDiff > 0? '+' : '-';
    oDiff = Math.abs(oDiff);
//    console.log(sign + new Date(oDiff).toISOString().substring(11,19).replace(/:00$/,''));
    let offH = oDiff / 3.6e6 | 0;
    let offM = (oDiff % 3.6e6) / 6e4 | 0;
    let offS = (oDiff % 6e4) / 1e3 | 0;

    let z = n=>(n<10?'0':'')+n;
    // Return offset (with offset seconds if not zero) or ISO 8601 UTC string
    return returnOffset? `${sign}${z(offH)}:${z(offM)}${offS? ':' + z(offS) : ''}` :
                         utcDate.toISOString();
  }
})();

// Given a local timestmap in format YYYY-MM-DDTHH:mm:ss and
// loc as IANA representative location
// Return equivalent ISO 8061 UTC timestmap
function getUTCString(timestamp, loc) {
  return getUTCTime(timestamp, loc);
}
// Given a local timestmap in format YYYY-MM-DDTHH:mm:ss and
// loc as IANA representative location
// Return offset at loc as ±HH:mm[:ss]
//  - seconds only included if not zero (typically pre-1900)
function getUTCOffset(timestamp, loc) {
  return getUTCTime(timestamp, loc, true);
}

// Examples
window.onload = function() {
  let t = document.getElementById('t0');
  let params = ['Local time', 'UTC time', false];
  let showData = (localTime, loc, offset, timeUTC) => {
    let row = t.insertRow();
    [localTime, loc, timeUTC, null, null].forEach((s, i) => {
      cell = row.insertCell();
      cell.textContent = i == 0? localTime.replace('T',' '):
                         i == 1? loc:
                         i == 2? offset  :
                         i == 3? timeUTC :
                         new Date(timeUTC).toLocaleString('en-CA', {timeZone: loc, hour12: false}).replace(',','') ;
    });
    return new Date(timeUTC).toLocaleString('en-CA', {timeZone: loc, hour12: false}).replace(',','');
  };
  // Local time required   Location
  [['2020-04-22T09:00:00','Europe/Berlin'],   // DST offset +2
   ['2020-01-22T09:00:00','Europe/Berlin'],   // Std offset +1
   ['2020-04-22T09:00:00','America/Denver'],  // DST offset -6
   ['2020-01-22T09:00:00','America/Denver'],  // Std offset -7
   ['2020-04-22T09:00:00','US/Aleutian'],     // DST offset -9
   ['2020-01-22T09:00:00','US/Aleutian'],     // Std offset -10
   ['2020-01-22T09:00:00','Pacific/Honolulu'],// Std offset -11
   ['2020-01-22T19:00:00','Pacific/Honolulu'],// Std offset -11
   ['2020-04-22T09:00:00','Asia/Singapore'],  // Std offset +8
   ['2020-04-22T09:00:00','Pacific/Apia'],    // Std offset +13
   ['2020-01-22T09:00:00','Pacific/Apia'],    // DST offset +14
   ['2020-01-22T09:00:00','Asia/Yangon'],     // Std offset +6:30
   ['2020-04-22T09:00:00','Pacific/Chatham'], // Std offset +12:45
   ['2020-01-22T09:00:00','Pacific/Chatham'], // DST offset +13:45
   
   // Historic offsets pre 1900
   ['1857-01-01T00:00:00','Europe/Berlin'],   // Std offset +00:53:28
   ['1857-01-01T00:00:00','Australia/Sydney'],// Std offset +10:04:52
   ['1857-01-01T00:00:00','America/New_York'],// Std offset -04:56:02
   ['1857-01-01T00:00:00','America/Sao_Paulo'],//Std offset -03:06:28
   
   // DST boundary check out of DST (2 to 3 am counted as "out")
   ['2020-04-05T01:45:00','Australia/Sydney'],// DST offset +11:00
   ['2020-04-05T01:59:59','Australia/Sydney'],// DST offset +11:00
   ['2020-04-05T02:00:00','Australia/Sydney'],// Std offset +10:00
   ['2020-04-05T02:30:00','Australia/Sydney'],// Std offset +10:00
   ['2020-04-05T03:00:00','Australia/Sydney'],// Std offset +10:00
   ['2020-04-05T03:15:00','Australia/Sydney'],// Std offset +10:00
   
   // DST boundary check into DST (2 to 3 am counted as "in")
   ['2020-10-04T01:45:00','Australia/Sydney'],// Std offset +10:00
   ['2020-10-04T02:00:00','Australia/Sydney'],// DST offset +11:00
   ['2020-10-04T02:30:00','Australia/Sydney'],// DST offset +11:00
   ['2020-10-04T02:59:59','Australia/Sydney'],// DST offset +11:00
   ['2020-10-04T03:00:00','Australia/Sydney'],// DST offset +11:00
   ['2020-10-04T03:15:00','Australia/Sydney'] // DST offset +11:00
  ].forEach(([localTime,loc]) => {
    // Show results
    let timeUTC = getUTCString(localTime, loc);
    let offset  = getUTCOffset(localTime, loc);
    showData(localTime, loc, offset, timeUTC);
  });
};

// Example use
let timestamp = '2020-06-30 08:30:00';
let locBer="Europe/Berlin";
let locSng = 'Asia/Singapore';
// Get UTC timestamp and offset for Berlin
let utc = getUTCString(timestamp, locBer);
let off = getUTCOffset(timestamp, locBer);
// Show times and offset - offset is just for display, not used to
// generate Singapore timestamp
console.log('Berlin   : ' + timestamp + ' ' + off); // 
console.log('Singapore: ' + new Date(utc).toLocaleString(
  'en-CA',{hour12:false, timeZone:locSng, timeZoneName:'short'}
).replace(',',''));
table {
  border-collapse: collapse;
}
td {
  font-family: geneva, arial;
  font-size: 80%;
  padding: 5px;
  border: 1px solid #bbbbbb;
}
td:nth-child(2) {
  font-family: monospace;
  font-size: 100%;
}
<table id="t0">
  <tr><th>Local time<th>Place<th>Offset<th>UTC<th>Check
</table>

  • Nein, nicht genau. Was ich zu erreichen versuche, ist, ein Array zu erstellen, das die Schreibstartzeiten für einen Termin basierend auf dem Land anzeigt. Also, wenn ich am 24.04 in Deutschland zugreife, bekomme ich [‘2020-04-24T09:00:00+02:00’]. Wenn ich dann am 12.12 wieder in Deutschland darauf zugreifen würde, würde ich es bekommen [‘2020-04-24T09:00:00+01:00’] aber wenn ich von SG darauf zugreife, würde ich das erstmal hinbekommen [‘2020-04-24T15:00:00+08:00’]aber das zweite: [‘2020-04-24T16:00:00+08:00’]. Das muss ich tun.

    – Petar Karagenov

    22. April 2020 um 12:44 Uhr

  • Die Frage ist, wie ich den Offset für ein bestimmtes Datum in Berliner Zeit überprüfe, wenn auf die App aus einem anderen Land zugegriffen wird.

    – Petar Karagenov

    22. April 2020 um 13:00 Uhr

  • @PetarKaragenov—Ich habe eine Option hinzugefügt RückgabeOffset Parameter, der, wenn er wahr ist, den Offset anstelle eines Zeitstempels zurückgibt. Nennen Sie es als getUTCTime(localTime, location[, true]). Möglicherweise möchten Sie die Funktion in zwei neue Funktionen umwandeln: getUTCString und getUTCOffset.

    – RobG

    22. April 2020 um 23:39 Uhr


  • @PetarKaragenov – verwenden Sie für Ihr Berlin/Singapur-Beispiel getUTCTime(string, 'Europe/Berlin') um die äquivalente UTC-Zeichenfolge (und Offset, wenn Sie möchten, für die Anzeige) zu erhalten. Dann benutze Intl.DateTimeFormat Verwenden Sie die generierte UTC-Zeichenfolge und die Zeitzone Asien/Singapur, um einen Zeitstempel für die entsprechende Zeit in Singapur zu erhalten. Wenn Sie weitere Hilfe dazu benötigen, stellen Sie eine andere Frage. 🙂

    – RobG

    23. April 2020 um 0:19 Uhr


  • @RobG Bitte sagen Sie mir, warum Sie verwenden utcDate in dDiff = Date.UTC(p.year, p.month - 1, p.day, p.hour, p.minute, p.second) - utcDate;aber utcDate hätte sich ändern können do-while Schleife? Liegt hier kein Fehler vor?

    – Alex

    22. Dezember 2020 um 16:09 Uhr

Ich habe versucht, etwas mit dem Code aus dem Post zu erreichen, aber ich bekomme immer noch eine falsche Antwort. Weiß nicht, wo meine Logik falsch ist.

Date.prototype.stdTimezoneOffset = function () {
            var jan = new Date(this.getFullYear(), 0, 1);
            var jul = new Date(this.getFullYear(), 6, 1);
            return Math.max(jan.getTimezoneOffset(), jul.getTimezoneOffset());
        }

        Date.prototype.isDstObserved = function () {
            return this.getTimezoneOffset() < this.stdTimezoneOffset();
        }

        let currentDate="2020-12-22";
        const today = new Date();
        let schedule = [];

        if (!today.isDstObserved()) {
            schedule = [
                new Date(`${currentDate}T07:00:00Z`), // 9:00 in Germany
                new Date(`${currentDate}T08:00:00Z`), // 10:00
                new Date(`${currentDate}T09:00:00Z`) // 11:00
            ]
        } else {
            if (today.getTimezoneOffset() < new Date('2019-11-21').getTimezoneOffset()) {
                schedule = [
                    new Date(`${currentDate}T07:00:00Z`), // 9:00 in Germany
                    new Date(`${currentDate}T08:00:00Z`), // 10:00
                    new Date(`${currentDate}T09:00:00Z`) // 11:00
                ]
            } else {
                schedule = [
                    new Date(`${currentDate}T08:00:00Z`), // 9:00
                    new Date(`${currentDate}T09:00:00Z`), // 10:00
                    new Date(`${currentDate}T10:00:00Z`) // 11:00
                ]
            }
        }

995310cookie-checkBerechnen Sie den Zeitzonen-Offset nur für eine bestimmte Zeitzone

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy