<waj>
Hey, I've been thinking more about your Date/Time implementation
<waj>
did you see how DateTime works in mono?
<waj>
it's actually quite similar but they encode date and time in the same int64 field to minimize the memory usage
<waj>
but having a DateTime that fits in a register seems like a big win ;)
<CraigBuchek>
What's the range on that?
<CraigBuchek>
I'm sure it gets past the year 2038 at least. ;)
<waj>
1-1-0001 12:00:00 AM to 31-12-9999 23:59:00
<waj>
seems good enough :P
<CraigBuchek>
That's an articificial limit, not the true range of a 64-bit integer counting seconds.
<waj>
I had this feeling that in some languages the date/time implementations were not well designed and I'd like to avoid the same mistake in crystal
<CraigBuchek>
I'm not sure there's a good reason to limit it to that range, if the storage allows more.
<CraigBuchek>
So if it's a 64-bit integer of seconds, do we not allow fractional second resolution of time?
<waj>
mm… seems there are milliseconds as well
<CraigBuchek>
Dates and times are one place where the complexity is mostly necessary, not incidental. That is, dates and times in the real world are complex.
<waj>
I know.. believe me in the really hard way :)
<waj>
but it's also something that's used all the time
<waj>
my point is… I'd like that the default implementation of date/time in crystal to be good enough for most applications
<waj>
It might not fit well if you are developing a scientific app
<CraigBuchek>
So I'm looking at the Mono DateTime class.
<CraigBuchek>
It doesn't say how long a tick is. Perhaps milliseconds from 0001-01-01 to 9999-12-31 all fit into 62 bits?
<waj>
I think mono's it's pretty similar to what you defined, but the composition of date and time is done in a tricky way to make it fit in 64 bits
<CraigBuchek>
Doesn't seem all that tricky, except the top 2 bits for the kind.
<CraigBuchek>
Whoa. A tick in Mono is actually 0.1 microseconds.
<CraigBuchek>
So If you're OK with microsecond accuracy (I am, not sure who wouldn't be OK with that) and no (or not many) dates before the year 1, then 64-bit microseconds looks like a decent internal representation.
<waj>
but do you agree with having a single class that combines Date and Time representations?
<CraigBuchek>
Actually, we could go back more than 40 times 1/1/1, so we could probably get to before 10000 BC, which would cover all history. Just not geological or astronomical dates.
<CraigBuchek>
I'd probably still want to have a Date class that makes it easier to talk about dates. And abstract calendars.
<CraigBuchek>
But it would pretty much always be used as a part of a Time.
<CraigBuchek>
So, Time.now.date.to_s => "2014-07-11"
<CraigBuchek>
Probably not even Date.today or Date.now, to keep it clear that it's not a fundamental class.
<waj>
sounds good
<CraigBuchek>
I'll go update the PR with our decisions.
<waj>
actually if Date is just a struct that wraps a Time inside there wouldn't be any overhead once the methods are inlined and there wouldn't be code duplication
<waj>
mm… just thinking that if Date and Time structs uses the same internal ticks representation, how could we still have separate structures but combine them in a DateTime were the internal structure is still just a single value
<waj>
I wish we could "include" a struct now :P
<CraigBuchek>
I was thinking that a Date wouldn't be a Time, it would be destructured into Y/M/D fields.
<waj>
but you would loose the benefits to make date calculations, right?
<CraigBuchek>
Or keep the JDN thing.
<CraigBuchek>
So def Time#date; jdn = self.ticks / ticks_per_day; return Date.new(jdn); end
<CraigBuchek>
Forgot to offset by the epoch.
e_dub has joined #crystal-lang
<CraigBuchek>
So I suppose then my date class would survive intact mostly.
<CraigBuchek>
But my ideas on Time would be quite different.
<asterite>
Craig, check that you have this: def initialize(@year, @month, @day, @calendar = Date::Calendar::DEFAULT)
<asterite>
So a Date would have @year, @month, @day and @calendar as instance variables, I'm not sure you want that
<asterite>
Also, the specs don't pass because Date::Intervals should include Comparable(self) (Comparable is generic)
<CraigBuchek>
@asterite. Sure. I was just optimizing time over space. I.e. keeping track of both Y/M/D and JDN. But I can optimize for soace instead.
<asterite>
But I didn't see you use those instance variables anywhere in the code except in the constructor
<CraigBuchek>
LOL. You're right.
<CraigBuchek>
Post-mature optimization.
<waj>
we're not sure about what's the best implementation of date/time for crystal. We just didn't dig into this topic yet. So actually any implementation you came up with would be infinite times better than ours ;-)
<CraigBuchek>
It actually took a fair amount of research to get calendar math right.
<CraigBuchek>
And I've been interested in calendars for a long time.
<waj>
but I know what I DONT want to happen in crystal, which is that sensation that the programmer never knows which class to use
<waj>
Date? Time? DateTime? need activesupport?
<CraigBuchek>
I'm with you there.
<CraigBuchek>
Date and Time. No DateTime!
<waj>
yup… and I'm still not 100% sure about Date :)
<waj>
if it's just to have a good string representation we could have a different method for that
<CraigBuchek>
So I'm guessing you'd rather have Time#year, Time#month, and Time#day?
<waj>
maybe… again, I'm not sure, so feel free to play with it. I'm open to suggestions.
<CraigBuchek>
Even if that's the case, I'd still want to write a Date class to abstract away that math.
kostya has joined #crystal-lang
<waj>
in the Date.ymd method, instead of returning an Array, you could use a tuple that would be more efficient
<waj>
and I'm pretty sure LLVM could inline the "ymd" method inside "year", "month" and "date" and remove the unsued parts ;)