Подтвердить что ты не робот

Как проверить, действует ли летнее время (летнее время), и если это то, что такое смещение?

Это немного из моего кода 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 или нет.

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

4b9b3361

Ответ 1

Этот код использует тот факт, что 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!");
}

Ответ 2

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

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

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

  • если он равен июню, северное полушарие, то текущий часовой пояс равен DST (+1 час)
  • если он равен январю, южному полушарию, то текущий часовой пояс равен DST (+1 час)

Ответ 3

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

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, чтобы увидеть, какой из них соответствует.

Ответ 4

Этот ответ очень похож на принятый ответ, но не переопределяет прототип 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(); 
}

Ответ 5

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

    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 (если он вообще существует) обязательно в июле,  и будет работать, даже если это будет в какой-то момент и какое-то место в любом месяце.  Однако с точки зрения производительности он будет работать быстрее, если действительно июль (или почти по месяцам) действительно является DST.

3) Хуже того, он будет сравнивать getTimezoneOffset первого из каждого месяца. [и сделайте это один раз за испытанный год].

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

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

Ответ 6

Библиотека 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

Ответ 7

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

MDN Web Docs

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

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

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

Хорошо отформатированная таблица временных зон предоставляется joda.org

joda-Time Time Zones

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

Все часовые пояса смещены от +00: 00/ "Etc/GMT" /Greenwich time

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

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

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

Посмотрите таблицу часовых поясов на joda.org и найдите часовой пояс для "Америка/Новый_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. Но это не говорит вам, если сегодня использует DST для часового пояса браузеров. Таким образом, вам нужно будет получить смещение часового пояса на сегодняшний день.

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

console.log('todaysTimeZone : ' + todaysTimeZone)

Ответ:? - Зависит от времени года.

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

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

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

Ответ 8

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

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

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

Ответ 9

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

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

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

Простым способом проверить, что это работает (в Windows), является изменение вашего часового пояса в зоне не DST, например, Аризона вернет false, тогда как EST или PST вернет true.

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

Ответ 10

Перспективное решение, которое работает во всех часовых поясах

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

Ответ 11

Мне недавно нужно было создать строку даты с 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>