Как проверить, действует ли 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);

Я хочу получить дату и время в «назад», но если летнее время используется, то даты отключаются на 1 час. Я не знаю, как проверить, действует ли DST или нет.

Как я могу узнать, когда летнее время начинается и заканчивается?

Джо Смо
источник

Ответы:

313

Этот код использует тот факт, что getTimezoneOffsetвозвращает большее значение в течение стандартного времени по сравнению с летним временем (DST). Таким образом, он определяет ожидаемый результат в течение стандартного времени и сравнивает, является ли результат данной даты одинаковым (стандартным) или меньшим (летнее время).

Обратите внимание, что getTimezoneOffsetвозвращаются положительные числа минут для зон к западу от UTC, которые обычно указываются как отрицательные часы (так как они «позади» UTC). Например, Лос-Анджелес - это UTC-8h Standard, UTC-7h DST. getTimezoneOffsetвозвращает 480(положительные 480 минут) в декабре (зима, стандартное время), а не -480. Он возвращает отрицательные числа для Восточного полушария (например, -600для Сиднея зимой, несмотря на то, что это «впереди» ( UTC + 10h ).

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
Я могу убедиться, что это работает на международном уровне. В настоящее время не существует часовых поясов, в которых бы использовалась какая-либо форма перехода на летнее время, когда как 1 января, так и 1 июля находятся либо в периоде летнего времени, либо в обоих периодах. Кроме того, во всех часовых поясах в TZDB ( с одним тривиальным исключением ) наибольшее из двух смещений - это смещение DST. Поскольку JavaScript getTimezoneOffsetвозвращает обратное значение, тогда Math.maxдействительно возвращается стандартное смещение. Код правильный.
Мэтт Джонсон-Пинт
7
Однако, если какой-либо часовой пояс когда-либо изменит свое определение так, что и 1 января, и 1 июля оба будут либо в DST, либо оба не в DST (и DST все еще применяется), тогда этот код не будет работать в этой зоне.
Мэтт Джонсон-Пинт
9
В целом это не работает, например, есть страны, которые не наблюдали ТЛЧ в определенные годы, а также некоторые страны возвращают ТЛЧ во время Рамадана. Кроме того, определение ECMAScript для Date нарушено, а также обработка переменной среды TZ в некоторых реализациях нарушена. Все это вместе делает этот метод ненадежным. Вам лучше использовать библиотеку, которая не использует Date, например timezonecomplete
rogierschouten
5
Этот код не работает в странах, где не наблюдается DST, например, в Южной Африке или Исландии; Это означает, что если вы используете его для сравнения с другими часовыми поясами в этих странах, он не будет показывать правильное время там. Предложите использовать UTC полностью, и вручную проверьте, находится ли время в пределах определенного диапазона летнего времени. Тогда это просто вопрос изменения нормального времени UTC смещения на +1, чтобы получить DST.
Кебман
1
Как это может быть правильно? Например, Германия ввела летнее время 2016-10-30, а США - неделю спустя, 2016-11-06. Плохая информация, подобная этой, является причиной того, что подобные вещи происходят: macworld.co.uk/news/apple/…
Даниэль Ф,
22

Создайте две даты: одну в июне, одну в январе. Сравните их значения getTimezoneOffset ().

  • если смещение января> смещение июня, клиент находится в северном полушарии
  • если смещение в январе <смещение в июне, клиент находится в южном полушарии
  • если нет разницы, клиентский часовой пояс не соблюдает летнее время

Теперь проверьте getTimezoneOffset () текущей даты.

  • если оно равняется июню, северное полушарие, тогда текущий часовой пояс - летнее время (+1 час)
  • если он равен январю, южное полушарие, то текущий часовой пояс - летнее время (+1 час)
Джон Ниландер
источник
Зачем вам полушария? Разве не достаточно сказать, что если getTimezoneOffset () для текущей даты равен меньшему из двух getTimezoneOffset (), то его DST? [а смещение - это разница между двумя?]
epeleg
Вам не нужны полушария, как наглядно демонстрирует принятый ответ :)
Джон Ниландер
Это не сработает. Лучше всего убедиться, что вы используете время UTC и вручную установить смещение для региона, для которого вы хотите. Затем вручную найдите начало и конец DST для того же региона (если есть). Затем вы хотите проверить, находится ли время для этого региона в диапазоне летнего времени или нет, а затем обновить смещение соответственно +1. Это позволяет сравнивать страны, в которых наблюдается летнее время, и страны, в которых нет.
Кебман
Вопрос заключается в том, как определить, действует ли DST в данный момент в часовом поясе клиентского компьютера Kebman, а не в том, как отображать даты, веб-клиенты уже справляются с этим за вас.
Джон Ниландер
Вы должны проверить с января по июль (или с февраля по август, с марта по сентябрь и т. Д.), Потому что они разнесены на 6 месяцев.
kpull1
17

Этот ответ очень похож на принятый ответ, но не переопределяет Dateпрототип и использует только один вызов функции, чтобы проверить, действует ли переход на летнее время, а не два.


Идея заключается в том, что, поскольку ни одна страна не соблюдает ТЛЧ, которое длится в течение 7 месяцев [1] , в области, где наблюдается летнее время, смещение от времени UTC в январе будет отличаться от июля.

В то время как летнее время перемещает часы вперед , JavaScript всегда возвращает большее значение в течение стандартного времени. Поэтому, получая минимальное смещение между январем и июлем, получим смещение часового пояса во время летнего времени.

Затем мы проверяем, равен ли часовой пояс дат этому минимальному значению. Если это так, то мы находимся в летнее время; в противном случае мы не.

Следующая функция использует этот алгоритм. Он принимает объект даты 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(); 
}
Toastrackenigma
источник
1
Это работает, но если в текущей временной зоне нет летнего времени, то это также приведет к значению true, что неверно. Если вы переключите его на Math.max(...) != d.get...(), он вернет истину, если DST наблюдается в данном часовом поясе И дата в настоящее время в DST. Если летнее время не соблюдается или дата соответствует стандартному смещению, возвращается значение false.
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) Он не предполагает, что летнее время (если оно вообще существует) обязательно в июле и будет работать, даже если оно будет в какой-то момент, а в каком-то месте будет в любом месяце. Однако с точки зрения производительности он будет работать быстрее, если действительно июль (или около месяца) действительно является летним временем.

3) В худшем случае он будет сравнивать getTimezoneOffset первого числа каждого месяца. [и делайте это Один раз за год тестирования].

Предположение, которое он все еще делает, состоит в том, что, если есть период DST, больше чем один месяц.

Если кто-то хочет снять это предположение, он может изменить цикл на нечто более похожее на то, что содержится в солютине, предоставленном Аароном Коулом, - но я все равно прыгнул бы на пол года вперед и вырвался из цикла, когда будут найдены два разных смещения]

epeleg
источник
4

Библиотека moment.js предоставляет .isDst()метод для своих временных объектов.

момент # 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 момент = требуется ('момент'); this.logger.info (момент ([2011, 2, 12]). isDST ()); this.logger.info (момент ([2011, 2, 14]). isDST ()); оба являются ложными
Logan_B
Даты изменения летнего времени различаются в разных странах , даже в штатах одной и той же страны (например, в штате Аризона). В США это было 2011-03-13, а в Германии - 2011-03-31. Таким образом, результат будет отличаться в зависимости от того, в каком часовом поясе настроен момент .js.
Даниэль Ф
1
Это даже изменяется в пределах штата Аризона timeanddate.com/time/us/arizona-no-dst.html
Даниэль Ф
3

getTimezoneOffset()Метод в JavaScript, в браузере, возвращает количество минут смещенных от 00:00 часового пояса. Например, часовой пояс America / New_York в Daylight Savings (DST) возвращает число 300. 300 минут - это 5-часовая разница от нуля. 300 минут, разделенные на 60 минут - это 5 часов. Каждый часовой пояс сравнивается с нулевым часовым поясом, +00: 00 / Etc / GMT / время по Гринвичу.

MDN Web Docs

Следующее, что вы должны знать, это то, что смещение имеет противоположный знак фактического часового пояса.

Информация о часовых поясах поддерживается Управлением по присвоению номеров в Интернете (iana)

часовые пояса Яны

Красиво отформатированная таблица часовых поясов предоставлена ​​joda.org

часовые пояса

+00: 00 или Etc / GMT - время по Гринвичу

Все часовые пояса смещены от +00: 00 / «Etc / GMT» / время по Гринвичу

Летнее время всегда более раннее, чем «обычное» время летом. Вы устанавливаете свои часы назад в осенний сезон. (Лозунг «Отступить», чтобы вспомнить, что делать)

Так, в Америке / Нью-Йорке время в летнее время (зима) на один час раньше обычного времени. Так, например, то, что обычно было в 5 часов вечера в Нью-Йорке летом, сейчас в 4 часа дня по Америке / Нью-Йорк в летнее время. Название времени "America / New_York" является именем часового пояса "Long Format". Восточное побережье США обычно называет часовой пояс Восточное стандартное время (EST).

Если вы хотите сравнить текущее смещение часового пояса с смещением часового пояса какой-либо другой даты, вам необходимо знать, что математический знак (+/- «Положительный / Отрицательный») смещения часового пояса является противоположностью часового пояса.

Посмотрите на таблицу часовых поясов на joda.org и найдите часовой пояс для "America / New_York". Он будет иметь отрицательный знак перед стандартным смещением.

Земля вращается против часовой стрелки вокруг своей оси. Человек, наблюдающий восход солнца в Гринвиче, видит восход солнца за 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 для часового пояса браузера. Итак, вам нужно получить смещение часового пояса на сегодня.

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. Вам нужно будет отслеживать правила каждого часового пояса для каждого часового пояса в мире. Так что, если есть лучший и более простой способ, вы можете сделать это лучше и проще.

Что нам осталось, так это то, что вам нужно знать, использует ли этот часовой пояс летнее время, а затем сравнить текущее смещение часового пояса с летним смещением часового пояса. Это всегда даст вам надежный ответ.

Последняя логика:

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
}
Алан Уэллс
источник
1
Согласно dateandtime.com, летнее время началось 10 марта 2019 года, и, следовательно, летом, а не зимой, а смещение летнего времени в Нью-Йорке составляет -4, а не -5.
jk7
Если в ответ необходимо внести улучшения или исправления, внесите изменения, и они будут рассмотрены.
Алан Уэллс
2

Используйте Moment.js ( https://momentjs.com/ )

moment().isDST(); даст вам, если наблюдается экономия дневного света.

Также он имеет вспомогательную функцию для расчета относительного времени для вас. Вам не нужно делать ручные вычисления, напримерmoment("20200105", "YYYYMMDD").fromNow();

Сантош С
источник
1

Вы близко, но немного не в себе. Вам никогда не нужно рассчитывать свое время, так как оно является результатом ваших собственных часов. Он может определить, используете ли вы летнее время в вашем местоположении, но не для удаленного местоположения, созданного смещением:

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

Это все равно будет неправильно и через час, если они находятся в летнее время. Вам нужна удаленная учетная запись времени, если они в настоящее время находятся внутри своего летнего времени или нет, и отрегулируйте соответственно. попробуйте рассчитать это и измените ваши часы на - скажем, 1/2/2015 и сбросьте часы на час назад, как если бы они находились вне летнего времени. Затем рассчитайте смещение для места, которое все еще должно отставать на 2 часа. Он покажет час впереди двухчасового окна. Вам все равно придется учесть час и отрегулировать. Я сделал это для Нью-Йорка и Денвера и всегда ошибаюсь (на час вперед) в Денвере.

Ларри Энзер
источник
1

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

Эта простая функция возвратит, наблюдает ли часовой пояс, в котором находится пользователь, переход на летнее время:

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

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

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

Нико Вестердейл
источник
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 или нет.
  • Размер месяцев года и то, как работают високосные годы, прекрасно вписывается в наше время на солнце. Черт возьми, это работает так прекрасно, что все, что мы когда-либо делаем, это просто настраиваем простые секунды здесь и там . Наша нынешняя система високосных лет действует с 24 февраля 1582 года и, вероятно, будет действовать в обозримом будущем.
  • Этот код работает в часовых поясах, которые не используют DST.
  • Этот код работает в исторические времена до того, как был внедрен DST (например, 1900-е годы).
  • Этот код максимально оптимизирован для целых чисел и не должен вызывать проблем при вызове в узком цикле. Запустив приведенный выше фрагмент кода, прокрутите вниз до нижней части вывода, чтобы увидеть тест производительности. Мой компьютер может обрабатывать 16384 даты за ~ 97 мс в Chrome.

Однако, если вы не готовитесь к более чем 2 периодам летнего времени, то приведенный ниже код можно использовать, чтобы определить, действует ли 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>

akinuri
источник
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 (восточное дневное время)

Это кажется совместимым со всеми браузерами.

YC
источник
Да, это не работает по всему миру. Летом в Европе вы получите"Thu Jul 02 2020 14:07:01 GMT+0200 (Central European Summer Time)"
Тадей Кревх
0

ES6 Стиль

Math.min(...[0, 6].map(v => new Date(95, v, 1).getTimezoneOffset() * -1));
nkitku
источник