| // Copyright 2008 The Closure Library Authors. All Rights Reserved. |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS-IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| |
| /** |
| * @fileoverview Date range data structure. Based loosely on |
| * com.google.common.util.DateRange. |
| * |
| */ |
| |
| goog.provide('goog.date.DateRange'); |
| goog.provide('goog.date.DateRange.Iterator'); |
| goog.provide('goog.date.DateRange.StandardDateRangeKeys'); |
| |
| goog.require('goog.date.Date'); |
| goog.require('goog.date.Interval'); |
| goog.require('goog.iter.Iterator'); |
| goog.require('goog.iter.StopIteration'); |
| |
| |
| |
| /** |
| * Constructs a date range. |
| * @constructor |
| * @param {goog.date.Date} startDate The first date in the range. |
| * @param {goog.date.Date} endDate The last date in the range. |
| * @final |
| */ |
| goog.date.DateRange = function(startDate, endDate) { |
| /** |
| * The first date in the range. |
| * @type {goog.date.Date} |
| * @private |
| */ |
| this.startDate_ = startDate; |
| |
| /** |
| * The last date in the range. |
| * @type {goog.date.Date} |
| * @private |
| */ |
| this.endDate_ = endDate; |
| }; |
| |
| |
| /** |
| * The first possible day, as far as this class is concerned. |
| * @type {goog.date.Date} |
| */ |
| goog.date.DateRange.MINIMUM_DATE = new goog.date.Date(0, 0, 1); |
| |
| |
| /** |
| * The last possible day, as far as this class is concerned. |
| * @type {goog.date.Date} |
| */ |
| goog.date.DateRange.MAXIMUM_DATE = new goog.date.Date(9999, 11, 31); |
| |
| |
| /** |
| * @return {goog.date.Date} The first date in the range. |
| */ |
| goog.date.DateRange.prototype.getStartDate = function() { |
| return this.startDate_; |
| }; |
| |
| |
| /** |
| * @return {goog.date.Date} The last date in the range. |
| */ |
| goog.date.DateRange.prototype.getEndDate = function() { |
| return this.endDate_; |
| }; |
| |
| |
| /** |
| * Tests if a date falls within this range. |
| * |
| * @param {goog.date.Date} date The date to test. |
| * @return {boolean} Whether the date is in the range. |
| */ |
| goog.date.DateRange.prototype.contains = function(date) { |
| return date.valueOf() >= this.startDate_.valueOf() && |
| date.valueOf() <= this.endDate_.valueOf(); |
| }; |
| |
| |
| /** |
| * @return {!goog.iter.Iterator} An iterator over the date range. |
| */ |
| goog.date.DateRange.prototype.iterator = function() { |
| return new goog.date.DateRange.Iterator(this); |
| }; |
| |
| |
| /** |
| * Tests two {@link goog.date.DateRange} objects for equality. |
| * @param {goog.date.DateRange} a A date range. |
| * @param {goog.date.DateRange} b A date range. |
| * @return {boolean} Whether |a| is the same range as |b|. |
| */ |
| goog.date.DateRange.equals = function(a, b) { |
| // Test for same object reference; type conversion is irrelevant. |
| if (a === b) { |
| return true; |
| } |
| |
| if (a == null || b == null) { |
| return false; |
| } |
| |
| return a.startDate_.equals(b.startDate_) && a.endDate_.equals(b.endDate_); |
| }; |
| |
| |
| /** |
| * Calculates a date that is a number of days after a date. Does not modify its |
| * input. |
| * @param {goog.date.Date} date The input date. |
| * @param {number} offset Number of days. |
| * @return {!goog.date.Date} The date that is |offset| days after |date|. |
| * @private |
| */ |
| goog.date.DateRange.offsetInDays_ = function(date, offset) { |
| var newDate = date.clone(); |
| newDate.add(new goog.date.Interval(goog.date.Interval.DAYS, offset)); |
| return newDate; |
| }; |
| |
| |
| /** |
| * Calculates the Monday before a date. If the input is a Monday, returns the |
| * input. Does not modify its input. |
| * @param {goog.date.Date} date The input date. |
| * @return {!goog.date.Date} If |date| is a Monday, return |date|; otherwise |
| * return the Monday before |date|. |
| * @private |
| */ |
| goog.date.DateRange.currentOrLastMonday_ = function(date) { |
| var newDate = date.clone(); |
| newDate.add(new goog.date.Interval(goog.date.Interval.DAYS, |
| -newDate.getIsoWeekday())); |
| return newDate; |
| }; |
| |
| |
| /** |
| * Calculates a date that is a number of months after the first day in the |
| * month that contains its input. Does not modify its input. |
| * @param {goog.date.Date} date The input date. |
| * @param {number} offset Number of months. |
| * @return {!goog.date.Date} The date that is |offset| months after the first |
| * day in the month that contains |date|. |
| * @private |
| */ |
| goog.date.DateRange.offsetInMonths_ = function(date, offset) { |
| var newDate = date.clone(); |
| newDate.setDate(1); |
| newDate.add(new goog.date.Interval(goog.date.Interval.MONTHS, offset)); |
| return newDate; |
| }; |
| |
| |
| /** |
| * Returns the range from yesterday to yesterday. |
| * @param {goog.date.Date=} opt_today The date to consider today. |
| * Defaults to today. |
| * @return {!goog.date.DateRange} The range that includes only yesterday. |
| */ |
| goog.date.DateRange.yesterday = function(opt_today) { |
| var today = goog.date.DateRange.cloneOrCreate_(opt_today); |
| var yesterday = goog.date.DateRange.offsetInDays_(today, -1); |
| return new goog.date.DateRange(yesterday, yesterday); |
| }; |
| |
| |
| /** |
| * Returns the range from today to today. |
| * @param {goog.date.Date=} opt_today The date to consider today. |
| * Defaults to today. |
| * @return {!goog.date.DateRange} The range that includes only today. |
| */ |
| goog.date.DateRange.today = function(opt_today) { |
| var today = goog.date.DateRange.cloneOrCreate_(opt_today); |
| return new goog.date.DateRange(today, today); |
| }; |
| |
| |
| /** |
| * Returns the range that includes the seven days that end yesterday. |
| * @param {goog.date.Date=} opt_today The date to consider today. |
| * Defaults to today. |
| * @return {!goog.date.DateRange} The range that includes the seven days that |
| * end yesterday. |
| */ |
| goog.date.DateRange.last7Days = function(opt_today) { |
| var today = goog.date.DateRange.cloneOrCreate_(opt_today); |
| var yesterday = goog.date.DateRange.offsetInDays_(today, -1); |
| return new goog.date.DateRange(goog.date.DateRange.offsetInDays_(today, -7), |
| yesterday); |
| }; |
| |
| |
| /** |
| * Returns the range that starts the first of this month and ends the last day |
| * of this month. |
| * @param {goog.date.Date=} opt_today The date to consider today. |
| * Defaults to today. |
| * @return {!goog.date.DateRange} The range that starts the first of this month |
| * and ends the last day of this month. |
| */ |
| goog.date.DateRange.thisMonth = function(opt_today) { |
| var today = goog.date.DateRange.cloneOrCreate_(opt_today); |
| return new goog.date.DateRange( |
| goog.date.DateRange.offsetInMonths_(today, 0), |
| goog.date.DateRange.offsetInDays_( |
| goog.date.DateRange.offsetInMonths_(today, 1), |
| -1)); |
| }; |
| |
| |
| /** |
| * Returns the range that starts the first of last month and ends the last day |
| * of last month. |
| * @param {goog.date.Date=} opt_today The date to consider today. |
| * Defaults to today. |
| * @return {!goog.date.DateRange} The range that starts the first of last month |
| * and ends the last day of last month. |
| */ |
| goog.date.DateRange.lastMonth = function(opt_today) { |
| var today = goog.date.DateRange.cloneOrCreate_(opt_today); |
| return new goog.date.DateRange( |
| goog.date.DateRange.offsetInMonths_(today, -1), |
| goog.date.DateRange.offsetInDays_( |
| goog.date.DateRange.offsetInMonths_(today, 0), |
| -1)); |
| }; |
| |
| |
| /** |
| * Returns the seven-day range that starts on the first day of the week |
| * (see {@link goog.i18n.DateTimeSymbols.FIRSTDAYOFWEEK}) on or before today. |
| * @param {goog.date.Date=} opt_today The date to consider today. |
| * Defaults to today. |
| * @return {!goog.date.DateRange} The range that starts the Monday on or before |
| * today and ends the Sunday on or after today. |
| */ |
| goog.date.DateRange.thisWeek = function(opt_today) { |
| var today = goog.date.DateRange.cloneOrCreate_(opt_today); |
| var iso = today.getIsoWeekday(); |
| var firstDay = today.getFirstDayOfWeek(); |
| var i18nFirstDay = (iso >= firstDay) ? iso - firstDay : iso + (7 - firstDay); |
| var start = goog.date.DateRange.offsetInDays_(today, -i18nFirstDay); |
| var end = goog.date.DateRange.offsetInDays_(start, 6); |
| return new goog.date.DateRange(start, end); |
| }; |
| |
| |
| /** |
| * Returns the seven-day range that ends the day before the first day of |
| * the week (see {@link goog.i18n.DateTimeSymbols.FIRSTDAYOFWEEK}) that |
| * contains today. |
| * @param {goog.date.Date=} opt_today The date to consider today. |
| * Defaults to today. |
| * @return {!goog.date.DateRange} The range that starts seven days before the |
| * Monday on or before today and ends the Sunday on or before yesterday. |
| */ |
| goog.date.DateRange.lastWeek = function(opt_today) { |
| var thisWeek = goog.date.DateRange.thisWeek(opt_today); |
| var start = goog.date.DateRange.offsetInDays_(thisWeek.getStartDate(), -7); |
| var end = goog.date.DateRange.offsetInDays_(thisWeek.getEndDate(), -7); |
| return new goog.date.DateRange(start, end); |
| }; |
| |
| |
| /** |
| * Returns the range that starts seven days before the Monday on or before |
| * today and ends the Friday before today. |
| * @param {goog.date.Date=} opt_today The date to consider today. |
| * Defaults to today. |
| * @return {!goog.date.DateRange} The range that starts seven days before the |
| * Monday on or before today and ends the Friday before today. |
| */ |
| goog.date.DateRange.lastBusinessWeek = function(opt_today) { |
| // TODO(user): should be i18nized. |
| var today = goog.date.DateRange.cloneOrCreate_(opt_today); |
| var start = goog.date.DateRange.offsetInDays_(today, |
| - 7 - today.getIsoWeekday()); |
| var end = goog.date.DateRange.offsetInDays_(start, 4); |
| return new goog.date.DateRange(start, end); |
| }; |
| |
| |
| /** |
| * Returns the range that includes all days between January 1, 1900 and |
| * December 31, 9999. |
| * @param {goog.date.Date=} opt_today The date to consider today. |
| * Defaults to today. |
| * @return {!goog.date.DateRange} The range that includes all days between |
| * January 1, 1900 and December 31, 9999. |
| */ |
| goog.date.DateRange.allTime = function(opt_today) { |
| return new goog.date.DateRange( |
| goog.date.DateRange.MINIMUM_DATE, |
| goog.date.DateRange.MAXIMUM_DATE); |
| }; |
| |
| |
| /** |
| * Standard date range keys. Equivalent to the enum IDs in |
| * DateRange.java http://go/datarange.java |
| * |
| * @enum {string} |
| */ |
| goog.date.DateRange.StandardDateRangeKeys = { |
| YESTERDAY: 'yesterday', |
| TODAY: 'today', |
| LAST_7_DAYS: 'last7days', |
| THIS_MONTH: 'thismonth', |
| LAST_MONTH: 'lastmonth', |
| THIS_WEEK: 'thisweek', |
| LAST_WEEK: 'lastweek', |
| LAST_BUSINESS_WEEK: 'lastbusinessweek', |
| ALL_TIME: 'alltime' |
| }; |
| |
| |
| /** |
| * @param {string} dateRangeKey A standard date range key. |
| * @param {goog.date.Date=} opt_today The date to consider today. |
| * Defaults to today. |
| * @return {!goog.date.DateRange} The date range that corresponds to that key. |
| * @throws {Error} If no standard date range with that key exists. |
| */ |
| goog.date.DateRange.standardDateRange = function(dateRangeKey, opt_today) { |
| switch (dateRangeKey) { |
| case goog.date.DateRange.StandardDateRangeKeys.YESTERDAY: |
| return goog.date.DateRange.yesterday(opt_today); |
| |
| case goog.date.DateRange.StandardDateRangeKeys.TODAY: |
| return goog.date.DateRange.today(opt_today); |
| |
| case goog.date.DateRange.StandardDateRangeKeys.LAST_7_DAYS: |
| return goog.date.DateRange.last7Days(opt_today); |
| |
| case goog.date.DateRange.StandardDateRangeKeys.THIS_MONTH: |
| return goog.date.DateRange.thisMonth(opt_today); |
| |
| case goog.date.DateRange.StandardDateRangeKeys.LAST_MONTH: |
| return goog.date.DateRange.lastMonth(opt_today); |
| |
| case goog.date.DateRange.StandardDateRangeKeys.THIS_WEEK: |
| return goog.date.DateRange.thisWeek(opt_today); |
| |
| case goog.date.DateRange.StandardDateRangeKeys.LAST_WEEK: |
| return goog.date.DateRange.lastWeek(opt_today); |
| |
| case goog.date.DateRange.StandardDateRangeKeys.LAST_BUSINESS_WEEK: |
| return goog.date.DateRange.lastBusinessWeek(opt_today); |
| |
| case goog.date.DateRange.StandardDateRangeKeys.ALL_TIME: |
| return goog.date.DateRange.allTime(opt_today); |
| |
| default: |
| throw Error('no such date range key: ' + dateRangeKey); |
| } |
| }; |
| |
| |
| /** |
| * Clones or creates new. |
| * @param {goog.date.Date=} opt_today The date to consider today. |
| * Defaults to today. |
| * @return {!goog.date.Date} cloned or new. |
| * @private |
| */ |
| goog.date.DateRange.cloneOrCreate_ = function(opt_today) { |
| return opt_today ? opt_today.clone() : new goog.date.Date(); |
| }; |
| |
| |
| |
| /** |
| * Creates an iterator over the dates in a {@link goog.date.DateRange}. |
| * @constructor |
| * @extends {goog.iter.Iterator} |
| * @param {goog.date.DateRange} dateRange The date range to iterate. |
| * @final |
| */ |
| goog.date.DateRange.Iterator = function(dateRange) { |
| /** |
| * The next date. |
| * @type {goog.date.Date} |
| * @private |
| */ |
| this.nextDate_ = dateRange.getStartDate().clone(); |
| |
| /** |
| * The end date, expressed as an integer: YYYYMMDD. |
| * @type {number} |
| * @private |
| */ |
| this.endDate_ = Number(dateRange.getEndDate().toIsoString()); |
| }; |
| goog.inherits(goog.date.DateRange.Iterator, goog.iter.Iterator); |
| |
| |
| /** @override */ |
| goog.date.DateRange.Iterator.prototype.next = function() { |
| if (Number(this.nextDate_.toIsoString()) > this.endDate_) { |
| throw goog.iter.StopIteration; |
| } |
| |
| var rv = this.nextDate_.clone(); |
| this.nextDate_.add(new goog.date.Interval(goog.date.Interval.DAYS, 1)); |
| return rv; |
| }; |