diff --git a/src/locale/en-gb.js b/src/locale/en-gb.js
--- a/src/locale/en-gb.js
+++ b/src/locale/en-gb.js
@@ -8,6 +8,7 @@ const locale = {
   months: 'January_February_March_April_May_June_July_August_September_October_November_December'.split('_'),
   monthsShort: 'Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec'.split('_'),
   weekStart: 1,
+  yearStart: 4,
   relativeTime: {
     future: 'in %s',
     past: '%s ago',
diff --git a/src/locale/zh-cn.js b/src/locale/zh-cn.js
--- a/src/locale/zh-cn.js
+++ b/src/locale/zh-cn.js
@@ -16,6 +16,7 @@ const locale = {
     }
   },
   weekStart: 1,
+  yearStart: 4,
   formats: {
     LT: 'HH:mm',
     LTS: 'HH:mm:ss',
diff --git a/src/plugin/weekOfYear/index.js b/src/plugin/weekOfYear/index.js
--- a/src/plugin/weekOfYear/index.js
+++ b/src/plugin/weekOfYear/index.js
@@ -1,17 +1,26 @@
 import { MS, Y, D, W } from '../../constant'
 
-export default (o, c, d) => {
+export default (o, c) => {
   const proto = c.prototype
   proto.week = function (week = null) {
     if (week !== null) {
-      return this.add((week - this.week()) * 7, 'day')
+      return this.add((week - this.week()) * 7, D)
     }
-    const weekStart = this.$locale().weekStart || 0
-    const startOfYear = d(this).startOf(Y)
-    const compareDay = startOfYear.subtract(startOfYear.day() - weekStart, D).subtract(1, MS)
-    const diffInWeek = this.diff(compareDay, W, true)
-    const result = Math.ceil(diffInWeek)
-    return result > 52 ? 1 : result
+    const yearStart = this.$locale().yearStart || 1
+    if (this.month() === 11 && this.date() > 25) {
+      const nextYearStartDay = this.startOf(Y).add(1, Y).date(yearStart)
+      const thisEndOfWeek = this.endOf(W)
+      if (nextYearStartDay.isBefore(thisEndOfWeek)) {
+        return 1
+      }
+    }
+    const yearStartDay = this.startOf(Y).date(yearStart)
+    const yearStartWeek = yearStartDay.startOf(W).subtract(1, MS)
+    const diffInWeek = this.diff(yearStartWeek, W, true)
+    if (diffInWeek < 0) {
+      return this.startOf('week').week()
+    }
+    return Math.ceil(diffInWeek)
   }
 
   proto.weeks = function (week = null) {

diff --git a/test/locale/keys.test.js b/test/locale/keys.test.js
--- a/test/locale/keys.test.js
+++ b/test/locale/keys.test.js
@@ -28,6 +28,7 @@ Locale.forEach((locale) => {
       monthsShort,
       weekdaysMin,
       weekStart,
+      yearStart,
       meridiem
     } = locale.content
 
@@ -37,6 +38,7 @@ Locale.forEach((locale) => {
     if (weekdaysShort) expect(weekdaysShort).toEqual(expect.any(Array))
     if (weekdaysMin) expect(weekdaysMin).toEqual(expect.any(Array))
     if (weekStart) expect(weekStart).toEqual(expect.any(Number))
+    if (yearStart) expect(yearStart).toEqual(expect.any(Number))
 
     // months could be a function or array
     if (Array.isArray(months)) {
diff --git a/test/plugin/weekOfYear.test.js b/test/plugin/weekOfYear.test.js
--- a/test/plugin/weekOfYear.test.js
+++ b/test/plugin/weekOfYear.test.js
@@ -33,14 +33,25 @@ it('Week of year', () => {
 it('Week of year with locale', () => {
   dayjs.locale('en-gb')
   moment.locale('en-gb')
-
   const day = '2019-07-28'
   expect(dayjs(day).week()).toBe(moment(day).week())
+})
 
-  // Edges
-  expect(dayjs('2018-12-30').week()).toBe(moment('2018-12-30').week())
-  expect(dayjs('2019-12-29').week()).toBe(moment('2019-12-29').week())
-  expect(dayjs('2019-12-30').week()).toBe(moment('2019-12-30').week())
+describe('Week of year with locale edges', () => {
+  const testCases = [
+    '2018-12-30',
+    '2018-12-31',
+    '2019-12-29',
+    '2019-12-30',
+    '2016-01-01',
+    '2016-01-04'
+  ]
+  testCases.forEach((t) => {
+    it(`Edges ${t}`, () => {
+      expect(dayjs(t).week())
+        .toBe(moment(t).week())
+    })
+  })
 })
 
 it('Format w ww wo', () => {
diff --git a/test/plugin/weekday.test.js b/test/plugin/weekday.test.js
--- a/test/plugin/weekday.test.js
+++ b/test/plugin/weekday.test.js
@@ -31,6 +31,10 @@ it('Monday is the first day of the week', () => {
   expect(dayjs().weekday(0).date()).toBe(moment().weekday(0).date())
   expect(dayjs().weekday(-7).format()).toBe(moment().weekday(-7).format())
   expect(dayjs().weekday(7).format()).toBe(moment().weekday(7).format())
+  const d1 = '2020-01-05'
+  expect(dayjs(d1).weekday()).toBe(moment(d1).weekday())
+  const d2 = '2020-01-07'
+  expect(dayjs(d2).weekday()).toBe(moment(d2).weekday())
 })
 
 it('Saturday is the first day of the week', () => {

weekOfYear `week` edge cases with 2015-12-28 and 2016-10-30
**Describe the bug**
weekOfYear `week` edge cases do not match moment `week` calculations

```
expect(dayjs('2015-12-28').week()).toBe(moment('2015-12-28').week())
// dayjs: 1 , moment: 53

expect(dayjs('2016-10-30').week()).toBe(moment('2016-10-30').week())
// dayjs: 44, moment: 43
```

**Expected behavior**
dayjs should return correct week of year, according to http://www.whatweekisit.org/ moment is correct

**Information**
 - Day.js Version [1.8.19]
 - OS: [Mac OS]
 - Browser [running as unit test on Node 12.14.0]
 - Time zone: [CET]


test/timezone.test.js(1) test/timezone.test.js(2) test/timezone.test.js(3) test/timezone.test.js(4) test/plugin/weekday.test.js test/locale/keys.test.js
test/plugin/weekOfYear.test.js