在Julia中,我需要以与Microsoft Excel相同的方式将数字转换为DateTime
。
在Excel中,今天的日期为2019年9月23日,表示为43731,今天下午6点为43731.75。我可以忽略Excel incorrectly assumes that 1900 is a leap year的事实,因为我的所有数据都安全地超出了这一点。毫秒精度就足够了。
下面的代码似乎有效,但是有更好的方法吗?
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
答案 0 :(得分:1)
您可以重载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)
然后,您可以使用以下值:
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
非常重要的一点是,excel将所有数字都视为float64,在Julia中,日期是一种完全不同的类型。我认为,如果您希望一定范围的数字表现得像Date,则最好构造一个反映该行为的类型。
Excel日期的一个重要特征是您可以像数字一样操作日期,但是该操作的结果未格式化为日期。这是Excel决定使用Float64表示日期的结果。
定义的类型比数字具有更多的限制,如果要将日期作为数字使用,可以先将ExcelDate
转换为数字,但是仅使用julia {{1 }}类型,可以使用更多更好的方法来处理日期。
topic琐,但是日期并不是编程问题,所有编程语言的标准都不同。