Moment.js week number differs from MySQL - javascript

From the docs for Moment.js, it says moment().startOf('isoWeek') sets to the first day of the week according to ISO 8601.
From the wikipedia page for ISO 8601, it says the first week is (among other equivalent definitions): the first week with the majority (four or more) of its days in the starting year.
From the docs for MySQL, it says WEEK(date, 3) gives a week (1-53) with Monday as the first day of the first week with 4 or more days this year.
From what I can tell, these are all equivalent definitions of a week, yet they don't mesh.
My MySQL database (v5.6.17) gives me 201616 for SELECT YEARWEEK('2016-4-20',3)
Using Moment.js (v2.10.3) in the browser gives me Mon Apr 11 2016 for moment().year(2016).week(16).startOf("isoweek")
Those aren't the same week, and I can't figure out why.

When you call .week() you are setting the "locale" week (I have no idea how moment.js works that out), but likely the first day will be Sunday. When you then call .startOf('isoweek') you are then getting the ISO start of that week, which is the previous Monday.
If you want to use ISO, you have to use ISO methods, so:
moment().year(2016).isoWeek(16).startOf('isoweek');
creates a moment object for 2016-04-18T00:00:00
Or use a string:
moment('2016-W16') // 2016-04-18T00:00:00
which defaults to ISO week numbering and start of week.

Related

Monday and Sunday of previous week in Unix timestamp AND in New Zealand timezone

I was wondering what would be the best way to tackle getting the unix timestamps of Monday and Sunday in New Zealand timezone while the system clock (AWS Lambda) is in a different timezone.
I've tried the below and it seems to work well in my local computer however obviously when executed on AWS, it'll be a different timezone.
Can someone please suggest the best way to deal with timezones so the code can run on whatever location?
var monday = moment().day(-13).startOf('day').toDate().getTime() // Monday last week
var sunday = moment().day(-7).startOf('day').toDate().getTime() // Sunday last week
Unix Timestamp always give time in UTC regardless of your position. To get the local time of your position please apply the timezone offset to the unix timestamp. https://en.wikipedia.org/wiki/Unix_time
A few things:
You can use Moment-Timezone to work with IANA time zone identifiers in Moment.
New Zealand has two different IANA time zone identifiers:
Pacific/Auckland covers most of New Zealand, which uses UTC+12:00 during standard time, and UTC+13:00 during daylight saving time.
Pacific/Chatham covers the Chatham Islands which is also part of New Zealand. However, Chatham uses UTC+12:45 during standard time, and UTC+13:45 during daylight saving time.
You do not need to convert to a Date object. Moment can give you a Unix timestamp directly, either as seconds with .unix(), or as milliseconds with .valueOf(). Both imply a conversion to UTC, as Unix timestamps are inherently UTC based.
One cannot get a Unix timestamp for an entire day, but rather only for a point in time. The timestamp you are probably looking for would be at the start of the local day, which is always midnight (00:00) in New Zealand (but not necessarily in other time zones on DST transition days, depending on the time of the transition).
When use Moment's day function, day(-13) doesn't mean "Monday last week". It means "two Mondays ago." If you meant "one Monday ago", that would be day(-6). Likewise day(-7) means "one Sunday ago. In both cases, it doesn't count the current day. For example, since today is Sunday 2019-09-01, day(-7) refers to Sunday 2019-08-25.
Putting this all together:
var oneMondayAgoInAuckland = moment.tz('Pacific/Auckland').day(-6).startOf('day').valueOf();
var oneSundayAgoInAuckland = moment.tz('Pacific/Auckland').day(-7).startOf('day').valueOf();
At the moment, these return 1566734400000 and 1566648000000 respectively.

Handle unknown date parts in moment.js

I am using moment.js to parse birthdates:
moment(birthdate, 'DD.MM.YYYY')
If all date parts, i.e. day, month and year are available everything is fine. However there are people who dont have an exact birthdate. If only the year of birth is available the above parsing sets the day and month to default values that is the first January and this is wrong.
Can I create a moment object with unknown (nullable) values for the day and month?
No. The data stored by a moment object is a JavaScript Date object, which typically stores a Unix timestamp internally (exact number of seconds since 1970-01-01 00:00:00 UTC). This single value cannot represent anything other than an exact moment in time.
You will need to use a different structure to represent this "partial date" concept.

Moment JS Parse strange behaviour

I'm using moment.parse String+Format method
when I call moment("=min(C2:C4)", 'DD/MM/YYYY') it evaluates to valid date
Sun Apr 02 2017 00:00:00 GMT+0300 (FLE Daylight Time)
I can't understand how moment parses "=min(C2:C4)" to valid date. Just wonder, some one can explain.
From Moment.js docs:
Moment's parser is very forgiving, and this can lead to undesired/unexpected behavior.
Short answer: because of your expected loose format, moment parses the 2 as the day and the 4 as the month.
Long answer:
Visualizing this might be easier if you run your command in a console and view the results. I'd recommend taking a look there first, and I'll explain the important parts below.
Date string vs. format
You've specified your string as "=min(C2:C4)" and your format as DD/MM/YYYY, so moment is looking for a date in that general format: a day followed by a month followed by a year.
moment._pf.unusedTokens[]
This is an array and has one value, 'YYYY'; the parser did not find a year, but it did find a day and a month... hmmm.
moment._pf.unusedInput[]
This tells us more - an array with three values:
1. '=min(C'
2. ':C'
3. ')'
Looks like moment found the 2 and the 4 to match day and month. You'll find these values in the moment._pf.parsedDateParts array.
So, that should explain why the date is April 2, 2017. The month of 3 (this is the finalized month, not the actual value parsed. Months are zero-indexed, so it's back to "4") and the day of 2. No year was given, so moment assumes it's the current year. No time was given, so it assumes the start of the day.
If you don't want this behavior you should pass a 3rd / last param as true (strict matching). Check http://momentjs.com/docs/#/parsing/string-format/ for more details.

later.js - February and End of Month

I am creating a platform for recurring monthly orders.
I am using later.js for the recurrence. I have come across the following two cases and I am wondering if anybody has suggestions on how to better handle these (or if later.js handles them natively somehow):
later.parse.recur().on(31).dayOfMonth()
The date is the 31st of a given month. Current result is that is jumps months that end on the 30th. WORKAROUND: is to use last().dayOfMonth().
later.parse.recur().on(30).dayOfMonth()
later.parse.recur().on(31).dayOfMonth()
Month of February, ending on the 28th or 29th. How to handle if the date is 30th (or 31st). WORKAROUND: If date > 28th, add .and().on(59).dayOfYear()
Thanks!
I don't know the specifics of later.js, but apparently you can write something called a custom modifier: https://github.com/bunkat/later/blob/master/example/modifier.js
In addition to this, if you add a month to a javascript date (doesn't matter if the number becomes greater than 11/december), set the day of the month to the first then subtract 1 day, then you'll get the date of the last day in the originally given month. For example:
var a = new Date("2000-02-25");
var b = new Date(new Date(a.getFullYear(),a.getMonth()+1,1)-1);
console.log(b);

Will assigning 0 to the 3rd parameter of a JavaScript Date() object always create an end of month date?

I'm working on a jQuery credit card expiration date validation script. Credit cards expire after the last day of the expiration month. For instance, if the card expires on 8/2013 then it's good through 8/31/2013.
In the past on the server side I've determined the last day of the month by adding 1 to the current month, then subtracting 1 day.
Today I noticed that when creating a new date, if 0 is applied to the 3rd parameter of the JavaScript Date() object, the resulting date will be the end-of-month day. But I've been unable to locate any online documentation to affirm this observation.
Here is some sample code.
var month = 10;
var year = 2013;
var expires = new Date(year, month, 0);
alert(expires);
And here is a jsFiddle example that I created.
This is a bit confusing, because I thought in JavaScript months were zero based. I've tested this in Chrome, Firefox, IE, and Safari, and the behavior appears consistent. The returned date consistently displays the last day of the month. This looks like a lucky find, but I'd really like to understand what is happening here.
Am I safe to run with this approach to assigning an end of month date, and if so is there some online documentation that I can point to which affirms this? Thanks.
Months are zero-based. That creates an end-of-month date in the previous month. Month 10 is November, so creating a date with day 0 in November gives you the end of October (month 9).
That is, day 0 in November means "the day before 1 November", which is the last day of October. Day -1 in November would be 30 October.

Categories

Resources