Can I assign what "now" is using Moment.js? - javascript

I'm using moment.js and I want to write a test that says, "If you do not pass in a date, it returns now()". The problem is, every time the test runs, now() will be a different result. In other libraries, you can set what now() will return for testing purposes. Does moment.js provide a way to do that? I've been googling and not finding any results that say whether or not you can do this.

Timekeeper (https://www.npmjs.com/package/timekeeper) fills this exact need.
It overrides the date constructors (which moment uses under the hood) so it will work for moment as well.
You can do the following:
const timekeeper = require('timekeeper');
const freezeDate = new Date();
timekeeper.freeze(freezeDate);
// in your test
expect(result).to.equal(freezeDate);

You can change the time source (which basically overrides the implementation with a new Date.now) before each test by doing the following from the official momentjs docs. This returns the number of milliseconds since unix epoch time (1/1/1970).
moment.now = function () {
return +new Date();
}

Related

Getting wrong date in Node.js

I tried all the solutions i found here but none work.
Im just trying:
var a = new Date();
console.log(a);
//2020-01-12T05:05:17.320Z
//Time in my timezone: 2020-01-12T02:05:17.320Z
I'm from Brazil, o the timezone is -3:00
I already installed moment.js and tryed:
var moment = require('moment-timezone');
moment().tz("America/Sao_Paulo").format();
var a = new Date();
console.log(a);
but i keep getting whithout my timezone. I also tryed setting the TZ without the moment.js and didn't work.
I cant use some solution that change the way to call the "new Date()" because I have to parse a string to an object that contains Date and I use Prompts module, that get a date from console, that already return a date. I don't know what to do more.
Thanks for any help.
*I'm running on Windows, and the time is right, the configuration is pointing to the right timezone
edit1: more info
The best way that I found was add 'getTimezoneOffset' (minutes) using moment.js
//Will returns the current "wrong" time in formart '2020-09-29T19:47:46.411Z'
//Expect: 2020-09-29T16:47:46.411Z
console.log(new Date())
So if you want see the full date in format ('DD-MM-YYYY HH:mm') of any object
var moment = require('moment')
// specificDay is a Date (type: Object) like '2020-09-22T00:00:00.000Z'
// previously retrieved from the database without information about the time('HH:mm')
// Only with 'YYYY-MM-DD'
moment(specificDay, "YYYY-MM-DD").add(new Date().getTimezoneOffset(),'minute').format('DD-MM-YYYY HH:mm')
You're very close. Moment is a Javascript library that makes formatting time very easy. You are creating your moment object, but you're not outputting it.
I made a very slight change (2nd line) and it works as expected:
var moment = require('moment-timezone');
console.log(moment().tz("America/Sao_Paulo").format());
If you want it formatted nicely, see this page: https://momentjs.com/.
For example:
console.log(moment().tz("America/Sao_Paulo").format('lll'));
// output: Jan 12, 2020 2:45 AM
How does it work?
moment() creates a time object (just like new Date(), but it's moment's special time object). .tz() is calling the timezone function and we give it your time zone as a string "America/Sao_Paulo". .format() then outputs it in a nice custom string. console.log() outputs the whole string to the screen.
Node takes UTC timestamp
https://www.google.com/search?client=firefox-b-d&q=current+utc+time+online
So you can convert to a locale string and after that create a new date. This is a example for mexico city
let mx = (new Date()).toLocaleString('se-SE',{ timeZone: 'America/Mexico_City'}) + "Z";
return new Date(mx);

Javascript: Set a new Date to tomorrow 8am

I want to make a Javascript date object eg. var now = new Date().getTime() that is set for "tomorrow at 8am", how would I accomplish that?
You could do the following:
var now = new Date();
now.setDate(now.getDate() + 1)
now.setHours(8);
now.setMinutes(0);
now.setMilliseconds(0);
also check this
You could also: var now = Date("2016-03-23T8:00:00");
And var now = new Date(2016,03,23,8,0,0,0 );
If you have a lot of date arithmetics, I can only strongly recommend the use of moment.js.
Using this library, your code would be as short as moment().add(1, 'days').hours(8).startOf('hour').
moment.js works with 'moment' objects that wrap over JS dates to provide additional methods. The moment() invocation returns a moment of the current datetime, thus being the moment.js equivalent to new Date().
From there we can use the moment.js methods, as add(quantity, unit) that adds a duration to the previous date. All these manipulation methods return a modified moment, which mean we can chain them.
The hours() methods is both a getter and a setter depending on its arguments ; here we provide it with a number, which mean we set the moment's hour part to 8. A call to .hours() would have instead returned the current hour part.
startOf(unit) returns a moment at the start of the unit, meaning it will set all lesser units to 0 : moment().startOf('day') would return today's 00:00 am.

Moment.js keeps returning UTC instead of Local Date

I'm having what I hope/assume is a simple and silly issue getting Moment.js to return the local date.
I'm passing in this date/time string: 2015-02-19T06:32:00.001-05:00
Using this code:
var departureDateTime = "2015-02-19T06:32:00.001-05:00";
moment(departureDateTime).format("YYYY-MM-DD"); // returns 2015-02-19
That looks correct. However, if I inspect the time with the code below it will return the time in UTC, which will cause the date to be incorrect (a day in the future) at certain times during the day.
moment(departureDateTime).format("h:mma")); // 11:32am
What am I missing? I thought the default for Moment.js was to return the local time, so I'm confused as to why it wouldn't return 6:32am instead of 11:32am.
Thanks for any assistance you can offer.
A way to do it:
var dateStr = "2015-02-19T06:32:00.001-05:00";
moment(dateStr).utcOffset(dateStr).format("h:mma")
(From here: http://momentjs.com/docs/#/manipulating/utc-offset/)
Edit: The intended way to do it, according to the documentation identified by K_C, is to use parseZone:
var dateStr = "2015-02-19T06:32:00.001-05:00";
moment.parseZone(dateStr).format('h:mma');

AngularJS global Date timezone offset

I'm looking to show dates relative to the users' timezones.
My hope is that Angular has way to globally config the Date filter to do this—having to do this manually on a case-by-case basis feels wrong.
My timestamps are already wrapped in a timestamp() function (simply to multiply by 1000), but I'd prefer not to modify that function if I don't have to.
Edit:
I'm doing this, and it works, but as stated above, I'd like to set this one level higher if possible
$scope.timestamp = function (unix_time) {
var epoch = (unix_time * 1000);
var date = new Date();
var localOffset = (-1) * date.getTimezoneOffset() * 60000;
var stamp = Math.round(new Date(epoch + localOffset).getTime());
return stamp;
};
So, thanks to changes in angular 1.4.x this is now trivial. The proper way to handle this would be to create a decorator that alters the built in date filter before it runs. This is trivially easy, and won't have an impact on performance.
This is one I use. It simply adds a DEFAULT_TIMEZONE if no timezone is specified. This has the effect of moving all dates in the app to GMT as long as no other timezone is given.
module.config(['$provide', function($provide) {
var DEFAULT_TIMEZONE = 'GMT';
$provide.decorator('dateFilter', ['$delegate', '$injector', function($delegate, $injector) {
var oldDelegate = $delegate;
var standardDateFilterInterceptor = function(date, format, timezone) {
if(angular.isUndefined(timezone)) {
timezone = DEFAULT_TIMEZONE;
}
return oldDelegate.apply(this, [date, format, timezone]);
};
return standardDateFilterInterceptor;
}]);
}]);
From official documentation:
Timezones
Keep in mind that Angular datetime filter uses the time zone settings
of the browser. So the same application will show different time
information depending on the time zone settings of the computer that
the application is running on. Neither Javascript nor Angular
currently supports displaying the date with a timezone specified by
the developer.
http://docs.angularjs.org/guide/i18n
A level 'higher' could be creating a wrapper type (AKA class, ...) with your function as constructor. This should be coded at the entry point of the application for being possible using it everywhere.
Have you checked out momentjs http://momentjs.com/ ?
There's also angular-timezones, but I cannot speak to that package (https://github.com/michaelahlers/angular-timezones).

Performance - Date.now() vs Date.getTime()

var timeInMs = Date.now();
per MDN
vs.
var timeInMs = new Date(optional).getTime();
per MDN.
Is there any difference between the two, besides the syntax and the ability to set the Date (to not the current) via optional in the second version?
Date.now() is faster - check out the jsperf
These things are the same (edit semantically; performance is a little better with .now()):
var t1 = Date.now();
var t2 = new Date().getTime();
However, the time value from any already-created Date instance is frozen at the time of its construction (or at whatever time/date it's been set to). That is, if you do this:
var now = new Date();
and then wait a while, a subsequent call to now.getTime() will tell the time at the point the variable was set.
They are effectively equivalent, but you should use Date.now(). It's clearer and about twice as fast.
Edit: Source: http://jsperf.com/date-now-vs-new-date
When you do (new Date()).getTime() you are creating a new Date object. If you do this repeatedly, it will be about 2x slower than Date.now()
The same principle should apply for Array.prototype.slice.call(arguments, 0) vs [].slice.call(arguments, 0)
Yes, that is correct; they are effectively equivalent when using the current time.
Sometimes it's preferable to keep some time tracking variable in a Date object format rather than as just a number of milliseconds, to have access to Date's methods without re-instantiating. In that case, Date.now() still wins over new Date() or the like, though only by about 20% on my Chrome and by a tiny amount on IE.
See my JSPERF on
timeStamp2.setTime(Date.now()); // set to current;
vs.
timeStamp1 = new Date(); // set to current;
http://jsperf.com/new-date-vs-settime
I tried to find the extracly answer for your question. I found a page with a benchmark so clearly.
The static Date.now() method returns the number of milliseconds elapsed since January 1, 1970 00:00:00 UTC.
The getTime() method returns the number of milliseconds since the ECMAScript epoch.
You can use this method to help assign a date and time to another Date object. This method is functionally equivalent to the valueOf() method.
Source: https://developer.mozilla.org/
ex:
const moonLanding = new Date('July 20, 69 20:17:40 GMT+00:00');
console.log('getTime:::', moonLanding.getTime()); // expected output: -14182940000
console.log('valueOf:::', moonLanding.valueOf()); // expected output: -14182940000
Date.now() is calling the static method now() of the class Date.
While new Date().getTime() can be divided into two steps:
new Date(): Call the constructor() method of Date class to initialize an instance of Date class.
Call getTime() method of the instance we just initialize.
MDN web docs classifies Date.now() into static method of Date, and Date.prototype.getTime() into instance method.

Categories