Як перевірити, чи діє DST (перехід на літній час), а якщо так - компенсація?


154

Це трохи мого JS-коду, для якого це потрібно:

var secDiff = Math.abs(Math.round((utc_date-this.premiere_date)/1000));
this.years = this.calculateUnit(secDiff,(86400*365));
this.days = this.calculateUnit(secDiff-(this.years*(86400*365)),86400);
this.hours = this.calculateUnit((secDiff-(this.years*(86400*365))-(this.days*86400)),3600);
this.minutes = this.calculateUnit((secDiff-(this.years*(86400*365))-(this.days*86400)-(this.hours*3600)),60);
this.seconds = this.calculateUnit((secDiff-(this.years*(86400*365))-(this.days*86400)-(this.hours*3600)-(this.minutes*60)),1);

Я хочу отримати дату в "тому", але якщо DST використовується, то дати вимикаються на 1 годину. Я не знаю, як перевірити, чи діє DST чи ні.

Як я можу знати, коли починається та закінчується літній час?

Відповіді:


313

Цей код використовує той факт, що getTimezoneOffsetповертає більше значення за стандартний час проти літнього часу (DST). Таким чином, він визначає очікуваний вихід у стандартний час і порівнює, чи є вихід даної дати однаковим (Стандартним) або меншим (DST).

Зауважте, що getTimezoneOffsetповертає додатні числа хвилин для зон на захід від UTC, які зазвичай зазначаються як від’ємні години (оскільки вони «позаду» UTC). Наприклад, Лос-Анджелес - UTC – 8 год. Стандарт, UTC - 7 год. getTimezoneOffsetповернення 480(позитивні 480 хвилин) у грудні (зима, стандартний час), а не -480. Він повертає негативні цифри для Східної півкулі (наприклад, -600для Сіднея взимку, незважаючи на те, що це "вперед" ( UTC + 10 год ).

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();
}

var today = new Date();
if (today.isDstObserved()) { 
    alert ("Daylight saving time!");
}

28
Я можу переконатися, що це працює на міжнародному рівні. Наразі немає часових поясів, які використовують будь-яку форму DST, де і 1 січня, і 1 липня або обидва, або обидва поза періодом DST. Крім того, у всіх часових поясах в TZDB ( за одним тривіальним винятком ) більший з двох зрушень - це зміщення DST. Оскільки JavaScript getTimezoneOffsetповертає обернене значення, то Math.maxсправді повертає стандартне зміщення. Код правильний.
Метт Джонсон-Пінт

7
Однак якщо будь-який часовий пояс колись змінить своє визначення таким чином, що і 1 січня, і 1 липня обидва є або в DST, або обидва не в DST (і все ще застосовується DST), цей код не буде працювати в цій зоні.
Метт Джонсон-Пінт

9
Це взагалі не працює, наприклад, є країни, які не спостерігали DST протягом певних років, а також деякі країни скасовують DST під час рамадану. Далі, порушено визначення ECMAScript для Date, а також обробка змінної середовища TZ порушена в деяких реалізаціях. Все це у поєднанні робить цей метод ненадійним. Вам краще використовувати бібліотеку, яка не використовує дату, наприклад, timezonecomplete
rogierschouten

5
Цей код не працює в країнах, які не дотримуються DST, як, наприклад, Південна Африка або Ісландія; тобто якщо ви використовуєте його для порівняння з іншими часовими поясами в цих країнах, він не відображатиме правильний час там. Запропонуйте весь час використовувати UTC та вручну перевірити, чи зараз час знаходиться в межах певного діапазону DST. Тоді лише питання зміни звичайного часу зсуву UTC на +1, щоб отримати DST.
Кебман

1
Як це можна правильно? Наприклад, Німеччина вступила в DST 2016-10-30, тоді як США вступили через тиждень 2016-11-06. Погана інформація, як ця, викликає подібні речі: macworld.co.uk/news/apple/…
Daniel F

22

Створіть дві дати: одну в червні, одну в січні. Порівняйте їх значення getTimezoneOffset ().

  • якщо зміщення січня> зміщення червня, клієнт знаходиться у північній півкулі
  • якщо зміщення січня <зміщення червня, клієнт знаходиться у південній півкулі
  • якщо немає різниці, часовий пояс клієнта не дотримується стандартного стандарту

Тепер перевірте getTimezoneOffset () поточної дати.

  • якщо дорівнює червні, північній півкулі, то поточний часовий пояс становить DST (+1 година)
  • якщо дорівнює січні, південній півкулі, то поточний часовий пояс становить DST (+1 година)

Для чого потрібні півкулі? чи не буде достатньо сказати, що якщо getTimezoneOffset () для поточної дати дорівнює меншому з двох getTimezoneOffset (), то його DST? [а компенсування - різниця між двома?]
epeleg

Вам не потрібні півкулі, оскільки прийнята відповідь наочно демонструє :)
Jon Nylander

Це не спрацює. Найкраще зробити це - переконатися, що ви використовуєте час UTC та вручну встановіть зміщення для регіону, який вам потрібен. Потім вручну знайдіть початок і кінець для DST для того ж регіону (якщо такий є). Потім ви хочете перевірити, чи знаходиться час для цього регіону в межах діапазону DST чи ні, а потім оновити зміщення відповідно +1. Це дає можливість порівнювати країни, які дотримуються стандартів DST, та країни, які цього не виконують.
Кебман

Питання полягає в тому, як визначити, чи діє DST в даний момент у часовому поясі клієнтської машини Kebman, а не як відображати дати, веб-клієнти вже обробляють це для вас.
Джон Ніландер

Ви повинні перевіряти між січнем та липнем (або лютим і серпнем, березнем та вереснем тощо), оскільки вони 6 місяців.
kpull1

17

Ця відповідь досить схожа на прийняту відповідь, але не переосмислює Dateпрототип, і використовує лише один виклик функції, щоб перевірити, чи діє літній час, а не два.


Ідея полягає в тому, що, оскільки жодна країна не спостерігає за літнім часом, який триває протягом 7 місяців [1] , у районі, що спостерігає за ЗНТ, зміщення часу UTC у січні буде відрізнятися від рівня липня.

Поки літній час пересуває годинник вперед , JavaScript завжди повертає більше значення за стандартний час. Тому отримання мінімального зміщення між січнем та липнем отримає зміщення часового поясу під час DST.

Потім ми перевіряємо, чи часовий пояс дат дорівнює цьому мінімальному значенню. Якщо так, то ми в DST; інакше ми не є.

Наступна функція використовує цей алгоритм. Він займає об'єкт дати d, і повертається, trueякщо для цієї дати діє літній час, і falseякщо його немає:

function isDST(d) {
    let jan = new Date(d.getFullYear(), 0, 1).getTimezoneOffset();
    let jul = new Date(d.getFullYear(), 6, 1).getTimezoneOffset();
    return Math.max(jan, jul) != d.getTimezoneOffset(); 
}

1
Це працює, але якщо в поточній TimeZone немає DST, це також призведе до істини, що не є правильним. Якщо ви переключитесь на нього Math.max(...) != d.get...(), він поверне справжній iff, якщо DST спостерігається в заданому часовому поясі, а дата в даний час у DST Якщо DST не спостерігається або дата відповідає стандартному зміщенню, воно повернеться помилковим.
GreySage

12

Я зіткнувся з цією ж проблемою сьогодні, але оскільки наш літній час починається і припиняється в різні часи від США (принаймні, з мого розуміння), я використовував трохи інший маршрут.

var arr = [];
for (var i = 0; i < 365; i++) {
 var d = new Date();
 d.setDate(i);
 newoffset = d.getTimezoneOffset();
 arr.push(newoffset);
}
DST = Math.min.apply(null, arr);
nonDST = Math.max.apply(null, arr);

Тоді ви просто порівнюєте поточний зсув часового поясу з DST та nonDST, щоб побачити, який з них відповідає.


Так ми і робимо це. Тобто з’ясуйте час року, коли зміни DST у вашому цільовому часовому поясі та обчисліть зрушення для поточного дня та останньої дати зміни. Вони будуть або відрізнятися на годину, або бути рівними (якщо припустимо, що часовий пояс є зміщенням години).
Хізер

Немає необхідності створювати 365 значень. Бінарний підхід пошуку, який припиняється, як тільки визначається зміна зміщення, повинен бути набагато ефективнішим, навіть коли не спостерігається економія денного світла. Усі ці підходи припускають, що місця спостерігаються на літній час щорічно, що не обов'язково відповідає дійсності. Місця приймають та відмовляються від літнього часу час від часу (хоча ECMAScript передбачає діючі правила, незалежно від їх області, застосовується завжди).
RobG

2
Роб - як ви можете це зробити за допомогою двійкового пошуку, якщо ви не знаєте, де шукати (тобто місце, яке ви шукаєте, знаходиться вище або нижче тестового пункту?)
epeleg

9

На основі коментаря Метта Йохансона щодо рішення, наданого Шелдоном Гріффіном, я створив наступний код:

    Date.prototype.stdTimezoneOffset = function() {
        var fy=this.getFullYear();
        if (!Date.prototype.stdTimezoneOffset.cache.hasOwnProperty(fy)) {

            var maxOffset = new Date(fy, 0, 1).getTimezoneOffset();
            var monthsTestOrder=[6,7,5,8,4,9,3,10,2,11,1];

            for(var mi=0;mi<12;mi++) {
                var offset=new Date(fy, monthsTestOrder[mi], 1).getTimezoneOffset();
                if (offset!=maxOffset) { 
                    maxOffset=Math.max(maxOffset,offset);
                    break;
                }
            }
            Date.prototype.stdTimezoneOffset.cache[fy]=maxOffset;
        }
        return Date.prototype.stdTimezoneOffset.cache[fy];
    };

    Date.prototype.stdTimezoneOffset.cache={};

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

Він намагається отримати найкраще з усіх країн світу, враховуючи всі коментарі та запропоновані раніше відповіді, а саме:

1) Кешує результат за рік stdTimezoneOffset, так що вам не потрібно перераховувати його під час тестування кількох дат в одному році.

2) Не передбачається, що DST (якщо він взагалі існує) обов'язково в липні, і він буде працювати, навіть якщо в якийсь момент і в якомусь місці буде якийсь місяць. Однак для продуктивності він буде працювати швидше, якщо дійсно липень (або найближчі місяці) справді буде літнім часом.

3) Гірший випадок, якщо він порівняє getTimezoneOffset за перше число кожного місяця. [і робіть це раз на перевірений рік].

Припущення, яке вона все-таки робить, полягає в тому, що якщо є DST, то термін перевищує один місяць.

Якщо хтось хоче зняти це припущення, він може перетворити цикл на щось більше, як те, що в солютині, наданому Аароном Коулом, - але я все одно стрибну на півроку вперед і вирватися з петлі, коли знайдуться два різних компенсації]


4

Бібліотека moment.js забезпечує .isDst()метод для своїх часових об'єктів.

moment # isDST перевіряє, чи поточний момент переходить на літній час.

moment([2011, 2, 12]).isDST(); // false, March 12 2011 is not DST
moment([2011, 2, 14]).isDST(); // true, March 14 2011 is DST

Я спробував var moment = изисквати ('момент'); this.logger.info (момент ([2011, 2, 12]). isDST ()); this.logger.info (момент ([2011, 2, 14]). isDST ()); обидва помилкові
Logan_B

Дати зміни DST залежать від країн , навіть серед штатів тієї ж країни (тобто штату Арізона). У США це було на 2011-03-13, тоді як у Німеччині - на 2011-03-31. Таким чином, результат буде відрізнятися залежно від того, в якому часовому поясі moment.js налаштований для роботи.
Daniel F

1
Він навіть змінюється в межах штату Арізона timeanddate.com/time/us/arizona-no-dst.html
Даніель Ф

3

The getTimezoneOffset()Метод в JavaScript, в браузері, повертає кількість хвилин зміщених від 00:00 часового поясу. Наприклад, часовий пояс America / New_York в режимі літнього часу (DST) повертає число 300. 300 хвилин - це 5 годин різниці від нуля. 300 хвилин ділиться на 60 хвилин - це 5 годин. Кожен часовий пояс порівнюється з нульовим часовим поясом +00: 00 / Etc / GMT / Greenwich time.

Веб-документи MDN

Наступне, що ви повинні знати, - це те, що зміщення має протилежний знак фактичного часового поясу.

Інформація про часові пояси підтримується Інтернетом, що призначає номер (iana)

часові пояси iana

Приємно відформатовану таблицю часових поясів надає joda.org

Часові пояси часу joda

+00: 00 або Etc / GMT - час за Грінвічем

Усі часові пояси зміщені з +00: 00 / "Etc / GMT" / Грінвічський час

Перехід на літній час завжди є більш раннім, ніж "звичайний" час влітку. Ви встановлюєте годинник ще в осінній сезон. (Гасло "Падіння назад", щоб пам'ятати, що робити)

Так, час в Америці / Нью-Йорку в режимі літнього часу (взимку) за годину до звичайного часу. Так, наприклад, те, що зазвичай було влітку в 17:00 в Нью-Йорку влітку, зараз 16:00 в Америці / Нью-Йорку в режимі літнього часу. Назва "America / New_York" time - назва часового поясу "Long Format". Східне узбережжя США зазвичай називає їх часовий пояс Східним стандартним часом (EST)

Якщо ви хочете порівняти сьогоднішнє зміщення часового поясу зі зміщенням часового поясу на якусь іншу дату, вам потрібно знати, що математичний знак (+/- "Позитивний / Негативний") зміщення часового поясу протилежний часовому поясу.

Подивіться на таблицю часового поясу на joda.org і знайдіть часовий пояс для "Америка / Нью-Йорк". Він матиме негативний знак перед стандартним зміщенням.

Земля обертається проти годинникової стрілки на своїй осі. Людина, яка спостерігає схід сонця в Ґрінвічі, бачить схід за 5 годин до того, як хтось із Нью-Йорка побачить схід сонця. І хтось на Західному узбережжі США побачить схід сонця після того, як хтось на Східному узбережжі США побачить схід сонця.

Є причина, чому вам потрібно все це знати. Так що ви зможете логічно визначити, чи отримує якийсь код JavaScript статус DST правильно чи ні, без необхідності перевіряти кожен часовий пояс у різний час року.

Уявіть, що в Нью-Йорку - листопад, а годинник був встановлений на годину. Влітку в Нью-Йорку компенсування становить 240 хвилин або 4 години.

Ви можете перевірити це, створивши дату, яка є в липні, а потім отримати компенсацію.

var July_Date = new Date(2017, 6, 1);
var july_Timezone_OffSet = July_Date.getTimezoneOffset();

console.log('july_Timezone_OffSet: ' + july_Timezone_OffSet)

Що буде надруковано в журнал консолі розробника браузера?

Відповідь: 240

Отже, тепер ви можете створити дату в січні та побачити, що ваш браузер повертає за зміщення часового поясу на зимовий сезон.

var Jan_Date = new Date(2017, 0, 1);//Month is zero indexed - Jan is zero
var jan_Timezone_OffSet = Jan_Date.getTimezoneOffset();

console.log('jan_Timezone_OffSet: ' + jan_Timezone_OffSet)

Відповідь: 300

Очевидно, що 300 більший, ніж 240. Отже, що це означає? Чи слід написати код, що тести на зимовий зсув перевищують літній зсув? Або літній залік менше, ніж зимовий зсув? Якщо є різниця між зрушеннями літнього та зимового часового поясу, то можна припустити, що DST використовується для цього часового поясу. Але це не говорить вам про те, чи сьогодні використовується DST для часового поясу браузерів. Отже, вам потрібно буде компенсувати часовий пояс на сьогодні.

var today = new Date();
var todaysTimeZone = today.getTimezoneOffset();

console.log('todaysTimeZone : ' + todaysTimeZone)

Відповідь: - Залежить від часу року

Якщо сьогодні часовий пояс і літній зміщення часового поясу те ж саме, і зміщення часового поясу влітку і взимку різні, то по логічної дедукції, сьогодні має бути НЕ бути в DST.

Чи можете ви пропустити порівняння компенсацій літнього та зимового часових поясів (щоб знати, чи використовується DST для цього часового поясу) та просто порівняти сьогоднішній зсув часового поясу з літнім зміщенням TZ та завжди отримати правильну відповідь?

today's TZ Offset !== Summer TZ Offset

Ну що, сьогодні взимку чи влітку? Якщо ви це знали, то можете застосувати таку логіку:

if ( it_is_winter && ( todays_TZ_Offset !== summer_TZ_Offset) {
  var are_We_In_DST = true;
}

Але проблема полягає в тому, що ви не знаєте, чи сьогоднішня дата взимку чи влітку. Кожен часовий пояс може мати власні правила, коли починається і зупиняється DST. Вам потрібно буде стежити за правилами кожного часового поясу для кожного часового поясу в світі. Отже, якщо є кращий і простіший спосіб, то ви також можете зробити це кращим і легшим способом.

Що нам залишається, це те, що вам потрібно знати, чи використовує цей часовий пояс DST, а потім порівнювати сьогоднішній зміщення часового поясу із зрушенням літнього часового поясу. Це завжди дасть вам надійну відповідь.

Остаточна логіка:

if ( DST_Is_Used_In_This_Time_Zone && ( todays_TZ_Offset !== summer_TZ_Offset) {
  var are_We_In_DST = true;
}

Функція для визначення, чи використовує часовий пояс у браузері DST:

function is_DST_Used_In_This_TimeZone() {
  var Jan_Date, jan_Timezone_OffSet, July_Date, july_Timezone_OffSet 
      offsetsNotEqual, thisYear, today;

  today = new Date();//Create a date object that is now
  thisYear = today.getFullYear();//Get the year as a number

  Jan_Date = new Date(thisYear, 0, 1);//Month is zero indexed - Jan is zero
  jan_Timezone_OffSet = Jan_Date.getTimezoneOffset();

  console.log('jan_Timezone_OffSet: ' + jan_Timezone_OffSet)

  July_Date = new Date(thisYear, 6, 1);
  july_Timezone_OffSet = July_Date.getTimezoneOffset();

  console.log('july_Timezone_OffSet: ' + july_Timezone_OffSet)

  offsetsNotEqual = july_Timezone_OffSet !== jan_Timezone_OffSet;//True if not equal

  console.log('offsetsNotEqual: ' + offsetsNotEqual);

  return offsetsNotEqual;//If the offsets are not equal for summer and
       //winter then the only possible reason is that DST is used for
       //this time zone
}

Відповідно до dateandtime.com, DST розпочався 10 березня 2019 року, а отже, це влітку, а не взимку, а нью-йоркський зсув DST становить -4, а не -5.
jk7

Якщо у відповіді потребує вдосконалення чи виправлення, будь ласка, внесіть зміни, і вона буде переглянута.
Алан Уеллс

2

Використовуйте Moment.js ( https://momentjs.com/ )

moment().isDST(); дасть вам, якщо спостерігається економія денного світла.

Крім того, він має функцію помічника для розрахунку відносного часу для вас. Не потрібно робити ручні розрахунки, наприкладmoment("20200105", "YYYYMMDD").fromNow();


1

Ви близькі, але трохи відпочили. Ніколи не потрібно обчислювати власний час, оскільки це результат власного годинника. Він може визначити, якщо ви використовуєте літній час у своєму розташуванні, але не для віддаленого місця, отриманого в результаті зміщення:

newDateWithOffset = new Date(utc + (3600000*(offset)));

Це все ще буде помилковим і поза годиною, якщо вони знаходяться в стандартній літній час. Вам потрібен обліковий запис віддаленого часу, якщо вони зараз знаходяться в межах свого літнього часу або немає, і відповідно налаштувати їх. спробуйте обчислити це і змінити годинник на - скажімо, 2.02.2015 та скиньте годинник назад на годину, як ніби за межами DST. Потім обчисліть компенсацію місця, яке повинно відстати на 2 години. Він покаже на годину попереду двох годинного вікна. Вам все одно доведеться враховувати годину та коригувати. Я зробив це для Нью-Йорка та Денвера і завжди йшов неправильно (на годину вперед) у Денвері.


1

Я виявив, що використання бібліотеки Moment.js з деякими описаними тут концепціями (порівняння січня з червнем) працює дуже добре.

Ця проста функція повертає, чи дотримується часовий пояс, за яким користувач переглядає літній час:

function HasDST() {
    return moment([2017, 1, 1]).isDST() != moment([2017, 6, 1]).isDST();
}

Простий спосіб перевірити, що це працює (в Windows), - це змінити часовий пояс на не DST-зону, наприклад, Арізона поверне помилкову, тоді як EST або PST повернеться вірно.

введіть тут опис зображення


1

Майбутнє рішення, яке працює у всіх часових зонах

  1. Нехай xбуде очікувана кількість мілісекунд на рік інтересу, не враховуючи економії денного світла.
  2. Нехай yбуде кількість мілісекунд з епохи з початку року дати, що становить інтерес.
  3. Нехай zбуде кількість мілісекунд з епохи повної дати та часу, що цікавить
  4. Нехай tбуде віднімання в межах десяти xі yз z: z - y - x. Це дає компенсацію за рахунок ДСТ.
  5. Якщо tнуль, то DST не діє. Якщо tне дорівнює нулю, тоді діє DST.

(function(){"use strict";
function dstOffsetAtDate(dateInput) {
    var fullYear = dateInput.getFullYear()|0;
	// "Leap Years are any year that can be exactly divided by 4 (2012, 2016, etc)
 	//   except if it can be exactly divided by 100, then it isn't (2100,2200,etc)
 	//	  except if it can be exactly divided by 400, then it is (2000, 2400)"
	// (https://www.mathsisfun.com/leap-years.html).
    var isLeapYear = ((fullYear & 3) | (fullYear/100 & 3)) === 0 ? 1 : 0;
	// (fullYear & 3) = (fullYear % 4), but faster
    //Alternative:var isLeapYear=(new Date(currentYear,1,29,12)).getDate()===29?1:0
    var fullMonth = dateInput.getMonth()|0;
    return (
        // 1. We know what the time since the Epoch really is
        (+dateInput) // same as the dateInput.getTime() method
        // 2. We know what the time since the Epoch at the start of the year is
        - (+new Date(fullYear, 0, 0)) // day defaults to 1 if not explicitly zeroed
        // 3. Now, subtract what we would expect the time to be if daylight savings
        //      did not exist. This yields the time-offset due to daylight savings.
        - ((
            ((
                // Calculate the day of the year in the Gregorian calendar
                // The code below works based upon the facts of signed right shifts
                //    • (x) >> n: shifts n and fills in the n highest bits with 0s 
                //    • (-x) >> n: shifts n and fills in the n highest bits with 1s
                // (This assumes that x is a positive integer)
                (31 & ((-fullMonth) >> 4)) + // January // (-11)>>4 = -1
                ((28 + isLeapYear) & ((1-fullMonth) >> 4)) + // February
                (31 & ((2-fullMonth) >> 4)) + // March
                (30 & ((3-fullMonth) >> 4)) + // April
                (31 & ((4-fullMonth) >> 4)) + // May
                (30 & ((5-fullMonth) >> 4)) + // June
                (31 & ((6-fullMonth) >> 4)) + // July
                (31 & ((7-fullMonth) >> 4)) + // August
                (30 & ((8-fullMonth) >> 4)) + // September
                (31 & ((9-fullMonth) >> 4)) + // October
                (30 & ((10-fullMonth) >> 4)) + // November
                // There are no months past December: the year rolls into the next.
                // Thus, fullMonth is 0-based, so it will never be 12 in Javascript
                
                (dateInput.getDate()|0) // get day of the month
				
            )&0xffff) * 24 * 60 // 24 hours in a day, 60 minutes in an hour
            + (dateInput.getHours()&0xff) * 60 // 60 minutes in an hour
            + (dateInput.getMinutes()&0xff)
        )|0) * 60 * 1000 // 60 seconds in a minute * 1000 milliseconds in a second
        - (dateInput.getSeconds()&0xff) * 1000 // 1000 milliseconds in a second
        - dateInput.getMilliseconds()
    );
}

// Demonstration:
var date = new Date(2100, 0, 1)
for (var i=0; i<12; i=i+1|0, date.setMonth(date.getMonth()+1|0))
    console.log(date.getMonth()+":\t"+dstOffsetAtDate(date)/60/60/1000+"h\t"+date);
date = new Date(1900, 0, 1);
for (var i=0; i<12; i=i+1|0, date.setMonth(date.getMonth()+1|0))
    console.log(date.getMonth()+":\t"+dstOffsetAtDate(date)/60/60/1000+"h\t"+date);

// Performance Benchmark:
console.time("Speed of processing 16384 dates");
for (var i=0,month=date.getMonth()|0; i<16384; i=i+1|0)
    date.setMonth(month=month+1+(dstOffsetAtDate(date)|0)|0);
console.timeEnd("Speed of processing 16384 dates");
})();

Я вважаю, що вищевказаний фрагмент коду перевершує всі інші відповіді, розміщені тут з багатьох причин.

  • Ця відповідь працює у всіх часових поясах, навіть в Антарктиді / Кейсі .
  • Економія денного світла дуже сильно змінюється. Можливо, через 20 років у деяких країнах може бути 3 періоди DST замість звичайних 2. Цей код обробляє цей випадок, повертаючи зсув DST в мілісекундах, а не тільки, чи діє DST чи ні.
  • Розмір місяців року та спосіб роботи Leap Years ідеально підходять для того, щоб слідкувати за часом із сонцем. Чорт, це працює настільки чудово, що все, що ми коли-небудь робимо, - це лише налаштувати кілька секунд тут і там . Наша діюча система високосних років діє з 24 лютого 1582 р. І, ймовірно, залишиться в силі в осяжному майбутньому.
  • Цей код працює у часових поясах, які не використовують DST.
  • Цей код працює в історичні часи до того, як було впроваджено DST (наприклад, 1900-ті роки).
  • Цей код максимально оптимізований для цілих чисел і не повинен створювати проблем, якщо його викликають у вузькому циклі. Після запуску фрагмента коду вище, прокрутіть донизу висновку, щоб побачити показник продуктивності. Мій комп'ютер може обробляти 16384 дати за ~ 97 мс у Chrome.

Однак якщо ви не готуєтесь понад 2 періоди DST, тоді наведений нижче код можна використовувати, щоб визначити, чи DST діє як булева.

function isDaylightSavingsInEffect(dateInput) {
    // To satisfy the original question
    return dstOffsetAtDate(dateInput) !== 0;
}

0

Нещодавно мені потрібно було створити рядок дати за допомогою UTC та DST, і на основі відповіді Шелдона я склав це разом:

Date.prototype.getTimezone = function(showDST) {
    var jan = new Date(this.getFullYear(), 0, 1);
    var jul = new Date(this.getFullYear(), 6, 1);

    var utcOffset = new Date().getTimezoneOffset() / 60 * -1;
    var dstOffset = (jan.getTimezoneOffset() - jul.getTimezoneOffset()) / 60;

    var utc = "UTC" + utcOffset.getSign() + (utcOffset * 100).preFixed(1000);
    var dst = "DST" + dstOffset.getSign() + (dstOffset * 100).preFixed(1000);

    if (showDST) {
        return utc + " (" + dst + ")";
    }

    return utc;
}
Number.prototype.preFixed = function (preCeiling) {
    var num = parseInt(this, 10);
    if (preCeiling && num < preCeiling) {
        num = Math.abs(num);
        var numLength		 = num.toString().length;
        var preCeilingLength = preCeiling.toString().length;
        var preOffset		 = preCeilingLength - numLength;
        for (var i = 0; i < preOffset; i++) {
            num = "0" + num;
        }
    }
    return num;
}
Number.prototype.getSign = function () {
    var num	 = parseInt(this, 10);
    var sign = "+";
    if (num < 0) {
        sign = "-";
    }
    return sign;
}

document.body.innerHTML += new Date().getTimezone() + "<br>";
document.body.innerHTML += new Date().getTimezone(true);
<p>Output for Turkey (UTC+0200) and currently in DST: &nbsp; UTC+0300 (DST+0100)</p>
<hr>


0

Чи є проблема із використанням Date.toString().indexOf('Daylight Time') > -1

"" + new Date()

Сб 01 січня 100050 00:00:00 GMT-0500 (східний стандартний час)

"" + new Date(...)

Нд 01 травня 100033 00:00:00 GMT-0400 (східний літній час)

Це здається сумісним із усіма браузерами.


Так, це не працює у всьому світі. Влітку в Європі ви отримуєте"Thu Jul 02 2020 14:07:01 GMT+0200 (Central European Summer Time)"
Тадей Кревх

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.