Coder Social home page Coder Social logo

whoopinc / frozen-moment Goto Github PK

View Code? Open in Web Editor NEW
64.0 25.0 7.0 37 KB

Immutability for Moment.js. Freeze moments so that mutation methods return copies instead of altering the original timestamp. Parse, validate, manipulate, and display dates without needing to clone().

License: MIT License

JavaScript 93.80% HTML 6.20%

frozen-moment's Introduction

Frozen Moment

MIT License NPM version Bower version

Immutability for Moment.js

If you build large applications that use Moment.js, you've probably been surprised at some point by the mutability of moments. Things like moment.startOf("day") change the date of your original moment (instead of returning a new moment). Unfortunately, this leads to subtle bugs if you pass moments around and then start to do math on them while expecting other places to still have the old value.

Or maybe you're smarter than me, and yet you still wish that Moment had an immutable API. It gets annoying to keep typing moment.clone() all the time.

Either way, this plugin is for you.

API Reference: What does it do?

Frozen Moment is a plugin for Moment.js. With Frozen Moment, all of your normal moments will still work the same way they always have -- so you won't need to adopt immutability throughout your entire codebase all at once. Frozen Moment simply adds a new method to every moment instance:

Methods on Moment and Frozen Moment instances

moment().freeze()

Returns a "frozen" copy of the original moment. "Frozen" moments will behave exactly like normal moments, but all of the methods that would normally change the value of a frozen moment will instead return a new frozen moment.

Basically, frozen moments will automatically call moment.clone() before you try to call any of Moment's setters or manipulation functions. You'll also get a new instance every time you change a frozen moment's locale.

For performance and compatibility reasons, frozen moments are not made immutable with Object.freeze. If you want to shoot yourself in the foot by manually meddling with your frozen moment's internal data, go right ahead. That said, frozen moments will be immutable as long as you only use Moment's documented API methods.

Frozen moments attempt to play nice with other Moment.js plugins, assuming that the Frozen Moment plugin is loaded last and/or moment.frozen.autowrap() is called after the last Moment plugin has been initialized. That said, we cannot guarantee that every plugin will behave correctly. If you have problems using Frozen Moment with any other Moment plugin, please open an issue and we'll work with the other plugin maintainer to resolve the incompatibility.

Frozen moments do not have the freeze() method -- only regular moments do.

frozenMoment.thaw()

Returns a normal (un-frozen) copy of a frozen moment.

Regular old moments do not have a thaw() method -- only frozen moments do.

moment().isFrozen() / frozenMoment.isFrozen()

Returns true if called on a frozen moment, and false if called on a standard moment.

Note that moment.isMoment() will return true for frozen moments and normal moments alike.

Global configuration

moment.frozen.fn

This is the prototype for all frozen moment instances. It inherits from moment.fn, which is the prototype used for all Moment instances created by the core library.

moment.frozen.unwrap(methodNames...)

Removes all existing wrappers for the named moment prototype function(s), and whitelists those method names so that wrappers will not be re-created by subsequent calls to moment.frozen.autowrap(). This is a mechanism for performance-optimizing plugin authors to whitelist methods that do not mutate the moment instance, so that Frozen Moment will not automatically clone a new instance every time those methods are invoked.

moment.frozen.autowrap()

Re-generates wrappers for all functions on the Moment prototype that have not been explicitly whitelisted. Some plugin authors may want to call this after adding mutation methods to the Moment prototype, so that their users will not need to load their plugin before Frozen Moment. Alternatively, application authors may wish to call this after loading their Moment plugins, to ensure that all plugin methods are properly wrapped for immutable behavior.

TODO

Frozen Moment should generally work, and it has been used by a few folks in production applications. The current v0.4 release is a reasonably stable implementation of the core ideas. This code has inspired and informed Moment's implementation of immutability, which is coming in version 3.0.

Our maintainer is manually running our unit tests in a variety of browsers (IE 8 and the current releases of Chrome, Firefox, and Safari) to ensure broad runtime compatibility, in addition to our CI build with Node.

Pull requests are enthusiastically welcomed for improvements on our current to-do list. If you have other ideas for new features, it's often a good idea to get our feedback on your plans before you bother writing the code. In any event, please remember to submit unit tests to verify your changes.

Historical Note

The original version of Frozen Moment was a full-fledged fork of Moment.js. It is no longer maintained.

frozen-moment's People

Contributors

butterflyhug avatar eoftedal avatar jscinoz avatar pitaj avatar waisbrot avatar wyantb avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

frozen-moment's Issues

Expand test coverage

We should have mutability tests for all methods on moments and frozen moments.

We should also probably switch to a proper unit testing framework before we get too deep into writing more tests.

Firefox fails to run (errors) when using frozen-moment with webpack

Issue only happens on firefox. Chrome runs fine. Only happens using frozen-moment. Moment itself webpacks fine with same settings.

capture

Line with syntax error reads:

//! moment.js locale configuration
//! locale : Arabic Saudi Arabia (ar-sa)
//! author : Suhail Alkowaileet : https://github.com/xsoh
!function(e,t){t(n(6))}(this,function(e){"use strict";var t={1:"?",2:"?",3:"?",4:"?",5:"?",6:"?",7:"?",8:"?",9:"?",0:"?"},n={"?":"1","?":"2","?":"3","?":"4","?":"5","?":"6","?":"7","?":"8","?":"9","?":"0"},r=e.defineLocale("ar-sa",{months:"?????_??????_????_?????_????_?????_?????_?????_??????_??????_??????_??????".split("_"),monthsShort:"?????_??????_????_?????_????_?????_?????_?????_??????_??????_??????_??????".split("_"),weekdays:"?????_???????_????????_????????_??????_??????_?????".split("_"),weekdaysShort:"???_?????_??????_??????_????_????_???".split("_"),weekdaysMin:"?_?_?_?_?_?_?".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd D MMMM YYYY HH:mm"},meridiemParse:/?|?/,isPM:function(e){return"?"===e},meridiem:function(e,t,n){return 12>e?"?":"?"},calendar:{sameDay:"[????? ??? ??????] LT",nextDay:"[??? ??? ??????] LT",nextWeek:"dddd [??? ??????] LT",lastDay:"[??? ??? ??????] LT",lastWeek:"dddd [??? ??????] LT",sameElse:"L"},relativeTime:{future:"?? %s",past:"??? %s",s:"????",m:"?????",mm:"%d ?????",h:"????",hh:"%d ?????",d:"???",dd:"%d ????",M:"???",MM:"%d ????",y:"???",yy:"%d ?????"},preparse:function(e){return e.replace(/[??????????]/g,function(e){return n[e]}).replace(/?/g,",")},postformat:function(e){return e.replace(/\d/g,function(e){return t[e]}).replace(/,/g,"?")},week:{dow:6,doy:12}});return r})},function(e,t,n){

Work with startOf?

Doesn't seem to work with startOf.

> var moment = require('frozen-moment')
> var now = moment()
> var frozen = moment.frozen()
> now.format()
'2015-11-05T15:25:24-05:00'
> frozen.format()
'2015-11-05T15:25:48-05:00'
> now.startOf('year').format()
'2015-01-01T00:00:00-05:00'
> frozen.startOf('year').format()
'2015-11-05T15:25:48-05:00'

CI build to run tests on pull requests

Should run tests in Node and in at least one browser. (Ideally the CI build would run in all supported browsers.)

The CI build should also load Frozen Moment with all three supported module systems.

Publish selected internals for plugin integration

We should publish the prototype for frozen moment instances, similar to moment.fn, in case anyone has a reason to hook specifically into the frozen moment prototype. This should probably be moment.frozen.fn after implementing #4.

Similarly, we should expose the immutableMethods and mutableWithArguments arrays somehow, so that other plugins can whitelist their own methods as appropriate.

Play nice with moment-timezone

Currently, moment-timezone doesn't work properly on frozen moments because its updateOffset implementation assumes that it is using the mutable API.

In moment/moment-rfcs#2, I proposed automatically thawing the moment before updateOffset and then re-freezing afterward (or copying the changed properties when updateOffset is called during the constructor). I'm not sure how a plugin would get access to do that, but I'll leave this issue open in case other folks have better ideas.

Run unit tests in the browser

Not just in Node. Need to be able to run tests with both a traditional script tag / global variable initialization, and also with AMD module loading.

Typescript support?

I have an Angular2 typescript application (with Angular CLI as build tool).

Can I use frozen-moment? How would I import it? Are there typings available?

Made a POC

https://gist.github.com/wyantb/996c53b00008194301c9

Implementing the idea sounded interesting, so I hacked up a prototype real quick.

Just patching moment.fn seemed the quickest route to success here. Note that, obviously, I didn't expend a lot of effort trying to get the list of patched methods right. Still, though I'd throw it out there.

Also, I didn't implement the bit where you said that .thaw isn't available on non-frozen moments, and .freeze isn't available on frozen moments. If I was using this patch, and developing some common API, I'd probably still tend towards calling .freeze on every incoming moment, and there's little sense in me calling isFrozen beforehand.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.