Перетворіть код дати Excel у «дату»


15

Враховуючи невід'ємний цілий код дати в стилі Excel, поверніть відповідну "дату" в будь-якій розумній формі, яка чітко показує рік, місяць та "день".

Тривіально, ви можете подумати. Ви помітили "відлякуючі цитати"? Я використовував їх, тому що в Excel є деякі химерності. Excel підраховує дні з цифрою 1 на 1 січня ст , 1900, але , як якщо б 1900 був січня 0 - й і 29 лютого - го , так що будьте дуже обережні , щоб спробувати всі тестові випадки:

 Input → Output (example format)
     0 → 1900-01-00    Note: NOT 1899-12-31
     1 → 1900-01-01
     2 → 1900-01-02
    59 → 1900-02-28
    60 → 1900-02-29    Note: NOT 1900-03-01
    61 → 1900-03-01
   100 → 1900-04-09
  1000 → 1902-09-26
 10000 → 1927-05-18
100000 → 2173-10-14

1
Чи є щороку 0 січня та 29 лютого чи 1900 рік є єдиною аномалією?
Кудлатий

4
1900 рік - аномалія. Excel трактує високосні роки, за винятком 1900 року (що не високосний рік). Але це було для сумісності з Lotus 1-2-3, звідки виникла помилка.
Рік Хічкок

3
@RickHitchcock Мабуть, Lotus 1-2-3 devs зробив це, щоб заощадити на високосному коді року, таким чином правило просто стало кожні четвертий рік. З вагомою причиною теж; 1900 рік був далеко в минулому, а 2100 - ну, через деякий час.
Adám

3
@RickHitchcock Можливо, оригінальний Lotus 1-2-3 не міг би впоратися з Y2K, і тому Microsoft вирішила імітувати цю проблему, але в іншому випадку залишається правильною. До речі, спадщина живе на: OADate .NET має епоху 1899-12- 30 так , що вона буде вибудовуватися з Excel на всіх , крім перших двох місяців 1900 року , однак це вимагає DayOfWeekметод , тому що оригінальна епоха, 1899-12-30 (або вигаданий 1900-01-00) був обраний таким, що будній день просто був мод-7 числа дня, але це не спрацює з 1899-12-30.
Адам

4
Ось історія за "чому" про дати Excel: Joel on Software: My First BillG Review . Інформаційне (і розважальне) читання.
BradC

Відповіді:


14

Excel, 3 (+7?)

=A1

з форматом

yyy/m/d

Чистий порт


Формат виводу, звичайно, може змінюватися залежно від вашої мови.
Adám

2
Це працює лише в Excel для Windows. У Excel для Mac є система числення, яка починається з дат у 1904, а не в 1900 році. Вона не повідомляє про дату жодного року в 1900 році, які є частиною тестових випадків. Ви можете уточнити, що це Excel для Windows.
Keeta - відновити Моніку

1
@Keeta Для роботи в Excel для Mac просто зніміть прапорець "Використовувати систему дат 1904" у налаштуваннях .
BradC

1
@BradC Хоча це правда, будь-яке зміна конфігурації програми за замовчуванням ідеально добре, АЛЕ у відповіді повинно бути включено. Я коментую це як пункт для покращення відповіді. Я б сказав, що або перемкніть його ім'я в Excel для Windows, додайте застереження, або перейдіть на OpenOffice Calc (або подібне, оскільки вони цілеспрямовано включають і помилку). codegolf.meta.stackexchange.com/questions/10037/…
Keeta - відновити Моніку

6

k (kdb + 3,5), 55 54 51 50 байт

{$(`1900.01.00`1900.02.29,"d"$x-36526-x<60)0 60?x}

щоб перевірити, вставте цей рядок у консоль q:

k)-1@{$(`1900.01.00`1900.02.29,"d"$x-36526-x<60)0 60?x}'0 1 2 59 60 61 100 1000 10000 100000;

вихід повинен бути

1900.01.00
1900.01.01
1900.01.02
1900.02.28
1900.02.29
1900.03.01
1900.04.09
1902.09.26
1927.05.18
2173.10.14

{ } - це функція з аргументом x

0 60?xіндекс xсеред 0 60або 2, якщо вони не знайдені

ˋ1900.01.00ˋ1900.02.29 список двох символів

, додавати до нього

"d"$ перетворений на дату

x-36526 кількість днів з 1900 року (замість 2000 року за замовчуванням)

- x<60 відрегулювати помилку стрибка у програмі Excel

(ˋ1900.01.00ˋ1900.02.29,"d"$x-36526-x<60)@ 0 60?xjuxtaposition означає індексацію - середина "@" неявна

$ перетворити в рядок


1
Для іншої версії k (k5 / k6, я думаю) працює, {$[x;$`d$x-65746;"1900.01.00"]} здається, працює . Я припускаю, що десь переповнюється 100000.
zgrep

@zgrep Ви повинні розміщувати повідомлення, оскільки версії K в основному є абсолютно різними мовами.
Adám


3

JavaScript (ES6),  89 82  77 байт

Збережено  7  12 байт завдяки @tsh

n=>(p=n>60?'':19)+new Date(p*400,0,n-!p||1).toJSON().slice(p/9,10-!n)+(n&&'')

Спробуйте в Інтернеті!


n=>n?n-60?new Date(1900,0,n-(n>60)).toJSON().slice(0,10):'1900-02-29':'1900-01-00'
tsh

@tsh Це набагато краще. Спасибі. (Також мені цікаво, чи міг би такий підхід якось пограти в гольф.)
Арнольд

Я просто дізнаюся, що new Date(0,0,1)це те саме new Date(1900,0,1). Так вилучіть, 190економить 3 байти. І ...
tsh

2
77 байт:n=>(p=n>60?'':19)+new Date(p*400,0,n-!p||1).toJSON().slice(p/9,10-!n)+(n&&'')
tsh

Чи потрібно це запускати в GMT0 / -x?
l4m2

2

Чисто , 205 189 байт

import StdEnv
a=30;b=31;c=1900;r=rem
@m=sum(take m(?c))
?n=[b,if(n>c&&(r n 4>0||r n 100<1&&r n 400>0))28 29,b,a,b,a,b,b,a,b,a,b: ?(n+1)]
$n#m=while(\m= @m<n)inc 0-1
=(c+m/12,1+r m 12,n- @m)

Спробуйте в Інтернеті!


1
Перша відповідь, що не використовується вбудована обробка дат. Приємно!
Adám


1

APL (Dyalog Classic) , 31 байт

Функція анонімного мовчазного префікса. Повертає дату як[Y,M,D]

3↑×-60∘≠)+32NQ#263,60∘>+⊢-×

Спробуйте в Інтернеті!

× знак коду дати

⊢- відніміть це з аргументу (код дати)

60∘>+ приріст, якщо код дати перевищує шістдесят

2⎕NQ#263, використовувати його в якості безпосереднього аргументу для «Event 263» (IDN на сьогоднішній день)
IDN тільки як код дати Excel, але без 29 Лютого 1900 р і за день до 1 січня 1900 року є 31 грудня 1899

3↑ візьміть перші три елементи цього (четвертий - день тижня)

()+ Додати до них:

60∘≠ 0, якщо код дати 60; 1, якщо код дати не 60

×- відняти це від знака коду дати

¯3↑ візьміть останні три елементи (є лише один) набивання з (двома) нулями

розроблений разом з @ Adám в чаті




0

T-SQL, 141 95 94 байт

SELECT IIF(n=0,'1/0/1900',IIF(n=60,'2/29/1900',
FORMAT(DATEADD(d,n,-IIF(n<60,1,2)),'d')))FROM i

Розрив рядка призначений лише для читабельності.

Введення проводиться через попередньо існуючу таблицю i з цілим полем n , відповідно до наших стандартів IO .

SQL використовує аналогічну (але виправлену) 1-1-1900 вихідну точку для свого внутрішнього формату дати, тому мені потрібно лише компенсувати його на 1 або 2 дні у DATEADDфункції.

SQL не може вивести стовпчик, що містить поєднання значень дати та символів, тому я не можу залишити FORMATкоманду (оскільки вона потім намагатиметься перетворити 1/0/1900на дату, що, звичайно, недійсне).

Що приємно в SQL, це те, що я можу завантажити всі вхідні значення в таблицю і запустити їх усі відразу. Мої (США) місцеположення за замовчуванням у m/d/yyyyформаті дати:

n       output
0       1/0/1900
1       1/1/1900
2       1/2/1900
59      2/28/1900
60      2/29/1900
61      3/1/1900
100     4/9/1900
1000    9/26/1902
10000   5/18/1927
43432   11/28/2018
100000  10/14/2173

EDIT : Збережено 46 байт, змінивши вкладене, IIF()а не багатослівне CASE WHEN.

EDIT 2 : Збережено ще один байт, перемістивши -попереду IIF.

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