Чому не існує справжнього типу даних "Тільки для дати"?


24

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

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

Час завжди відносно фіксованої точки. 4:00 після меридіана або полудня. Найвища точка сонця в транзиті спостерігається і дозволяє нам встановити систему координат. За 3 години до полудня (Ante Meridian), 2 години після полудня, 1441899402938 мілісекунд з 1 січня 1970 року. Для людей, вирощених у декартовому світі, це друга природа.

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

Так само і з роками, що повторюються. Кожні 365 днів (або близько того) для мене є декілька особливих днів: дні народження, ювілеї, дитячі дні народження тощо. Програми бізнес-планування містять приклади зустрічей кожні сім днів, перший вівторок місяця тощо. Просто тому ми МОЖЕМЕ відобразити це на номер з плаваючою комою, а насправді відображення його на вказане число вирішує багато проблем, які по-старому дуже важкі, але це не означає, що це єдиний спосіб зробити це.

Поінформованість та розуміння природи «квадратного кілка в круглу дірку» використання DateTimes для зберігання дат робить вас кращим програмістом.

Чи є значення в додатку, явно призначеному як додаток для планування, для визначення класу дати, чи найкращий підхід "встановлений весь час до полудня"? Які проблеми можуть виникнути при використанні DateTime та встановленні компонента Time на полудень? Чи можна змінити часовий пояс таким чином? Я використовував MomentJS, але думаю, що це просто кращий клас дати.


7
це досить цікаве питання, я думаю. Візьмемо приклад іменинника, це по-справжньому має сенс по-людськи, я живу в одному місці, і всі прокидаються в той же час, вид дороги. як тільки вам потрібно це виразити математично, це стає дуже складним. Те ж саме з речами , як робота зрушення початку / кінця часів і т.д. вони Арент «раз» вони «годин дня в часовому поясі , в якому ви працюєте»
Ewan

3
NodaTime (бібліотека C # для дати та часу) має тип дат.
CodesInChaos

5
Зберігайте свої часи як UTC, жодних проблем з датою, без часових поясів.
Лорен Печтел

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

5
@MichaelBlackburn Я серйозно. У вашому поясненні звучить саме ситуація щодо власного типу даних, який виконує ділове правило (лише дата, наприклад, ви можете зберігати його як "DateTime" внутрішньо з часовою частиною, встановленою до полудня), але потім виставляйте лише потрібні частини (місяць , день тощо рік / немає року).
Брандін

Відповіді:


15

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

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

Дозвольте коротко зазначити, що неправда, що всі мови програмування пропонують лише тимчасові типи даних, які включають часовий компонент. Я натрапив на типи даних лише для дат у RDBMS і в відповідних діалектах SQL. Але це не має значення: той факт, що ці типи даних існують, не означає, що їх добре мати, а RDBMS мають довгу історію плутання пам’яті з представленням.

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

Наприклад, у DateTimeтипі даних Microsoft Dotnet одиниця часу становить 100 наносекунд, а початок часу - 12:00, опівночі, 1 січня, 0001 р. Н.е.

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

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

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

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


4
Це не вірно для "Днів", які є концепцією, навіть старшою за Час. Їх найбільш правильно вважати перерахунком або модулем. Неділя слідує за понеділком тощо, поки ми не повернемося до неділі, яка йде в суботу. Це справді інша річ.
Майкл Блекберн

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

4
-1: Не всі способи використання часу представляють єдиний момент у часі. День народження - це інша ідея, представлена ​​місяцем і днем ​​у григоріанському календарі. Є сенс запитати "чи сьогодні день народження Кевіна?" Відповідь залежить від місця. Якби я в Сіднеї, це міг би бути моїм днем ​​народження, але якби я був у Гонолулу, це не було б ще кілька годин.
кевін клайн

6
@MikeNakis Результатом стали б мікроампери, а не дурниці. Більш важливо: коли ви використовуєте дату, а не другу чи мілісекунду, ви, як правило, говорите про весь день - часовий період - а не про конкретний час, і залежно від контексту це може бути повторювана подія.
Калеб

4
В ОП говорили про дні народження, які точно представлені java.util.MonthDay. День народження - це не вимір, це людське уявлення про день, який повторюється щороку. Існує безліч людських уявлень про час, які не представлені жодною точкою в часі.
кевін клайн

9

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

DateTimeТипу присутня в багатьох мовах є точну точку в часі ( «миттєве час»). Крім цього, у нас є ряд відносних чи «людських» понять часу та часового простору, таких як календарні дні, періодичні дати, місяці, роки тощо, які в багатьох випадках неоднозначні та залежать від контексту. Ці типи не є настільки корисними для всіх, але необхідні в певних областях застосування, таких як календарі, інструменти планування та інші програми, які взаємодіють із людськими поняттями часу.

Якщо ви пишете щось на зразок програми для календаря, ви, безумовно, отримаєте користь від використання такої бібліотеки, як Joda-time, яка забезпечує більш багатий набір типів часу. Наприклад LocalDate, побачення без часу. Це має іншу семантику, ніж звичайна, DateTimeз часовою частиною, встановленою на нуль, оскільки DateTimeнерухомість вказує на конкретний момент часу (опівночі в конкретному часовому поясі), в той час як LocalDateпозначає цілий день і не прив’язана до конкретного часового поясу. Це також означає, що ви не можете безпосередньо перекласти один на інший.

LocalDateце, звичайно, простіше, ніж DateTimeтому, що не потрібно враховувати часові пояси, але ви повинні бути в курсі інших питань, наприклад, що поточна дата може фактично піти назад, коли ви перетинаєте часовий пояс, і що той самий момент у часі може відповідають різним датам у різних часових поясах. Якщо ви використовуєте місцеві дати в мережевих або веб-додатках, ви повинні бути дуже обережними щодо цих проблем. Видалення часової частини з дати не вирішує фундаментальної проблеми часових поясів! І якщо взяти до уваги історичні дати та різні культури, це стає ще складніше, оскільки ця дата може відповідати дико різним випадкам у часі, скажімо, Юліанському проти григоріанського календаря.

Тепер ви запитуєте, чому мови не мають щось подібне до LocalDate вбудованого . Перш за все, деякі мови, такі як SQL та Visual Basic, мають тип дати без часової частини. І Java також додала LocalDateв останній версії. Але інших платформ типу .Net цього немає. Тільки мовні дизайнери дійсно можуть відповісти, чому це не включено до стандартної бібліотеки, але я гадаю, що «миттєвий час» концептуально простий і універсально корисний, тоді як інші часові концепції корисні лише для конкретних областей додатків (наприклад, календарі тощо) .). Тому має сенс дозволити розробнику програми писати власні типи для обробки складніших випадків використання або дозволити їм обробляти сторонні бібліотеки (наприклад, Joda-time).


5

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

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

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

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

Усі ці факти цитуються з чудового FAQ, який можна знайти в бібліотеці календарів для OCaml, написаного Жульєном Синьоллом.

  1. Юліанський календар був введений Юлієм Цезарем у 45 р. До н. Це було загальним вживанням до 1500-х років, коли країни почали змінювати григоріанський календар (розділ 2.2). Однак деякі країни (наприклад, Греція та Росія) використовували його в 1900-х роках, а православна церква в Росії досі використовує його, як і деякі інші православні церкви.

  2. Перехід з юліанського на григоріанський календар не відбувся рівномірно, і залежно від року зміни було відмінено 10 - 13 днів. Наприклад, у Франції 9 грудня 1582 року відбувся 20 грудня 1582 р., А в Греції 9 березня 1924 р. 23 березня 1924 р.

  3. Навіть в сучасну епоху використовується багато різних календарів (григоріанських, православних, ісламських та китайських), щоб цитувати їх декілька, які використовують різні способи обчислення років та ювілеїв чи дати релігійних святкувань.

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

  1. Частини року (наприклад, "6 місяців" відповідає "0,5"), які використовуються разом із відсотковою ставкою для обчислення фактичних відсотків за позикою за певний термін. Існує від 6 до 10 рецептів для обчислення цих дробів, кожен з яких відрізняється способами обробки тривалості високосного року, положенням періоду щодо останнього дня лютого та тривалістю місяця.

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

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

Чи є значення в додатку, явно призначеному як додаток для планування, для визначення класу дати, чи найкращий підхід "встановлений весь час до полудня"? Які проблеми можуть виникнути при використанні DateTime та встановленні компонента Time на полудень? Чи можна змінити часовий пояс таким чином? Я використовував MomentJS, але думаю, що це просто кращий клас дати.

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


2

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

Ви говорите з такими уявленнями, коли ви посилаєтесь на День тижня як просто якийсь модульний вид подання фактичного моменту часу. Насправді це дещо складніше. Якщо вам було доручено написати функцію, яка поверне День тижня для заданого моменту часу, врахуйте наступну інформацію, яка вам знадобиться в якості введення для такого алгоритму. Вам знадобиться врахувати момент часу, Календар, часовий пояс, який слід врахувати (Майте на увазі, часові пояси змінюються ВСЕ ЧАС, тому вам потрібно знати, коли почався цей ефективний часовий пояс, коли він закінчився в конкретні часові координати. Північна Корея нещодавно просто наприклад, змінили їх!), і якщо діє літній час, це змінюється з часом. Тепер подумайте, чи вам було надано DateTime у локальному часовому поясі,

Ви можете бачити, наскільки складним може бути справді таке, здавалося б, просте питання.

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

Час справді є координатою, але крім простої дати, врахуйте інші дані, які залежать від часу, які можуть знадобитися, наприклад:

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

Як користувач, я хотів би, щоб це завдання було виконано через 15 секунд після завершення опівночі кожну другу середу.

Інтервал: діапазон часу між двома конкретними координатами часу. Випадок використання, коли ви можете розглянути інтервал.

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

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

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

  • Конкретні точки або діапазони часу повинні зберігатися в UTC або якийсь тип даних, який містить достатньо інформації, щоб можна було легко абстрагуватися назад до UTC, де це було потрібно
  • Логіку програми слід записати для форматування UTC або діапазону координат UTC у стан репрезентативних даних, який є більш засвоюваним для кінцевого користувача.
  • Важливі тривалості повинні зберігатися в мілісекундах
  • Спеціальні налаштування або кінцеві користувальницькі налаштування на відображенні будь-яких даних щодо часу повинні зберігатися як додаткові дані та оброблятися як варіант відображення. (Наприклад, кіоск A, центральний часовий пояс, формат військового часу або налаштування користувача B, стандартний час у часовому поясі Тель-Авіва (GMT + 7: 00) та ін.)
  • Уникайте FP-номерів

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

1
@AlanShutko І так, потрібні "додаткові дані" - це такі, як місцевий часовий пояс, і "Дні" та будь-які інші важливі дані, які потрібно захопити. Це все лише абстракції, однак до одного моменту часу, навіть якщо момент часу не важливий для вашого алгоритму. Що стосується наносекундної та навіть мікросекундної шкали, моя відповідь орієнтована більше на програмне забезпечення типу Web та LOB. Я сумніваюся, що обраною мовою LHC є C # або Javascript.
maple_shaft

1
Мільсекунди чудово підходять для повторюваних фізичних процесів. Для людської діяльності іноді відповідною одиницею є номінальні дні, наприклад, якщо вона буде доставлена ​​наприкінці дня, вона буде доступна для використання в пункті призначення через три дні.
кевін клайн

Раніше я розглядав можливість використання 64-розрядних чисел з плаваючою точкою для координат часу, а ще важливіше - для часових проміжків, оскільки вони дозволяють виражати крихітні величини з великою точністю, а також величезні величини, де втрата точності насправді не має значення. . (То що робити, якщо динозаври померли 65 мільйонів років тому дають чи забирають кілька років?) Отже, чому ви говорите, що їх слід уникати?
Майк Накіс

Майк, я думаю, що його стурбованість математикою FP неминуче округляється, оскільки вона перетворюється з десяткових у двійкові значення. Наприклад, 0,3 є десятковим, що повторюється, коли виражається у вигляді двійкового FP-числа, і тому не може бути представлений точно. Справа не в тому, що вам не вистачає потужності, але вам не вистачає точності.
Майкл Блекберн

2

Коротше кажучи, оскільки більшість типів часу на комп'ютері орієнтовані на належне керування проблемою часу та часового поясу.

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

Інший - це (відповідно до питання) моделювання довільної інформації про дату, наприклад запису дати народження людини. Уявіть випадок, коли двоє людей народжуються одночасно, одна в Новій Зеландії, а друга на Гаваях. Ймовірність полягає в тому, що вони матимуть різні дати народження у своїх паспортах, і якщо людина, що народилася на Гаваях, переїжджає на Нову Зеландію, вони вважатимуться на день старше новонародженого, незважаючи на те, що прожили точно такий же час.

Пропозиція у питанні про встановлення дати, щоб мати час полудня, UTC буде працювати, але ВСІМО скрізь. Зсув за UTC становить від -12 до +14, тому в тихоокеанських місцях є кілька місць, де такий підхід не зможе. Я схильний розглядати ці типи даних як рядки у yyyymmdd форматі, і якщо мені доведеться робити порівняння обчислень між двома датами, це можна сміливо зробити як порівняння рядків. Здійснюючи дельта-порівняння (наприклад, між датою та теперішньою кількістю часу або до досягнення ними віку X), потрібно переконатися, що всі дати створені в одному зміщенні UTC, а потім можна використовувати стандартні функції часу для виконання роботи.


3
" Я схильний трактувати ці типи даних як рядки у форматі yyymmdd, і якщо мені доведеться робити порівняння обчислень між двома датами, це можна сміливо зробити як порівняння рядків ". Це впевнено звучить як Dateтип даних, просто переноситься в aString
Росс Паттерсон

Як ви кажете, його рядкове зображення дати, на відміну від оригінального плаката, дата не змінюється, перебуваючи в часовому поясі UTC + 13.
Майкл Шоу

2

Чому не існує справжнього типу даних "Тільки для дати"?

З тих же причин, я думаю, що значення DateTime, як правило, вказані в UTC: простота та надійність . Точкою значення DateTime є вказівка ​​єдиного моменту часу, який не впливає на часовий пояс, економію денного світла, календар та інші місцеві коригування. Значення DateTime вказують один момент (до межі роздільної здатності типу), а не часовий період або набір разів. Ці обмеження дозволяють порівняти значення DateTime надійним, передбачуваним, нескладним способом.

Намагатися вказати дату зі значенням DateTime - це як намагатися використовувати точку для вказівки області.Ви можете зробити цю роботу, використовуючи конвенцію, наприклад, "ця точка являє собою центр кола з радіусом 100 м", але там є багато проблем: всім потрібно використовувати ту саму умову, вам потрібно написати купу підтримуючий код, щоб зробити роботу з неправильним типом менш болісним, і майже гарантується, що в якийсь момент вам потрібно буде вказати площу, яка більша або менша, ніж звичайна. Так і з датами: ви можете використовувати "полудень" як звичайний час для визначення дат, але потім ви потрапляєте у часові пояси, оскільки люди очікують, що дати вказуватимуть у місцевому часі, а не UTC. І навіть якщо ви знайдете задовільний спосіб використовувати DateTime для визначення дати, вам знадобиться додаткова інформація, щоб знати, чи це абсолютна дата, чи відносна: чи це 4 липня, 1776 р. Чи кожного 4 липня? Що робити, якщо ви хочете повторити, використовуючи якийсь інший період? І календарі мають всілякі шалені питання: деякі місяці довші за інші, деякі роки довші за інших, деякі дні навіть довші за інші, а деякі календарі мають у них прогалини. Ви б не хотіли вирішувати ці проблеми лише цілі дні, тому що одні й ті ж проблеми виникають на більш короткі терміни: ви, мабуть, хочете мати можливість писати код, який виражає "приймати по 1 таблетці кожні 4 години" так само легко, як " гурт збирається щороку третю п’ятницю ».

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

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


2
"Складно надати тип, який стосується всіх способів використання дат." Щоправда, ось чому жахлива ідея намагатися надати єдиний тип, щоб зробити це все. Перші версії Java дали лише java.util.Date, і результат був жахливим. Потім вони додали складну ієрархію java.util.Calendar, і це не стало набагато краще.
кевін клайн

1
@kevincline Повністю згоден. ОП не вказав мову, тому я прагнув загальності.
Калеб

" З тих же причин, я думаю, що значення DateTime, як правило, задаються в UTC " ... О, чи це було б правдою. Настав 2015 рік, і ще багато написано коду, використовуючи домашній часовий пояс автора :-(
Росс Паттерсон

1
Мені справді було цікаво, чому не існує загальновизнаної конвенції щодо дат. Ваше "використання точки, щоб зобразити область", ідеально інкапсулює моє розчарування.
Майкл Блекберн

2

Чому не існує справжнього типу даних "Тільки для дати"?

У різних бібліотеках для різних мов існує багато таких типів. Існує майже напевно один для вашої поточної мови. Пакет Java util мав жахливий API для обчислення часу, але впровадження пакету java.time зробило життя набагато кращим. Див. Розділ java.time.LocalDate, що містить значення року-місяця, або java.time.MonthDay, що містить лише місяць та день.


1

Календарі маніпулювання - один з найбідніших аспектів обчислень. Цілі книги написані на цю тему. @MichealBlackburn абсолютно вірно запитує тип даних, призначений лише для дати, який не вирішує до точки на часовій шкалі, за умови повторної інтерпретації. Історично існували законні суперечки щодо значення дати. Треба не шукати далі, ніж прийняття григоріанського календаря, щоб знайти, наскільки він складний. Крім того, роки не завжди починалися з 1 січня навіть у Західній Європі та її колоніях ( наприклад , Британія та Британська Америка розпочали рік 25 березня).


1
Це правильно. Поширені питання календаря, які я цитую у своїй відповіді, - це чудовий ресурс для виявлення складнощів і тонкощів підданих маніпуляцій
Майкл Ле Барб'є Грюневальд

-2

У відповідь на:

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

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

date = new DateTime(year, month, day, 0, 0, 0);

Якщо ви хочете, можете продовжити DateTime самостійно:

public class Date extends DateTime {
    ...
    public Date(int year, int month, int day) {
        this(year, month, day, 0, 0, 0);
    }
}

Примітка. Я навмисно ігнорую час та часовий пояс за замовчуванням. Насправді не важливо, на що ви їх встановили, якщо вони однакові для всіх Dates. Ви можете зробити справу за UTC. Ви можете зробити випадок використання часового поясу, на якому знаходиться ваш сервер - в будь-якому випадку, я не думаю, що це важливо для представлення неточного значення, як Date. Те саме з часом за замовчуванням - ви можете зробити це 0, ви можете зробити полудень. Це не має значення. Якщо Facebook надішле мені повідомлення про день народження о 00:01, але я народився о 23:59, мені це дуже не цікаво, і я не буду ображатися, що вони були більше 12 годин.

Вищезазначене є на Java, але працює аналогічно на будь-якій мові, яка має DateTimeспадщину. Насправді у Java є численні способи вирішення цього питання, і вищесказане застаріле (вони хочуть, щоб ви Calendarзараз використовували ). Але як і інші повідомлення в коментарях, деякі мови на насправді дійсно забезпечують Dateклас, по- видимому саме по цій причині.

DateЙмовірно , кожна реалізація, ймовірно, є лише обгорткою для мови, DateTimeі вона нулює час. Інакше вам знадобиться скопійований код, щоб вирішити такі проблеми, як кількість днів між двома датами / датами, або два рівні Dates (що про 29 лютого та 1 березня?). Такі речі зазвичай вирішуються на DateTimeуроці. Є сенс повторно використовувати той самий код для Date.


4
-1: Використовуйте LocalDate, якщо ви хочете лише рік + місяць + день. Використання DateTime для цієї мети призведе до помилок, коли інший програміст бачить DateTime і припускає, що він представляє момент у часі.
кевін клайн

@kevincline Я не вважав це необхідним, оскільки це питання є мовним. Я також думаю, що очевидно, що використання коду, який позначений як "Застарілий", є сценарієм використання за власним ризиком. Що ще важливіше, я використовував це лише як приклад того, що ви можете зробити в сценарії, коли мова не має класу LocalDateабо Dateкласу типу, і вам доведеться "згорнути свій власний".
Шаз

1
Але "це необхідно" для чіткого стислого і правильного коду, що включає правила бізнесу про час (на відміну від фізичного часу). якщо бібліотека не надає типи для номінального часу, програмісту потрібно буде їх винайти, і спосіб зробити це не починається з "DateTime".
кевін клайн

@kevincline Я не бачу, як код був би менш чітким чи стислим. Яка різниця з точки зору програміста між new Date(2000, 1, 1);і new Date(2000, 1, 1);? Чи можете ви сказати, хто з них порожні години, хвилини та секунди? Якщо ви переживаєте за появу додаткових функцій (наприклад, setMinutes ()), ви можете піти шляхом Dateобертання, DateTimeа не успадковувати його, а потім виставляєте лише setYear, setMonth, setDay тощо. І це, звичайно, не менше правильніше, ніж дата-час бібліотеки, який ви використовуєте.
Шаз

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