dlevs / duration-fns

Functions for working with durations.
MIT License
58 stars 6 forks source link

Add date reference for conversions #5

Open ryanking1809 opened 4 years ago

ryanking1809 commented 4 years ago

Hi there, great job with this library! Just one problem I'm having involves converting to single units. Would it be possible to add a date reference for conversions like you have done with normalisation?

For example, I would like the following to return a number of full days:

durationFns.toDays({ years: 1, months: 1 }) 
// 395.4166666666667

durationFns.toDays({ years: 1, months: 1 }, '2018-01-01') 
// 396
dlevs commented 4 years ago

Hey, I actually tried to build the API exactly like this originally! I got a bit of a headache while thinking about the more fuzzy units, like toMonths():

duration.toDays({ years: 1, months: 1 }, '2018-01-01')
// 396 👌 Simple and easy to understand.

duration.toMonths({ days: 40 }, '2018-01-01')
// ??? 🤔 Some number between 1 and 2... Need to calculate length of February to get remainder?

I didn't implement these as I didn't want to deal with the complexity for a feature that I wasn't sure anyone would need. This does looks useful to have, though! I could take another stab at this when I get some time, or feel free to raise a PR.

I think the key may lie in the between() function:

duration.between(
    '2018-01-01',
    duration.apply('2018-01-01', { years: 1, months: 1 }),

    // We could add an optional array of units to use to express the output. Defaults to all units.
    ['days']
)

Something like the above would be useful in general, and could then be used internally by toDays().

ryanking1809 commented 4 years ago

I'll probably have some working algorithms by tomorrow. Might need help integrating it into date-fns as I'm not super across typescript and your testing system. Will keep you updated anyways.

ryanking1809 commented 4 years ago

Ok, I have some working algorithms you can find here https://github.com/ryanking1809/datemath - you would be most interested in durationBetween, wholeUnitsBetween and durationHelpers - I've tried commenting everything to make it easier to understand.

I've also added the options for users to create unit multiples, for things like fortnights and quarters if you feel as though that's in scope of the library.

dlevs commented 4 years ago

Nice! Thanks for sharing those. I like the approaches here and can see how a lot of these ideas can fit into this library.

I'd happily have another go at this, pretty much lifting your code and sticking it into the library where it makes sense.

I don't have much free time at the moment, though. If you want to have a go at integrating the code, by all means raise a PR. Otherwise, I'll probably have a stab at it at some point in the next month.

dlevs commented 4 years ago

I've also added the options for users to create unit multiples, for things like fortnights and quarters if you feel as though that's in scope of the library.

I'm less keen on this idea, though I have considered it in the past. I like the simple one-to-one mapping of the duration units to the ISO spec. It makes functions like toString simple. I see the value in adding custom units, but am not in any rush to do so as I'm sure such a feature would come back to bite me in the future. :D

ryanking1809 commented 4 years ago

I've also added the options for users to create unit multiples, for things like fortnights and quarters if you feel as though that's in scope of the library.

I'm less keen on this idea, though I have considered it in the past. I like the simple one-to-one mapping of the duration units to the ISO spec. It makes functions like toString simple. I see the value in adding custom units, but am not in any rush to do so as I'm sure such a feature would come back to bite me in the future. :D

This is a requirement for me, unfortunately. The way I'm using it the library sticks to the main core units but there's the option to do maths with multiples of units. But if it complicates things for you I might continue going down my own route (you're still welcome to use my code above either way)

dlevs commented 4 years ago

I'm open to the idea. Can definitely see some value in it. I'm a bit swamped at the moment, so it probably makes more sense to roll your own, or fork this if it's any good for you.

I'll get around to this at some point, but it will probably not be soon enough for you! I'm open to PRs, but either way interested to see what you come up with. 😀