Dayjs: ISO weeks (start from monday)?

Created on 31 May 2018  路  30Comments  路  Source: iamkun/dayjs

There are some handy methods in moment.js like .startOf('isoWeek'), .isoWeekday(1). They are very useful when Monday is the first day of week in current locale.

I didn't found any similar methods, are they exists?

enhancement released

Most helpful comment

I found 2 solutions to override the weekStart globally (per locale). I don't know if this is the best way but maybe this helps somebody else too:

Solution 1:

import 'dayjs' from 'dayjs';
dayjs.Ls.en.weekStart = 1;

Solution 2:

import 'dayjs' from 'dayjs';
import en from 'dayjs/locale/en';
dayjs.locale({
    ...en,
    weekStart: 1,
});

All 30 comments

Check isoWeek here https://day.js.org/docs/en/get-set/iso-week


@denisinvader No such feature at the moment. > Monday is the first day of week in current locale I'm not familiar with this. Is that mean `.startOf('isoWeek')` is Monday, while `.startOf('week')` is still Sunday?

@iamkun yes https://momentjs.com/docs/#/get-set/weekday/

I think it would be nice to define the first day of week globally by locale or plugin

Should be defined in locale file I think.

I could work on this

That would be nice. What's your plan then?

let me dive in the code for a couple of days first

Cool THX.

Well regardless of the locale (depending on the user settings), I need to be able to get the start of the week to be monday (like the iso).

In moment: startOf('week') depend on the locale and startOf('isoWeek') is always monday.

But it could be startOf('localeWeek') and startOf('week') (locale should be default)

@iamkun here is my plan:

  • Add new boolean parameter in locale configuration - for example mondayFirst, false by default;
  • Conditionally change calculation in Dayjs.$set and Dayjs.day methods
  • Conditionally change calculation in Dayjs.startOf method for the C.W case

I think adding new constant isoWeek only for .startOf method is unnecessary, its calculation could depends only on current locale

And for those (like me) that want all locale weeks to start on Sunday or Monday they can override the mondayFirst parameter (is it easy ?). That way no need of an isoWeek.

@hlehmann you mean the case when you want to use texts from some locale that starts from Sunday, but set "mondayFirst" in config (not in the locale)?

Yes something like this

  • dayjs.locale('en', {mondayFirst:true})
  • dayjs.locale('en').extendLocale({mondayFirst:true})

better in locale file monday: 0 or monday:1

Plus, I'm looking for a way to implement this as a plugin, rather in the main code.

I would suggest to instead of defining an attribute mondayFirst, could be something like startOfWeek and define 0 as sunday or 1 as monday.

Any news here?

Any update?

Here is my quick workaround:

const dayjs = require('dayjs')

const current_millis = dayjs().valueOf()
const add_day = (count, millis) => dayjs(millis).add(count, 'day').valueOf()

// ===== the actual "week starts on" stuff =====
const start_of_week = (millis, week_starts_on) => {
  if (week_starts_on === 'sunday') {
    return dayjs(millis).startOf('week').valueOf()
  } else if (week_starts_on === 'monday') {
    return add_day(1, dayjs(millis).subtract(1, 'day').startOf('week').valueOf())
  }
}

const end_of_week = (millis, week_starts_on) => {
  if (week_starts_on === 'sunday') {
    return dayjs(millis).endOf('week').valueOf()
  } else if (week_starts_on === 'monday') {
    return add_day(1, dayjs(millis).subtract(1, 'day').endOf('week').valueOf())
  }
}
// =====

console.log('===== week start =====')

console.log(`week starts on sunday: ${dayjs(start_of_week(current_millis, 'sunday')).format('DD MMM YYYY')}`)
console.log(`week starts on monday: ${dayjs(start_of_week(current_millis, 'monday')).format('DD MMM YYYY')}`)

console.log('===== week end =====')

console.log(`week ends on sunday: ${dayjs(end_of_week(current_millis, 'sunday')).format('DD MMM YYYY')}`)
console.log(`week ends on monday: ${dayjs(end_of_week(current_millis, 'monday')).format('DD MMM YYYY')}`)

:tada: This issue has been resolved in version 1.8.4 :tada:

The release is available on:

Your semantic-release bot :package::rocket:

I found 2 solutions to override the weekStart globally (per locale). I don't know if this is the best way but maybe this helps somebody else too:

Solution 1:

import 'dayjs' from 'dayjs';
dayjs.Ls.en.weekStart = 1;

Solution 2:

import 'dayjs' from 'dayjs';
import en from 'dayjs/locale/en';
dayjs.locale({
    ...en,
    weekStart: 1,
});

Hello @iamkun

Thank your efforts and helping me out here.

Will you be open to a PR where I add a section (basically what @dantodev has posted above) in the API reference of the startOf method?

@hoodwink73 Thanks. But seems we don't have to mention this, do we?

I had to dig in the source code to find this two solutions. Adding this to the docs would be better. Some one who needs this feature may not have the time, patience or skills to search in the soure code and may decide to use another library.

But which of my solutions is better for documentation? The first one is shorter but I don't think that the Ls variable should be used/documented as public API. The second solution is a bit more code but you could also override other locale settings at the same time.

Solution 2 is better I think.

However, a new plugin 'isoWeek' should be made to fix this issue is better than the temporary solution above.

A plugin would be a suitable solution as well. But it should still have the option to set different isoWeek values for different locales.

According to moment.js, Gets or sets the ISO day of the week with 1 being Monday and 7 being Sunday. There's no other option cause it's ISO standard.

I think the current solution is great and if you need to redefine weekStart for some reason, merging locale fits perfectly in the current API (as in the example above)

dayjs.locale({
    ...en,
    weekStart: 1,
});

Also needed .isoWeekday plugin. Quickly made smth like this:

import { Dayjs, PluginFunc } from 'dayjs'

declare module 'dayjs' {
  interface Dayjs {
    /**
     * 1: Monday
     * ...
     * 6: Saturday
     * 7: Sunday
     */
    isoWeekday (): number
  }
}

const isoWeekday: PluginFunc = (_opt, dayjsClass) => {
  dayjsClass.prototype.isoWeekday = function (this: Dayjs) {
    const { $W } = this as any
    return $W <= 0 ? $W + 7 : $W
  }
}

export default isoWeekday

Hello @iamkun.
I think that, both of them should be supported. 'isoWeek' is not only a regional thing we can use dayjs.locale({ ...zh }); to implement, but also a regional-less thing we can use both isoWeek and week.

I approved that it should be handled in local(), but it also could be a single accessible method

Hi, question: in all locales/settings

  1. dayjs().day(7) is always Sunday?

  2. dayjs().day() is either 0 or 7, depending on locale ?

I think the current solution is great and if you need to redefine weekStart for some reason, merging locale fits perfectly in the current API (as in the example above)

dayjs.locale({
    ...en,
    weekStart: 1,
});

This one works perfectly, will be very helpful for react app where I need to load it globally on beginning. While using the plugin doesn't seem to work on my other calendar if defined at the top level app

Was this page helpful?
0 / 5 - 0 ratings

Related issues

fundon picture fundon  路  5Comments

scottsandersdev picture scottsandersdev  路  3Comments

lyz810 picture lyz810  路  4Comments

antony picture antony  路  5Comments

paraself picture paraself  路  3Comments