ПОДЕРЖАЙТЕ ЧАС
Використання об'єкта дати для подання одразу ж дати поставить перед вами величезну проблему надмірної точності. Вам потрібно керувати часом та часовим поясом, щоб їх не було, і вони можуть прокрастися назад на будь-якому кроці. Прийнята відповідь на це питання потрапляє у пастку.
Дата JavaScript не має поняття часового поясу . Настав момент часу (галочки з епохи) із зручними (статичними) функціями для перекладу до рядків і з них, використовуючи за замовчуванням «локальний» часовий пояс пристрою або, якщо зазначено, UTC або інший часовий пояс. Щоб представити лише дату ™ з об’єктом дати, ви хочете, щоб ваші дати представляли півночі UTC на початку дати, про яку йдеться. Це звичайна і необхідна конвенція, яка дозволяє вам працювати з датами незалежно від сезону або часового поясу їх створення. Тож вам потрібно бути дуже пильним, щоб керувати поняттям часового поясу, як під час створення об’єкта «Дата півночі UTC», так і при його серіалізації.
Багато людей плутають поведінку консолі за замовчуванням. Якщо ви розпорошите дату на консоль, вихід, який ви бачите, буде включати ваш часовий пояс. Це лише тому, що консоль дзвонить toString()
у вашу дату та toString()
дає місцеві репресії. Базова дата не має часового поясу ! (Поки час відповідає зсуву часового поясу, у вас все ще є об’єкт дати півночі UTC)
Десеріалізація (або створення об'єктів дати за півночі UTC)
Це крок округлення, з хитрістю, що є дві "правильні" відповіді. Більшу частину часу ви хочете, щоб ваша дата відображала часовий пояс користувача. Клацніть, якщо сьогодні ваш день народження . Користувачі в NZ та США клацають одночасно та отримують різні дати. У такому випадку зробіть це ...
// create a date (utc midnight) reflecting the value of myDate and the environment's timezone offset.
new Date(Date.UTC(myDate.getFullYear(),myDate.getMonth(), myDate.getDate()));
Іноді міжнародна порівнянність зумовлює місцеву точність. У такому випадку зробіть це ...
// the date in London of a moment in time. Device timezone is ignored.
new Date(Date.UTC(myDate.getUTCFullYear(), myDate.getUTCMonth(), myDate.getUTCDate()));
Десеріалізуйте побачення
Часто дати на дроті будуть у форматі РРРР-ММ-DD. Щоб десаріалізувати їх, зробіть це ...
var midnightUTCDate = new Date( dateString + 'T00:00:00Z');
Серіалізація
Подбавши про керування часовим поясом під час створення, тепер вам потрібно бути впевненим, щоб уникнути часового поясу, коли ви перетворюєтесь назад у рядкове представлення. Тож можна сміливо використовувати ...
toISOString()
getUTCxxx()
getTime() //returns a number with no time or timezone.
.toLocaleDateString("fr",{timezone:"UTC"}) // whatever locale you want, but ALWAYS UTC.
І зовсім уникати всього іншого, особливо ...
getYear()
, getMonth()
,getDate()
Отже, щоб відповісти на ваше запитання, 7 років занадто пізно ...
<input type="date" onchange="isInPast(event)">
<script>
var isInPast = function(event){
var userEntered = new Date(event.target.valueAsNumber); // valueAsNumber has no time or timezone!
var now = new Date();
var today = new Date(Date.UTC(now.getUTCFullYear(), now.getUTCMonth(), now.getUTCDate() ));
if(userEntered.getTime() < today.getTime())
alert("date is past");
else if(userEntered.getTime() == today.getTime())
alert("date is today");
else
alert("date is future");
}
</script>
Дивіться, як це працює ...
Оновлення 2019 року ... безкоштовні речі ...
Враховуючи популярність цієї відповіді, я все це вклав у код. Наступна функція повертає обернутий об'єкт дати та розкриває лише ті функції, які безпечно використовувати із простою датою ™.
Назвіть його об’єктом Date, і він вирішить JustADate, що відображає часовий пояс користувача. Назвіть це за допомогою рядка: якщо рядок є ISO 8601 із вказаним часовим поясом, ми просто округлимо часову частину. Якщо часовий пояс не вказаний, ми перетворимо його на дату, що відображає локальний часовий пояс, як і для об'єктів дати.
function JustADate(initDate){
var utcMidnightDateObj = null
// if no date supplied, use Now.
if(!initDate)
initDate = new Date();
// if initDate specifies a timezone offset, or is already UTC, just keep the date part, reflecting the date _in that timezone_
if(typeof initDate === "string" && initDate.match(/((\+|-)\d{2}:\d{2}|Z)$/gm)){
utcMidnightDateObj = new Date( initDate.substring(0,10) + 'T00:00:00Z');
} else {
// if init date is not already a date object, feed it to the date constructor.
if(!(initDate instanceof Date))
initDate = new Date(initDate);
// Vital Step! Strip time part. Create UTC midnight dateObj according to local timezone.
utcMidnightDateObj = new Date(Date.UTC(initDate.getFullYear(),initDate.getMonth(), initDate.getDate()));
}
return {
toISOString:()=>utcMidnightDateObj.toISOString(),
getUTCDate:()=>utcMidnightDateObj.getUTCDate(),
getUTCDay:()=>utcMidnightDateObj.getUTCDay(),
getUTCFullYear:()=>utcMidnightDateObj.getUTCFullYear(),
getUTCMonth:()=>utcMidnightDateObj.getUTCMonth(),
setUTCDate:(arg)=>utcMidnightDateObj.setUTCDate(arg),
setUTCFullYear:(arg)=>utcMidnightDateObj.setUTCFullYear(arg),
setUTCMonth:(arg)=>utcMidnightDateObj.setUTCMonth(arg),
addDays:(days)=>{
utcMidnightDateObj.setUTCDate(utcMidnightDateObj.getUTCDate + days)
},
toString:()=>utcMidnightDateObj.toString(),
toLocaleDateString:(locale,options)=>{
options = options || {};
options.timezone = "UTC";
locale = locale || "en-EN";
return utcMidnightDateObj.toLocaleDateString(locale,options)
}
}
}
// if initDate already has a timezone, we'll just use the date part directly
console.log(JustADate('1963-11-22T12:30:00-06:00').toLocaleDateString())
date1 === date2
начебто не забезпечує послідовну поведінку; краще зробитиdate1.valueOf() === b.valueOf()
чи навітьdate1.getTime() === date2.getTime()
. Дивність.