1/* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 5var EXPORTED_SYMBOLS = ["CalWeekInfoService"]; 6 7var { XPCOMUtils } = ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm"); 8 9const SUNDAY = 0; 10const THURSDAY = 4; 11 12XPCOMUtils.defineLazyPreferenceGetter(this, "startWeekday", "calendar.week.start", SUNDAY); 13 14function CalWeekInfoService() { 15 this.wrappedJSObject = this; 16} 17CalWeekInfoService.prototype = { 18 QueryInterface: ChromeUtils.generateQI(["calIWeekInfoService"]), 19 classID: Components.ID("{6877bbdd-f336-46f5-98ce-fe86d0285cc1}"), 20 21 // calIWeekInfoService: 22 getWeekTitle(aDateTime) { 23 /** 24 * This implementation is based on the ISO 8601 standard. 25 * ISO 8601 defines week one as the first week with at least 4 26 * days, and defines Monday as the first day of the week. 27 * Equivalently, the week one is the week with the first Thursday. 28 * 29 * This implementation uses the second definition, because it 30 * enables the user to set a different start-day of the week 31 * (Sunday instead of Monday is a common setting). If the first 32 * definition was used, all week-numbers could be off by one 33 * depending on the week start day. (For example, if weeks start 34 * on Sunday, a year that starts on Thursday has only 3 days 35 * [Thu-Sat] in that week, so it would be part of the last week of 36 * the previous year, but if weeks start on Monday, the year would 37 * have four days [Thu-Sun] in that week, so it would be counted 38 * as week 1.) 39 */ 40 41 // The week number is the number of days since the start of week 1, 42 // divided by 7 and rounded up. Week 1 is the week containing the first 43 // Thursday of the year. 44 // Thus, the week number of any day is the same as the number of days 45 // between the Thursday of that week and the Thursday of week 1, divided 46 // by 7 and rounded up. (This takes care of days at end/start of a year 47 // which may be part of first/last week in the other year.) 48 // The Thursday of a week is the Thursday that follows the first day 49 // of the week. 50 // The week number of a day is the same as the week number of the first 51 // day of the week. (This takes care of days near the start of the year, 52 // which may be part of the week counted in the previous year.) So we 53 // need the startWeekday. 54 55 // The number of days since the start of the week. 56 // Notice that the result of the subtraction might be negative. 57 // We correct for that by adding 7, and then using the remainder operator. 58 let sinceStartOfWeek = (aDateTime.weekday - startWeekday + 7) % 7; 59 60 // The number of days to Thursday is the difference between Thursday 61 // and the start-day of the week (again corrected for negative values). 62 let startToThursday = (THURSDAY - startWeekday + 7) % 7; 63 64 // The yearday number of the Thursday this week. 65 let thisWeeksThursday = aDateTime.yearday - sinceStartOfWeek + startToThursday; 66 67 if (thisWeeksThursday < 1) { 68 // For the first few days of the year, we still are in week 52 or 53. 69 let lastYearDate = aDateTime.clone(); 70 lastYearDate.year -= 1; 71 thisWeeksThursday += lastYearDate.endOfYear.yearday; 72 } else if (thisWeeksThursday > aDateTime.endOfYear.yearday) { 73 // For the last few days of the year, we already are in week 1. 74 thisWeeksThursday -= aDateTime.endOfYear.yearday; 75 } 76 77 let weekNumber = Math.ceil(thisWeeksThursday / 7); 78 return weekNumber; 79 }, 80 81 /** 82 * gets the first day of a week of a passed day under consideration 83 * of the preference setting "calendar.week.start" 84 * 85 * @param aDate a date time object 86 * @return a dateTime-object denoting the first day of the week 87 */ 88 getStartOfWeek(aDate) { 89 let date = aDate.clone(); 90 date.isDate = true; 91 let offset = startWeekday - aDate.weekday; 92 date.day += offset; 93 if (offset > 0) { 94 date.day -= 7; 95 } 96 return date; 97 }, 98 99 /** 100 * gets the last day of a week of a passed day under consideration 101 * of the preference setting "calendar.week.start" 102 * 103 * @param aDate a date time object 104 * @return a dateTime-object denoting the last day of the week 105 */ 106 getEndOfWeek(aDate) { 107 let date = this.getStartOfWeek(aDate); 108 date.day += 6; 109 return date; 110 }, 111}; 112