Як використовувати дату в Javascript для доісторичних дат?


76

Я працюю над проектом, в якому дата JavaScript недостатньо велика.

Я хочу розмістити кілька подій на одній осі часу, деякі з них мають місяць і день, а деякі ні, тому просто використовувати рік - це не варіант. Я хочу мати можливість посадки на Місяць і великого вибуху на одній осі.

Це дуже допомогло б, якби я міг використовувати функціонал, який має існуючий об'єкт Date. Це сягає лише 270 000 років, і мені потрібно повернутися до Великого вибуху (13 800 000 000 років тому). Мені не потрібно, щоб дати містили секунди або мілісекунди.

Як я можу розширити об'єкт Date, щоб включити представлення для таких дат?

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

Оновлення:

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

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

JSFiddle


14
Ви повинні вказати, які ваші вимоги стосуються цих дат. Вам потрібно виконати арифметику дати, наприклад?
Аарон,

23
Вам справді потрібно знати дні та місяці, якщо рік становить 45000000 до н.е.? Якщо так, то яким календарем ви хочете користуватися (тим більше, що ця дата передує датам календарів та людей )? Думаю, було б непогано записати день народження Діппі .
MT0

2
Зрозумійте, що малоймовірно, що календарна система залишиться незмінною ще протягом 270000 років. Чорт, навіть 1000 років. Дуже дальні розрахунки дат, мабуть, марні. Це також стосується повернення у минуле: нинішня система григоріанського календаря була остаточно закріплена у всьому світі приблизно сто років тому після Першої світової війни.
Сімба

13
Представлення 270 тис. Років = Перша світова проблема в найкращому вигляді.
CodeAngry

1
Ви задумувались про використання логарифмічної шкали?
sampathsris

Відповіді:


81

Мені не потрібно, щоб дати містили секунди або мілісекунди.

Зверніть увагу, що григоріанський календар рухається циклами 400 років, отже, циклами 240 000 років. Тому ви можете взяти представлення 60000 мілісекунд Date, яке ви не хочете використовувати, щоб повернутися назад у 240000-річні цикли (до 60000 таких циклів). Це може затягнути вас приблизно на 14,4 мільярда років до нашої ери (безпосередньо перед Великим вибухом :)) з мінімальним дозволом.

Наступний приклад не бере до уваги всю функціональність об'єкта Date. Однак при подальшому впровадженні, я вважаю, можливо мати подібну функціональність. Наприклад, один BigDate, xє більше , ніж інший BigDate, yякщо обидві дати ACі x.original > y.originalчи x.isAC()але !y.isAC(), або , якщо обидві дати BC, що або x.getFullYear() < y.getFullYear()або x.getFullYear() === y.getFullYear() && x.original > y.original.

Використання BigDate:

var time = new Date (
  [year /*range: 0-239999*/], 
  [month /*range: 0-11*/], 
  [day of month /*range: 1-31*/], 
  [hours /*range: 0-23*/], 
  [minutes /*range: 0-59*/], 
  [a factor of 240,000,000 years to go back (from the first parameter year) /*range: 0-59*/],
  [a factor of 240,000 years to go back (from the first parameter year) /*range: 0-999*/]); 
var bigDate = new BigDate(time);

HTML

<span id="years"></span>
<span id="months"></span>
<span id="date"></span>
<span id="hours"></span>
<span id="minutes"></span>
<span id="acbc"></span>

ЯВАСКРИПТ

function BigDate (date) { this.original = date; }    

// set unchanged methods,
BigDate.prototype.getMinutes = function () { return this.original.getMinutes(); }
BigDate.prototype.getHours = function () { return this.original.getHours(); }
BigDate.prototype.getDate = function () { return this.original.getDate(); }
BigDate.prototype.getMonth = function () { return this.original.getMonth(); }

// implement other BigDate methods..

І ось м’ясо:

// now return non-negative year
BigDate.prototype.getFullYear = function () {  
  var ms = this.original.getSeconds() * 1000 + this.original.getMilliseconds();
  if (ms === 0) return this.original.getFullYear();
  else return (ms * 240000) - this.original.getFullYear();
}

// now add AC/BC method
BigDate.prototype.isAC = function () {
  var result = this.original.getSeconds() === 0 &&
    this.original.getMilliseconds() === 0;
  return result;
}

Деякі демонстраційні програми (також можуть бути використані для створення BigDate.prototype.toString()тощо):

var years = document.getElementById("years");
var months = document.getElementById("months");
var date = document.getElementById("date");
var hours = document.getElementById("hours");
var minutes = document.getElementById("minutes");
var acbc = document.getElementById("acbc");

// SET A TIME AND PRESENT IT
var time = new Date (2016, 1, 28, 8, 21, 20, 200); 
var bigDate = new BigDate(time);
var monthsName = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
years.innerHTML = bigDate.getFullYear();
months.innerHTML = monthsName[bigDate.getMonth()];    
date.innerHTML = bigDate.getDate();
hours.innerHTML = bigDate.getHours() + ":";
minutes.innerHTML = bigDate.getMinutes();
acbc.innerHTML = (bigDate.isAC()) ? "AC":"BC";

Отриманий вміст буде таким: 4847996014 Jan 28 8: 21 BC

Ось JSFiddle .

Уточнення

Щодо (виправданих) зауважень до дизайну, мені відомо, що BigDateпредставлений вище об’єкт виявляє поганий інтерфейс та дизайн. Об'єкт представлений лише як приклад споживання невикористаної інформації секунд і мілісекунд для задоволення питання. Сподіваюся, цей приклад допоможе зрозуміти техніку.


@Zach Ross-Clyne Дякуємо за пропозицію щодо редагування. Я відредагував ще кілька, включаючи вашу пропозицію щодо getSeconds()використання.
guysigner

12
WTH не просто зберігає зміщення / коефіцієнт на BigDateекземплярі, замість того, щоб приховувати його в загорнутому Dateоб'єкті? Також вам слід виставити корисний конструктор, замість того, щоб дозволяти людям возитися з "факторами".
Бергі

2
Я з @Bergi. Викрадення секунд і мілісекунд є непотрібним і надзвичайно заплутаним. Це надзвичайно поганий дизайн. -1.
jpmc26,

2
Я не бачив оригіналу до редагування, але я не думаю, що ви дійсно включили дану критику у свої редакції. Я все ще бачу зміщення, вкладене в поля Dateсекунд і мілісекунд об'єкта без жодної причини (зокрема, без пояснення причини). Чому б не помістити зміщення в окремі поля поряд this.original? Не кажучи вже про майбутні великі дати, неможливо представити їх без зриву isAC(). Як заявляли інші коментатори, це поганий дизайн, і ІМО в його поточному стані не повинна бути найвищою оцінкою / прийнятою відповіддю.
св

@sv Питання не хвилювало представлення майбутніх більших дат. Щодо Ваших інших коментарів, будь ласка, дивіться додане роз’яснення у дописі.
guysigner

31

Якщо вам потрібно лише представити роки, може бути достатньо простого числа: вони можуть представляти до +/- 9007199254740991.

Ви можете обернути його у власний клас, щоб надати йому функції дати.


18

Оберніть дату

Створіть власний клас, який розширює клас Date, додавши довге ціле поле "зміщення року".

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


11

ECMAScript каже:

Об'єкт Date містить число, яке вказує конкретний момент часу з точністю до мілісекунд. Таке число називається тимчасовим значенням. Значенням часу також може бути NaN, що вказує на те, що об'єкт Date не представляє конкретний момент часу.

Час вимірюється в ECMAScript в мілісекундах з 01 січня 1970 р. За UTC. У значеннях часу стрибкові секунди ігноруються. Передбачається, що на день відбувається рівно 86 400 000 мілісекунд. Значення ECMAScript Number можуть представляти всі цілі числа від –9,007,199,254,740,992 до 9,007,199,254,740,992; цього діапазону достатньо для вимірювання часу з точністю до мілісекунд для будь-якої миті, яка знаходиться приблизно в межах 285 616 років, вперед або назад, починаючи з 01 січня 1970 р. UTC.

Фактичний діапазон часу, підтримуваний об'єктами ECMAScript Date, дещо менший: рівно –100000000 днів до 100000000 днів, виміряних відносно опівночі на початок 01 січня 1970 року за UTC. Це дає діапазон 8 640 000 000 000 000 мілісекунд до будь-якої сторони на 01 січня 1970 року за UTC.

Точний момент опівночі на початок 01 січня 1970 р. UTC представлений значенням +0.

Таким чином, ви можете створити власний метод для Дат, де ви можете використовувати ціле значення як рік. Але на практичному прикладі діапазон Ecmascript для дат досить хороший, щоб вмістити всі практичні дати. Той, якого ви намагаєтесь досягти, не має реального практичного сенсу / сенсу, оскільки навіть той, хто не впевнений, чи відповідає він вавилонській астрології ?

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