Excel日期到Unix时间戳

时间:2009-11-09 20:21:55

标签: excel

有谁知道如何将Excel日期转换为正确的Unix时间戳?

11 个答案:

答案 0 :(得分:99)

这些不适用于我......当我将时间戳转换回来时,已有4年了。

这非常有效:=(A2-DATE(1970,1,1))*86400

归功于:Filip Czaja http://fczaja.blogspot.ca

原帖:http://fczaja.blogspot.ca/2011/06/convert-excel-date-into-timestamp.html

答案 1 :(得分:68)

Windows和Mac Excel(2011):

Unix Timestamp = (Excel Timestamp - 25569) * 86400
Excel Timestamp =  (Unix Timestamp / 86400) + 25569

MAC OS X(2007):

Unix Timestamp = (Excel Timestamp - 24107) * 86400
Excel Timestamp =  (Unix Timestamp / 86400) + 24107

供参考:

86400 = Seconds in a day
25569 = Days between 1970/01/01 and 1900/01/01 (min date in Windows Excel)
24107 = Days between 1970/01/01 and 1904/01/02 (min date in Mac Excel 2007)

答案 2 :(得分:11)

如果我们假设Excel中的日期是A1格式的日期格式,并且Unix时间戳应该是格式化为数字的A2格式,则A2中的公式应为:

=(A1 * 86400) - 2209075200

其中:

86400是当天的秒数 2209075200是1900-01-01和1970-01-01之间的秒数,它们是Excel和Unix时间戳的基准日期。

以上适用于Windows。在Mac上,Excel中的基准日期为1904-01-01,秒数应更正为:2082844800

答案 3 :(得分:6)

以下是一个参考映射,假设UTC适用于Microsoft Excel等电子表格系统:

                         Unix  Excel Mac    Excel    Human Date  Human Time
Excel Epoch       -2209075200      -1462        0    1900/01/00* 00:00:00 (local)
Excel ≤ 2011 Mac† -2082758400          0     1462    1904/12/31  00:00:00 (local)
Unix Epoch                  0      24107    25569    1970/01/01  00:00:00 UTC
Example Below      1234567890      38395.6  39857.6  2009/02/13  23:31:30 UTC
Signed Int Max     2147483648      51886    50424    2038/01/19  03:14:08 UTC

One Second                  1       0.0000115740…             —  00:00:01
One Hour                 3600       0.0416666666…             ―  01:00:00
One Day                 86400          1        1             ―  24:00:00

* “Jan Zero,1900”是1899/12/31;请参阅下面的错误部分。 Excel 2011 for Mac(及更早版本)使用1904 date system

由于我经常使用awk处理CSV和空格分隔的内容,因此我开发了一种将UNIX纪元转换为时区/ DST的方法 - 适当的 Excel日期格式:

echo 1234567890 |awk '{ 
  # tries GNU date, tries BSD date on failure
  cmd = sprintf("date -d@%d +%%z 2>/dev/null || date -jf %%s %d +%%z", $1, $1)
  cmd |getline tz                                # read in time-specific offset
  hours = substr(tz, 2, 2) + substr(tz, 4) / 60  # hours + minutes (hi, India)
  if (tz ~ /^-/) hours *= -1                     # offset direction (east/west)
  excel = $1/86400 + hours/24 + 25569            # as days, plus offset
  printf "%.9f\n", excel
}'

我在这个例子中使用了echo,但你可以管道一个文件,其中第一列(对于.csv格式的第一个单元格,称为awk -F,)是一个UNIX纪元。更改$1代表您想要的列/单元格编号或改为使用变量。

这使系统调用date。如果您可靠地拥有GNU版本,则可以删除2>/dev/null || date … +%%z和第二个, $1。考虑到GNU的常见程度,我不建议假设BSD的版本。

getlinedate +%z输出的时区偏移读入tz,然后将其转换为hours。格式类似于-0700PDT)或+0530IST),因此提取的第一个子字符串为0705,第二个是0030(然后除以60以小时表示),第三次使用tz查看我们的偏移量是否为负数,并在需要时更改hours

此页面上所有其他答案中给出的公式用于设置excel,并将日光节省感知时区调整添加为hours/24

如果您使用的是旧版Excel for Mac,则需要使用24107代替25569(请参阅上面的映射)。

使用GNU日期将任意非纪元时间转换为Excel友好时间:

echo "last thursday" |awk '{ 
  cmd = sprintf("date -d \"%s\" +\"%%s %%z\"", $0)
  cmd |getline
  hours = substr($2, 2, 2) + substr($2, 4) / 60
  if ($2 ~ /^-/) hours *= -1
  excel = $1/86400 + hours/24 + 25569
  printf "%.9f\n", excel
}'

这基本上是相同的代码,但date -d不再有@代表unix时代(考虑到字符串解析器的能力,我实际上对@感到惊讶是强制性的;其他日期格式有9-10位?)现在要求两个输出:纪元和时区偏移。因此你可以使用例如@1234567890作为输入。

错误

Lotus 1-2-3(原始的电子表格软件)故意treated 1900 as a leap year,尽管它不是(这在每个字节计数时减少了代码库)。 Microsoft Excel retained这个兼容性错误,跳过第60天(虚构的1900/02/29),保留Lotus 1-2-3的第59天到1900/02/28的映射。相反,LibreOffice分配了第60天到1900/02/28,并将之前的所有日期都推回了一天。

1900/03/01之前的任何日期都可能休息一天:

Day        Excel   LibreOffice
-1            -1    1899/12/29
 0    1900/01/00*   1899/12/30
 1    1900/01/01    1899/12/31
 2    1900/01/02    1900/01/01
 …
59    1900/02/28    1900/02/27
60    1900/02/29(!) 1900/02/28
61    1900/03/01    1900/03/01

Excel不承认否定日期,并且对第0天的1月份(1899/12/31)有一个特殊的定义。在内部,Excel确实处理负日期(它们毕竟只是数字),但它将它们显示为数字,因为它不知道如何将它们显示为日期(也不能将旧日期转换为负数)。 1900年2月29日,一个从未发生过的日子,被Excel认可,但不是LibreOffice。

答案 4 :(得分:3)

因为我对上述内容的编辑被拒绝了(你们其中任何人真的尝试过吗?),这就是你真正需要做的工作:

Windows(和Mac Office 2011 +):

  • Unix时间戳= (Excel Timestamp - 25569) * 86400
  • Excel时间戳= (Unix Timestamp / 86400) + 25569

MAC OS X(Office 2011之前):

  • Unix时间戳= (Excel Timestamp - 24107) * 86400
  • Excel时间戳= (Unix Timestamp / 86400) + 24107

答案 5 :(得分:2)

你显然已经休息了一天,恰好是86400秒。 使用数字2209161600 不是数字2209075200 如果你谷歌这两个数字,你会发现上述支持。 我尝试了你的公式,但总是与我的服务器不同1天。从unix时间戳开始并不明显,除非你在unix而不是人类时间考虑;-)但是如果你仔细检查那么你会发现这可能是正确的。

答案 6 :(得分:1)

我有一个带有“人类可读”日期的旧Excel数据库,例如 2010.03.28 20:12:30 这些日期以UTC + 1(CET)为单位,需要将其转换为纪元时间。

我使用 =(A4-DATE(1970; 1; 1))* 86400-3600 公式将日期从A列转换为B列值。 检查您的时区偏移量并进行数学计算。 1小时是3600秒。

我在这里写答案的唯一一件事是,您可以看到该主题已有5年的历史了,因为我使用的是新的Excel版本以及该主题中的红色帖子,但它们不正确。 DATE(1970; 1; 1)。这里的1970年和1月需要分开;而不是,

如果您也遇到此问题,希望对您有所帮助。 祝你有美好的一天:)

答案 7 :(得分:0)

目前的答案都没有对我有用,因为我的数据来自unix方面的格式:

2016-02-02 19:21:42 UTC

我需要将其转换为Epoch以允许引用具有纪元时间戳的其他数据。

  1. 为日期部分创建一个新列,并使用此公式进行解析

    =DATEVALUE(MID(A2,6,2) & "/" & MID(A2,9,2) & "/" & MID(A2,1,4)) 
    
  2. 正如其他Grendler已在此处所述,创建另一列

    =(B2-DATE(1970,1,1))*86400 
    
  3. 创建另一列,只添加时间以获得总秒数:

    =(VALUE(MID(A2,12,2))*60*60+VALUE(MID(A2,15,2))*60+VALUE(MID(A2,18,2)))
    
  4. 创建最后一列,只将最后两列添加到一起:

    =C2+D2
    

答案 8 :(得分:0)

这是我对此的最终答案。

显然,javascript的new Date(year, month, day)构造函数也没有考虑闰秒。

// Parses an Excel Date ("serial") into a
// corresponding javascript Date in UTC+0 timezone.
//
// Doesn't account for leap seconds.
// Therefore is not 100% correct.
// But will do, I guess, since we're
// not doing rocket science here.
//
// https://www.pcworld.com/article/3063622/software/mastering-excel-date-time-serial-numbers-networkdays-datevalue-and-more.html
// "If you need to calculate dates in your spreadsheets,
//  Excel uses its own unique system, which it calls Serial Numbers".
//
lib.parseExcelDate = function (excelSerialDate) {
  // "Excel serial date" is just
  // the count of days since `01/01/1900`
  // (seems that it may be even fractional).
  //
  // The count of days elapsed
  // since `01/01/1900` (Excel epoch)
  // till `01/01/1970` (Unix epoch).
  // Accounts for leap years
  // (19 of them, yielding 19 extra days).
  const daysBeforeUnixEpoch = 70 * 365 + 19;

  // An hour, approximately, because a minute
  // may be longer than 60 seconds, see "leap seconds".
  const hour = 60 * 60 * 1000;

  // "In the 1900 system, the serial number 1 represents January 1, 1900, 12:00:00 a.m.
  //  while the number 0 represents the fictitious date January 0, 1900".
  // These extra 12 hours are a hack to make things
  // a little bit less weird when rendering parsed dates.
  // E.g. if a date `Jan 1st, 2017` gets parsed as
  // `Jan 1st, 2017, 00:00 UTC` then when displayed in the US
  // it would show up as `Dec 31st, 2016, 19:00 UTC-05` (Austin, Texas).
  // That would be weird for a website user.
  // Therefore this extra 12-hour padding is added
  // to compensate for the most weird cases like this
  // (doesn't solve all of them, but most of them).
  // And if you ask what about -12/+12 border then
  // the answer is people there are already accustomed
  // to the weird time behaviour when their neighbours
  // may have completely different date than they do.
  //
  // `Math.round()` rounds all time fractions
  // smaller than a millisecond (e.g. nanoseconds)
  // but it's unlikely that an Excel serial date
  // is gonna contain even seconds.
  //
  return new Date(Math.round((excelSerialDate - daysBeforeUnixEpoch) * 24 * hour) + 12 * hour);
};

答案 9 :(得分:0)

要弥补夏令时(从3月的最后一个星期日开始,直到10月的最后一个星期日),我必须使用以下公式:

zeros(128,2e7,'single');  

快速说明:

如果日期[“ A2”]在三月的最后一个星期日和十月的最后一个星期日[第三和第四代码行]之间,那么我将减去一个小时[-TIME(1; 0; 0)]

答案 10 :(得分:0)

如果您可以创建自定义函数(用户定义函数:UDF): 创建一个 VBA 模块并复制这些代码:

Function unix_time(Optional my_year, Optional my_month, Optional my_day, Optional my_hour, Optional my_minute, Optional my_second)
    Dim now_date, now_time, ref_date, ref_time

    my_year = IIf(IsMissing(my_year) = False, my_year, year(Now))
    my_month = IIf(IsMissing(my_month) = False, my_month, month(Now))
    my_day = IIf(IsMissing(my_day) = False, my_day, day(Now))

    my_hour = IIf(IsMissing(my_hour) = False, my_hour, hour(Now))
    my_minute = IIf(IsMissing(my_minute) = False, my_minute, minute(Now))
    my_second = IIf(IsMissing(my_second) = False, my_second, second(Now))

    now_date = DateSerial(my_year, my_month, my_day)
    now_time = TimeSerial(my_hour, my_minute, my_second)

    ref_date = DateSerial(1970, 1, 1)
    ref_time = TimeSerial(0, 0, 0)'You can change this line based on your time zone. for example : Tehran -> TimeSerial(3,30,0)

    now_date = now_date + now_time

    ref_date = ref_date + ref_time

    unix_time = (now_date - ref_date) * 86400
End Function

然后输入您想要的任何单元格:=unix_time()