Path: blob/trunk/third_party/closure/goog/date/daterange.js
2868 views
// Copyright 2008 The Closure Library Authors. All Rights Reserved.1//2// Licensed under the Apache License, Version 2.0 (the "License");3// you may not use this file except in compliance with the License.4// You may obtain a copy of the License at5//6// http://www.apache.org/licenses/LICENSE-2.07//8// Unless required by applicable law or agreed to in writing, software9// distributed under the License is distributed on an "AS-IS" BASIS,10// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.11// See the License for the specific language governing permissions and12// limitations under the License.1314/**15* @fileoverview Date range data structure. Based loosely on16* com.google.common.util.DateRange.17*18* @author [email protected] (David P. Baker)19*/2021goog.provide('goog.date.DateRange');22goog.provide('goog.date.DateRange.Iterator');23goog.provide('goog.date.DateRange.StandardDateRangeKeys');2425goog.require('goog.date.Date');26goog.require('goog.date.Interval');27goog.require('goog.iter.Iterator');28goog.require('goog.iter.StopIteration');29303132/**33* Constructs a date range.34* @constructor35* @struct36* @param {goog.date.Date} startDate The first date in the range.37* @param {goog.date.Date} endDate The last date in the range.38* @final39*/40goog.date.DateRange = function(startDate, endDate) {41/**42* The first date in the range.43* @type {goog.date.Date}44* @private45*/46this.startDate_ = startDate;4748/**49* The last date in the range.50* @type {goog.date.Date}51* @private52*/53this.endDate_ = endDate;54};555657/**58* The first possible day, as far as this class is concerned.59* @type {goog.date.Date}60*/61goog.date.DateRange.MINIMUM_DATE = new goog.date.Date(0, 0, 1);626364/**65* The last possible day, as far as this class is concerned.66* @type {goog.date.Date}67*/68goog.date.DateRange.MAXIMUM_DATE = new goog.date.Date(9999, 11, 31);697071/**72* @return {goog.date.Date} The first date in the range.73*/74goog.date.DateRange.prototype.getStartDate = function() {75return this.startDate_;76};777879/**80* @return {goog.date.Date} The last date in the range.81*/82goog.date.DateRange.prototype.getEndDate = function() {83return this.endDate_;84};858687/**88* Tests if a date falls within this range.89*90* @param {goog.date.Date} date The date to test.91* @return {boolean} Whether the date is in the range.92*/93goog.date.DateRange.prototype.contains = function(date) {94return date.valueOf() >= this.startDate_.valueOf() &&95date.valueOf() <= this.endDate_.valueOf();96};979899/**100* @return {!goog.date.DateRange.Iterator} An iterator over the date range.101*/102goog.date.DateRange.prototype.iterator = function() {103return new goog.date.DateRange.Iterator(this);104};105106107/**108* Tests two {@link goog.date.DateRange} objects for equality.109* @param {goog.date.DateRange} a A date range.110* @param {goog.date.DateRange} b A date range.111* @return {boolean} Whether |a| is the same range as |b|.112*/113goog.date.DateRange.equals = function(a, b) {114// Test for same object reference; type conversion is irrelevant.115if (a === b) {116return true;117}118119if (a == null || b == null) {120return false;121}122123return a.startDate_.equals(b.startDate_) && a.endDate_.equals(b.endDate_);124};125126127/**128* Calculates a date that is a number of days after a date. Does not modify its129* input.130* @param {goog.date.Date} date The input date.131* @param {number} offset Number of days.132* @return {!goog.date.Date} The date that is |offset| days after |date|.133* @private134*/135goog.date.DateRange.offsetInDays_ = function(date, offset) {136var newDate = date.clone();137newDate.add(new goog.date.Interval(goog.date.Interval.DAYS, offset));138return newDate;139};140141142/**143* Calculates a date that is a number of months after the first day in the144* month that contains its input. Does not modify its input.145* @param {goog.date.Date} date The input date.146* @param {number} offset Number of months.147* @return {!goog.date.Date} The date that is |offset| months after the first148* day in the month that contains |date|.149* @private150*/151goog.date.DateRange.offsetInMonths_ = function(date, offset) {152var newDate = date.clone();153newDate.setDate(1);154newDate.add(new goog.date.Interval(goog.date.Interval.MONTHS, offset));155return newDate;156};157158159/**160* Returns the range from yesterday to yesterday.161* @param {goog.date.Date=} opt_today The date to consider today.162* Defaults to today.163* @return {!goog.date.DateRange} The range that includes only yesterday.164*/165goog.date.DateRange.yesterday = function(opt_today) {166var today = goog.date.DateRange.cloneOrCreate_(opt_today);167var yesterday = goog.date.DateRange.offsetInDays_(today, -1);168return new goog.date.DateRange(yesterday, yesterday.clone());169};170171172/**173* Returns the range from today to today.174* @param {goog.date.Date=} opt_today The date to consider today.175* Defaults to today.176* @return {!goog.date.DateRange} The range that includes only today.177*/178goog.date.DateRange.today = function(opt_today) {179var today = goog.date.DateRange.cloneOrCreate_(opt_today);180return new goog.date.DateRange(today, today.clone());181};182183184/**185* Returns the range that includes the seven days that end yesterday.186* @param {goog.date.Date=} opt_today The date to consider today.187* Defaults to today.188* @return {!goog.date.DateRange} The range that includes the seven days that189* end yesterday.190*/191goog.date.DateRange.last7Days = function(opt_today) {192var today = goog.date.DateRange.cloneOrCreate_(opt_today);193var yesterday = goog.date.DateRange.offsetInDays_(today, -1);194return new goog.date.DateRange(195goog.date.DateRange.offsetInDays_(today, -7), yesterday);196};197198199/**200* Returns the range that starts the first of this month and ends the last day201* of this month.202* @param {goog.date.Date=} opt_today The date to consider today.203* Defaults to today.204* @return {!goog.date.DateRange} The range that starts the first of this month205* and ends the last day of this month.206*/207goog.date.DateRange.thisMonth = function(opt_today) {208var today = goog.date.DateRange.cloneOrCreate_(opt_today);209return new goog.date.DateRange(210goog.date.DateRange.offsetInMonths_(today, 0),211goog.date.DateRange.offsetInDays_(212goog.date.DateRange.offsetInMonths_(today, 1), -1));213};214215216/**217* Returns the range that starts the first of last month and ends the last day218* of last month.219* @param {goog.date.Date=} opt_today The date to consider today.220* Defaults to today.221* @return {!goog.date.DateRange} The range that starts the first of last month222* and ends the last day of last month.223*/224goog.date.DateRange.lastMonth = function(opt_today) {225var today = goog.date.DateRange.cloneOrCreate_(opt_today);226return new goog.date.DateRange(227goog.date.DateRange.offsetInMonths_(today, -1),228goog.date.DateRange.offsetInDays_(229goog.date.DateRange.offsetInMonths_(today, 0), -1));230};231232233/**234* Returns the seven-day range that starts on the first day of the week235* (see {@link goog.i18n.DateTimeSymbols.FIRSTDAYOFWEEK}) on or before today.236* @param {goog.date.Date=} opt_today The date to consider today.237* Defaults to today.238* @return {!goog.date.DateRange} The range that starts the Monday on or before239* today and ends the Sunday on or after today.240*/241goog.date.DateRange.thisWeek = function(opt_today) {242var today = goog.date.DateRange.cloneOrCreate_(opt_today);243var iso = today.getIsoWeekday();244var firstDay = today.getFirstDayOfWeek();245var i18nFirstDay = (iso >= firstDay) ? iso - firstDay : iso + (7 - firstDay);246var start = goog.date.DateRange.offsetInDays_(today, -i18nFirstDay);247var end = goog.date.DateRange.offsetInDays_(start, 6);248return new goog.date.DateRange(start, end);249};250251252/**253* Returns the seven-day range that ends the day before the first day of254* the week (see {@link goog.i18n.DateTimeSymbols.FIRSTDAYOFWEEK}) that255* contains today.256* @param {goog.date.Date=} opt_today The date to consider today.257* Defaults to today.258* @return {!goog.date.DateRange} The range that starts seven days before the259* Monday on or before today and ends the Sunday on or before yesterday.260*/261goog.date.DateRange.lastWeek = function(opt_today) {262var thisWeek = goog.date.DateRange.thisWeek(opt_today);263var start = goog.date.DateRange.offsetInDays_(thisWeek.getStartDate(), -7);264var end = goog.date.DateRange.offsetInDays_(thisWeek.getEndDate(), -7);265return new goog.date.DateRange(start, end);266};267268269/**270* Returns the range that starts seven days before the Monday on or before271* today and ends the Friday before today.272* @param {goog.date.Date=} opt_today The date to consider today.273* Defaults to today.274* @return {!goog.date.DateRange} The range that starts seven days before the275* Monday on or before today and ends the Friday before today.276*/277goog.date.DateRange.lastBusinessWeek = function(opt_today) {278// TODO(user): should be i18nized.279var today = goog.date.DateRange.cloneOrCreate_(opt_today);280var start =281goog.date.DateRange.offsetInDays_(today, -7 - today.getIsoWeekday());282var end = goog.date.DateRange.offsetInDays_(start, 4);283return new goog.date.DateRange(start, end);284};285286287/**288* Returns the range that includes all days between January 1, 1900 and289* December 31, 9999.290* @param {goog.date.Date=} opt_today The date to consider today.291* Defaults to today.292* @return {!goog.date.DateRange} The range that includes all days between293* January 1, 1900 and December 31, 9999.294*/295goog.date.DateRange.allTime = function(opt_today) {296return new goog.date.DateRange(297goog.date.DateRange.MINIMUM_DATE, goog.date.DateRange.MAXIMUM_DATE);298};299300301/**302* Standard date range keys. Equivalent to the enum IDs in303* DateRange.java http://go/datarange.java304*305* @enum {string}306*/307goog.date.DateRange.StandardDateRangeKeys = {308YESTERDAY: 'yesterday',309TODAY: 'today',310LAST_7_DAYS: 'last7days',311THIS_MONTH: 'thismonth',312LAST_MONTH: 'lastmonth',313THIS_WEEK: 'thisweek',314LAST_WEEK: 'lastweek',315LAST_BUSINESS_WEEK: 'lastbusinessweek',316ALL_TIME: 'alltime'317};318319320/**321* @param {string} dateRangeKey A standard date range key.322* @param {goog.date.Date=} opt_today The date to consider today.323* Defaults to today.324* @return {!goog.date.DateRange} The date range that corresponds to that key.325* @throws {Error} If no standard date range with that key exists.326*/327goog.date.DateRange.standardDateRange = function(dateRangeKey, opt_today) {328switch (dateRangeKey) {329case goog.date.DateRange.StandardDateRangeKeys.YESTERDAY:330return goog.date.DateRange.yesterday(opt_today);331332case goog.date.DateRange.StandardDateRangeKeys.TODAY:333return goog.date.DateRange.today(opt_today);334335case goog.date.DateRange.StandardDateRangeKeys.LAST_7_DAYS:336return goog.date.DateRange.last7Days(opt_today);337338case goog.date.DateRange.StandardDateRangeKeys.THIS_MONTH:339return goog.date.DateRange.thisMonth(opt_today);340341case goog.date.DateRange.StandardDateRangeKeys.LAST_MONTH:342return goog.date.DateRange.lastMonth(opt_today);343344case goog.date.DateRange.StandardDateRangeKeys.THIS_WEEK:345return goog.date.DateRange.thisWeek(opt_today);346347case goog.date.DateRange.StandardDateRangeKeys.LAST_WEEK:348return goog.date.DateRange.lastWeek(opt_today);349350case goog.date.DateRange.StandardDateRangeKeys.LAST_BUSINESS_WEEK:351return goog.date.DateRange.lastBusinessWeek(opt_today);352353case goog.date.DateRange.StandardDateRangeKeys.ALL_TIME:354return goog.date.DateRange.allTime(opt_today);355356default:357throw Error('no such date range key: ' + dateRangeKey);358}359};360361362/**363* Clones or creates new.364* @param {goog.date.Date=} opt_today The date to consider today.365* Defaults to today.366* @return {!goog.date.Date} cloned or new.367* @private368*/369goog.date.DateRange.cloneOrCreate_ = function(opt_today) {370return opt_today ? opt_today.clone() : new goog.date.Date();371};372373374375/**376* Creates an iterator over the dates in a {@link goog.date.DateRange}.377* @constructor378* @struct379* @extends {goog.iter.Iterator<goog.date.Date>}380* @param {goog.date.DateRange} dateRange The date range to iterate.381* @final382*/383goog.date.DateRange.Iterator = function(dateRange) {384/**385* The next date.386* @type {goog.date.Date}387* @private388*/389this.nextDate_ = dateRange.getStartDate().clone();390391/**392* The end date, expressed as an integer: YYYYMMDD.393* @type {number}394* @private395*/396this.endDate_ = Number(dateRange.getEndDate().toIsoString());397};398goog.inherits(goog.date.DateRange.Iterator, goog.iter.Iterator);399400401/** @override */402goog.date.DateRange.Iterator.prototype.next = function() {403if (Number(this.nextDate_.toIsoString()) > this.endDate_) {404throw goog.iter.StopIteration;405}406407var rv = this.nextDate_.clone();408this.nextDate_.add(new goog.date.Interval(goog.date.Interval.DAYS, 1));409return rv;410};411412413