将Excel日期代码转换为“日期”


15

给定非负整数Excel样式的日期代码,以任何清楚地显示年,月和日的合理形式返回相应的“日期”。

您可能会认为微不足道。您是否注意到“吓care行情”?我使用这些是因为Excel有一些怪癖。Excel的计算与数字1天,1月1日,1900,但仿佛1900有一个1月0日和2月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正确处理leap年,但1900(不是 which 年)除外。但这是为了与产生错误的Lotus 1-2-3兼容。
里克·希区柯克

3
@RickHitchcock显然,Lotus 1-2-3开发人员这样做是为了节省leap年代码,因此该规则只是每四年一次。也有充分的理由;1900年是过去,而2100年是一段时间。
亚当

3
@RickHitchcock很有可能是原始的Lotus 1-2-3无法处理Y2K,因此Microsoft决定模仿一个问题,但否则保持正确。顺便说一句,遗产仍然存在:.NET的OADate具有时代1899-12- 30,因此它将在1900年的前两个月以外的所有时间与Excel保持一致,但这是必需的,DayOfWeek因为原始时代为1899-12-30 (或假想的1900-01-00)的选择方式是,将工作日简单地设为日期的mod-7,但不适用于1899-12-30。
亚当

4
这是有关Excel日期“为什么”的背后的故事:关于软件的Joel:我的第一个BillG评论。内容丰富(且有趣)的阅读。
BradC

Answers:


14

Excel,3(+7?)

=A1

格式

yyy/m/d

纯口


当然,输出格式可能会根据您的区域设置而有所不同。
亚当

2
这仅适用于Windows的Excel。Excel for Mac具有一个以1904年而不是1900年开始的日期的数字系统。它不会报告1900年中任何年份的日期,这是测试用例的一部分。您可能要指定这是Windows的Excel。
Keeta-恢复莫妮卡

1
@Keeta若要在Mac上的Excel上运行,只需在首选项中取消选中“使用1904年日期系统” 。
BradC

1
@BradC尽管为true,但对程序默认配置的任何更改都非常好,但必须包含在答案中。我评论这是为了改善答案。我会说要么将其名称切换为Windows版Excel,添加警告,要么切换到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如果找不到索引,则为或2 x之间的索引0 60

ˋ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?x并置意味着索引-中间的“ @”是隐式的

$ 转换为字符串


1
对于k的其他版本(我认为是k5 / k6),{$[x;$`d$x-65746;"1900.01.00"]} 似乎可行。我认为某处某处溢出100000
zgrep

@zgrep您应该发布,因为K的版本基本上是完全不同的语言。
亚当


3

JavaScript(ES6), 89 82  77字节

@tsh 节省了 7 个12字节

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确实好多了。谢谢。(另外,我想知道这种方法是否可以打高尔夫球。)
Arnauld

我只是发现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 '18 / 11/29

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
不使用内置日期处理的第一个答案。真好!
亚当


1

APL(Dyalog Classic),31个字节

匿名默认前缀功能。将日期返回为[Y,M,D]

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

在线尝试!

× 日期代码的符号

⊢- 从参数中减去该值(日期代码)

60∘>+ 如果日期代码超过60,则增加

2⎕NQ#263, 将其用作“事件263”(迄今为止的IDN)的直接参数
IDN类似于Excel的日期代码,但是没有1900年2月29日,并且1900年1月1日之前的日期是1899年12月31日

3↑ 取其中的前三个要素(第四个要素是星期几)

(…在其中)+ 添加以下内容:

60∘≠ 如果日期代码为60,则为0;否则为0。如果日期代码不是60,则为1

×- 从日期代码的符号中减去

¯3↑ 取最后三个元素(只有一个)填充(两个)零

聊天中与@Adám一起开发


1

C#(.NET Core)186185字节

using System;class P{static void Main(){var i=int.Parse(Console.ReadLine());Console.Write((i==0|i==60)?$"1900-{i%59+1}-{i%31}":DateTime.FromOADate(i+(i<60?1:0)).ToString("yyyy-M-d"));}}

在线尝试!


通过将OR运算符(||)替换为二进制OR运算符(|)来获得-1个字节。



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

换行符仅用于可读性。

根据我们的IO标准,输入是通过预先存在的表i和整数字段n进行的

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

编辑:通过更改为嵌套IIF()而不是更详细,节省了46个字节CASE WHEN

编辑2:通过将。移到-前面来保存另一个字节IIF

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.