复制Excel';Julia中日期的表示
在Julia中,我需要以与Microsoft Excel相同的方式将数字转换为日期时间 在Excel中,今天2019年9月23日用43731表示,今天下午6点用43731.75表示。我可以忽略一个事实,因为我所有的数据都安全地超出了这一点。毫秒精度就足够了 下面的代码似乎有效,但有更好的方法吗复制Excel';Julia中日期的表示,julia,Julia,在Julia中,我需要以与Microsoft Excel相同的方式将数字转换为日期时间 在Excel中,今天2019年9月23日用43731表示,今天下午6点用43731.75表示。我可以忽略一个事实,因为我所有的数据都安全地超出了这一点。毫秒精度就足够了 下面的代码似乎有效,但有更好的方法吗 function exceldatetodate(exceldate::Integer) Dates.Date(1899, 12, 30) + Dates.Day(exceldate) end f
function exceldatetodate(exceldate::Integer)
Dates.Date(1899, 12, 30) + Dates.Day(exceldate)
end
function exceldatetodate(exceldate::Real)
t,d = modf(exceldate)
Dates.Date(1899, 12, 30) + Dates.Day(d) + Dates.Millisecond(floor(t * 86400000))
end
julia> exceldatetodate(43731)
2019-09-23
julia> exceldatetodate(43731.75)
2019-09-23T18:00:00
您可以重载
convert
方法,并创建保存该值的自定义类型
using Dates
struct ExcelDate{T<:Real}
val::T
end
function exceldatetodate(exceldate::Integer)
Dates.DateTime(1899, 12, 30) + Dates.Day(exceldate)
end
function exceldatetodate(exceldate::Real)
t,d = modf(exceldate)
return Dates.DateTime(1899, 12, 30) + Dates.Day(d) + Dates.Millisecond((floor(t * 86400000)))
end
function exceldatetodate(exceldate::ExcelDate)
exceldatetodate(exceldate.val)
end
function exceldatetodate(exceldate::ExcelDate)
exceldatetodate(exceldate.val)
end
function toexceldate(date::Date)
datetime = Dates.value(DateTime(date) - Dates.DateTime(1899, 12, 30))
datetime = round(datetime/86400000,digits = 3)
return ExcelDate(datetime)
end
function toexceldate(date::DateTime)
datetime = Dates.value(date - Dates.DateTime(1899, 12, 30))
datetime = round(datetime/86400000,digits = 3)
return ExcelDate(datetime)
end
Base.convert(d::Type{Dates.DateTime},n::ExcelDate) = exceldatetodate(n)
Base.convert(d::Type{Dates.Date},n::ExcelDate) = convert(Date,exceldatetodate(n))
Base.convert(d::Type{T},n::ExcelDate) where T<: Real = convert(d,n.val)
Base.convert(d::Type{ExcelDate},n::Dates.DateTime) = toexceldate(n)
Base.convert(d::Type{ExcelDate},n::Dates.Date) = toexceldate(n)
非常重要的一点是,excel将所有数字视为浮点64,而在Julia中,日期是完全不同的类型。在我看来,如果你想让某个特定范围的数字表现得像一个日期,那么最好构造一个反映该行为的类型。
excel日期的一个重要特征是,您可以像数字一样对日期进行操作,但该操作的结果不会格式化为日期。这是Excel决定使用浮点64表示日期的结果。
定义的类型比数字有更多的限制,如果您想将日期作为数字使用,您可以先将ExcelDate
转换为数字,但只使用juliaDate
类型更有意义,它有更好、更多的方法来处理日期。离题,但日期是编程中一个尚未解决的问题,所有编程语言的标准都不同。您是否检查了
XLSX.jl
如何处理它()?我不知道有没有更好的办法。但是如果还没有,这将是添加到XLSX.jl
的好东西。我会等待一个更好的答案,但如果没有,你应该在那里打开一个问题。这是一个有趣的建议,重载convert
感觉非常“Julian”,这很好。不过,我认为重载+
是没有意义的(对于类型Date
,没有仔细定义)。重载-
可能不会返回另一个ExcelDate
,就像减去两个Date
s会返回一个期间而不是日期。是的,在excel中,“行为”是将两个日期的操作格式化为一个数字。我会改正的that@PhilipSwannell请注意,+(::日期,::日期)
未定义,但+(::日期,::时间)
未定义。就个人而言,我并不真正喜欢第二种方法——我认为构造函数DateTime(::Date,::Time)
(也定义了它)是足够的和有意义的。可能值得强调的是,这个答案适用于任何使用Float64
表示DateTime
的语言,只要您适当调整纪元日期。例如,Excel使用1899-12-31,Matlab使用0-0-0(但在其他方面都是相同的)。
original_numbers = 40000.01:41000.01 #test numbers
excel_dates = convert.(ExcelDate,original_numbers)
dates = convert.(Date,excel_dates) #just days
datetimes = convert.(DateTime,excel_dates) #days and miliseconds
orig2 = convert.(ExcelDate,datetimes) #this preserves the original number
orig3 = convert.(ExcelDate,dates) #this does not preserve the original number