quinnj / Dates.jl

[DEPRECATED] Date/DateTime Implementation for the Julia Language; Successor to Datetime.jl
Other
8 stars 9 forks source link

use start + k*step formulation for more ranges #5

Closed StefanKarpinski closed 10 years ago

StefanKarpinski commented 10 years ago
julia> [Date(2014,1,31):Month(1):Date(2015)]
12-element Array{Date,1}:
 2014-01-31
 2014-02-28
 2014-03-28
 2014-04-28
 2014-05-28
 2014-06-28
 2014-07-28
 2014-08-28
 2014-09-28
 2014-10-28
 2014-11-28
 2014-12-28

I would expect this to give me the last day of each month, which the other technique gives.

quinnj commented 10 years ago

In general, I think this is the right thing to do, but note you still have the behavior like:

In  [45]: [Date(2014,4,30):Month(1):Date(2015,4)]

Out [45]: 12-element Array{Date,1}:
 2014-04-30
 2014-05-30
 2014-06-30
 2014-07-30
 2014-08-30
 2014-09-30
 2014-10-30
 2014-11-30
 2014-12-30
 2015-01-30
 2015-02-28
 2015-03-30

So even though you started from April 30th (last day of the month), you don't get the last days of all months going forward. But then again, this is also matches exactly how we do Date-Month arithmetic anyway, so overall at least we're being consistent with this.

StefanKarpinski commented 10 years ago

I'd still like to explore the idea of date-like objects representing intervals of time so that you would do this sort of thing by asking for the last day of each month – or the 30th day of each month, if that's what you want, which would then error out if any of the months you asked that of didn't have a 30th day.

quinnj commented 10 years ago

You should dive into the adjusters.jl file a little more; it's a higher-order programming approach to just this kind of thing. To get the last day of every month in the "adjusting" way would be as simple as:

In  [3]: recur(x->x==lastdayofmonth(x),Date(2014):Date(2015))

Out [3]: 12-element Array{Date,1}:
 2014-01-31
 2014-02-28
 2014-03-31
 2014-04-30
 2014-05-31
 2014-06-30
 2014-07-31
 2014-08-31
 2014-09-30
 2014-10-31
 2014-11-30
 2014-12-31
StefanKarpinski commented 10 years ago

Shouldn't we encourage this by not supporting the likely-to-be-wrong way of doing it?

quinnj commented 10 years ago

The likely-to-be-wrong way being using ranges?

StefanKarpinski commented 10 years ago

Well, ranges with ill-defined steps with respect the the endpoints, as in this case.

tonyhffong commented 10 years ago

Should we formalize a relative-Date type with an expression constructor? For example, RelDate( :( 1b+2w+m+y ) ) When applied on a date (with a holiday calendar), we get next biz day + 2 weeks, 1 month, and 1 year.

My motivation is that there are many more relative date expressions than day/ week/ month / year. For example you could use 'e' for end of month, 'a' for start of month, 'd' for day (ignore holiday), 'b' for same day or next business day (if landed on a holiday), 'p' for same day or previous business day (if landed on a holiday). 'w1' to 'w7' for the next weekday, and so on...

To be able to chain them would be very powerful. So you can express things like Date(y, 5 ) + RelDate( :( e-w1) ) for Memorial Day, etc.

StefanKarpinski commented 10 years ago

I haven't processed this idea fully, but using expressions like this strikes me as a bad idea.

quinnj commented 10 years ago

@tonyhffong, please check out the adjusters.jl code, you can accomplish everything you discussed plus much more (and a much better API). I really need to settle on some solid documentation for that, because I've had several comments of wanting to develop this and that and it can all be done through the adjuster interface. I'll bump the docs up on my list and maybe do a demo/blog post to share on the users forum.

tonyhffong commented 10 years ago

@StefanKarpinski , I'm agnostic to using Expr vs String. I'm fine with just RelDate( "2w+1b" ) (if your "expression" means Expr). At the end of the day, each "letter" simply corresponds to a distinct Period type. So this proposal is really about a very compressed way of doing date math. @quinnj, I'll take a look at adjusters.jl.

StefanKarpinski commented 10 years ago

Strings are only better if this is its own little mini language. Still not entirely sold on it though.

tonyhffong commented 10 years ago

Happy to discuss pros and cons. For completeness, I can see the use case for date math requiring a union of holiday calendars so you are dealing with fairly long expressions like [Date(2014,4,30):HolidayMod( [ cal1, cal2 ], Month(1)+EndOfMonth()+SameOrPreviousBDay() ):Date(2015,4)] So a little DSL that shortens to something like: Date(2014,4): RelDate( "1m+e+0p", [cal1, cal2] ): Date(2015,4) may pay in terms of readability. The idea is similar to strftime, regex, printf, etc.