Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a brief comparison with Moment.js? #275

Closed
rauschma opened this issue Dec 5, 2016 · 32 comments
Closed

Add a brief comparison with Moment.js? #275

rauschma opened this issue Dec 5, 2016 · 32 comments

Comments

@rauschma
Copy link

rauschma commented Dec 5, 2016

Given how much of a de-facto standard Moment.js has become, it may make sense to briefly explain how date-fns differs.

@s-a
Copy link

s-a commented Dec 5, 2016

This was my first thought when I found date-fns. https://date-fns.org/ tells some details. I personly often call moment.js to use http://momentjs.com/docs/#/displaying/ the display methods. However pretty interesting solution here 👍

@kossnocorp
Copy link
Member

kossnocorp commented Dec 5, 2016

@rauschma Moment.js has a few problems that motivated me to start the project:

Also date-fns works with the native date type: no extra dependencies for propTypes in React, Sinon.js works out of the box (and other mocking tools), and so on.

date-fns cons is:

Functionality-wise date-fns equals to Moment.js.

@c-dante
Copy link

c-dante commented Dec 5, 2016

Some more to add from my reply to a recent r/javascript post

  • Similar bundle size (64 KB min v1,12,1 vs moment's 59.9 KB minified v2.17.1)
    • Although if you only include what you use, you'll get significantly smaller
  • Does not force wrapping dates
    • In order to do anything in moment, you have to wrap everything in a moment object
    • While moment doesn't extend the Date object, it does expect certain functionality through its code
    • Better for tree shaking if you're using a modern bundler
  • All of date-fns's code are pure functions (and simple to grok)
    • Easy to read code for debugging
    • Immutable is nice
    • No global settings
    • No plugins
    • No chaining (composition is better anyway though)
  • Timezone coming soon
  • Locale and internationalization as configs to display functions
  • No duration support (could be coming if an api is suggested)

Source: my reddit comment

Edit: Updated to reflect bundle sizes. Minified bundles are a bad comparison though since ES6 imports and tree shaking, especially since this is a pure function approach.

@fregante
Copy link

fregante commented Dec 6, 2016

I see 64KB here: https://github.com/date-fns/date-fns/blob/master/dist/date_fns.min.js

Which is still not that small and if you keep adding features the difference might end up not being much. Moment.js started out as as micro library and look where it ended up 😄

@thisconnect
Copy link

Good look trying to tree shake Moment.js

@s-a
Copy link

s-a commented Dec 6, 2016

@bfred-it in fact no one need s the full API. It is interesting to bundle functions I need.

@kossnocorp
Copy link
Member

@bfred-it the dist version of date-fns (https://github.com/date-fns/date-fns/blob/master/dist/date_fns.min.js) coming as a single file while with webpack, Browserify (and other module bundler tools) you'll get the only code you use. It's possible to optimize the dist by splitting the functions into "packs", but our focus is npm version. Contributions are welcome tho!

@fregante
Copy link

fregante commented Dec 6, 2016

Perfect! I didn't even realize. 😅 I was only responding to c-dante's comment

@luislobo
Copy link

luislobo commented Dec 6, 2016

It would be good to add this to the README.md

@kossnocorp
Copy link
Member

Will convert the comments into FAQ. Please tell me if you have more questions.

@kossnocorp
Copy link
Member

@benjamingr
Copy link

A way to do chaining would be absolutely great. Personally I wouldn't mind even altering the built in Date object with immutable helpers. The part I want is mostly just infix.

@c-dante
Copy link

c-dante commented Dec 9, 2016

@benjamingr chaining is not good -- mutation of objects defeats the purpose of this library being small, pure functions. Also, manipulating the built-in prototypes is also a bad practice. At that point, just use moment which embrasess that approach.

If you want chaining in the sense of not having to do nested functions, check out the FP issue #253 which would let the library support pure function composition nicely.

That all being said, a small function (chain) that would basically do what Lodash's wrapper does would support this in a possibly not awful way.

@benjamingr
Copy link

@c-dante I didn't suggest mutation at all - you can chain functions without mutating the objects.

Two example that come to mind are how functional languages like Haskell deal with this through infix notation or how languages like C# deal with it with the DateTime class instances being mutable.

To be clear. Something like:

imaginaryApi(date).addDays(3).addMinutes(30)

Would return a new Date instance. If we want to avoid intermediate dates we can do:

imaginaryApi(date).addDays(3).addMinutes(30).get()

@c-dante
Copy link

c-dante commented Dec 9, 2016

Yeah, I don't know if you saw what I added, but I'm not opposed to either the FP changes happening, and implementing the chain as just a "flow wrapper", or creating a light chain operator such as you pointed out.

All this being said -- make a different issue with the request? This doesn't pertain to this issue.
I'm not a fan of mutating the Date prototype, as that is a bad practice.

@benjamingr
Copy link

@c-dante you could just return a Proxy for a date and that could give you chaining without .value() needed.

@blyndcide
Copy link

The bind operator :: would be great for chaining in a functional library like date-fns. Maybe look into it after ecma stage 1 approval.

@milankinen
Copy link

@benjamingr I've also thought a lot about chaining but IMHO OO is not the right approach for this library because we're talking about date-fns. I'm also worried about tree shaking issues with OO implementation.

How about currying and re-ordering of function arguments to support partial application (like Ramda does)? That would enable quite elegant composition of date functions and also supports chaining.

// fromMillis :: millis -> date
// format :: format -> date -> formatted-string
// add :: unit -> value -> date -> date
// sub :: unit -> value -> date -> date
// set :: unit -> value -> date -> date
// startOf :: unit -> date -> date

// functions can be used like any other function
fromMillis(0) // => 1.1.1970
startOf("day", new Date())  // today at 00:00

// see http://ramdajs.com/docs/#pipe
const doPipe = (x, ...fns) => R.pipe(...fns)(x)

// supports inline "chaining"
doPipe(fromMillis(0),
  set("year", 2016),
  add("days", 1),
  add("minutes", 50),
  sub("seconds", 10),
  format("YYYY-MM-DDTHH:mm:ss"))
// => "2016-01-02T00:49:50"

// and point-free composition!
const addDays = add("days")
const startOfHour = startOf("hour")

const tomorrowAt15 = R.pipe(
  addDays(1),
  set("hour", 15),
  startOfHour)

// reusability!
tomorrowAt15(new Date())
const apiObjects = ...
const apiObjsWithModifiedDate =
  R.map(R.evolve({start_time: R.pipe(parse, tomorrowAt15)}), apiObjects)

However, I see some at least the following caveat in this approach:

  • What is the correct place for locale?

@kossnocorp
Copy link
Member

Hey, there! We're looking for testimonials for the new date-fns.org home page. If you want to share your thoughts with the world, see: date-fns/date-fns.org#93. 😇

@pke
Copy link

pke commented Mar 11, 2017

Similar bundle size (64 KB min v1,12,1 vs moment's 59.9 KB minified v2.17.1)

I am seeing momentjs at 141kb when used with webpack. That is because their package.json main file points to the non-minified version. Momentjs together with opening_hours are both each bigger than my main app code. That's insane.
It all comes down to i18n. Lib authors always forget, that no-one actually needs all languages and that languages should be optional in the first place. At least in the npm packages. In the CDN distros they can build one with all languages included.

I'll switch to date-fns. Thanks for the library!

And I am surprised to see momentjs started as 3.7kb lib! WOW, this thing has exploded.

@helmbold
Copy link

A comparison with Luxon would be helpful, too.

Why not add the "need help" status to this issue, since the comparison page still doesn't exist since this issue was created in 2016?

@Jogai
Copy link

Jogai commented Apr 24, 2018

And maybe add a comparison like:

@RehanSaeed
Copy link

A comparison with dayjs would also be helpful (a 2kb bundle size and moment drop-in replacement). Although date-fns is 30kb, it's more like lodash in that it's just a collection of functions so you pay for what you use. However, what else would I be missing if I picked dayjs?

@stevemao
Copy link

For those who'd like to transition from momentjs to date-fns, please check out https://github.com/you-dont-need/You-Dont-Need-Momentjs

@LunaPg
Copy link

LunaPg commented Oct 5, 2018

How did you extract your metring between your repo and Moment ?
Do you covert the full range of moment methods ?

@anishbangalore
Copy link

@rauschma Moment.js has a few problems that motivated me to start the project:

Also date-fns works with the native date type: no extra dependencies for propTypes in React, Sinon.js works out of the box (and other mocking tools), and so on.

date-fns cons is:

Functionality-wise date-fns equals to Moment.js.

Also moment stops laravel-mix when you compile as production "npm run prod", if you are using dynamic import of components. 👎

@leshakoss
Copy link
Contributor

Closing due to lack of activity (and the fact that moment.js is not actively maintained anymore)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests