Adam Shaw %!s(int64=7) %!d(string=hai) anos
pai
achega
7dd5157ccc

+ 3 - 3
plugins/gcal/GcalEventSource.ts

@@ -119,7 +119,7 @@ export default class GcalEventSource extends EventSource {
 
     // when timezone isn't known, we don't know what the UTC offset should be, so ask for +/- 1 day
     // from the UTC day-start to guarantee we're getting all the events
-    if (!dateEnv.canComputeTimeZoneOffset()) {
+    if (!dateEnv.canComputeOffset) {
       start = addDays(start, -1)
       end = addDays(end, 1)
     }
@@ -128,8 +128,8 @@ export default class GcalEventSource extends EventSource {
       this.ajaxSettings.data || {},
       {
         key: apiKey,
-        timeMin: dateEnv.toIso(start),
-        timeMax: dateEnv.toIso(end),
+        timeMin: dateEnv.formatIso(start),
+        timeMax: dateEnv.formatIso(end),
         singleEvents: true,
         maxResults: 9999
       }

+ 13 - 7
src/Calendar.ts

@@ -25,8 +25,9 @@ import EventDefMutation from './models/event/EventDefMutation'
 import EventSource from './models/event-source/EventSource'
 import { getThemeSystemClass } from './theme/ThemeRegistry'
 import { RangeInput, OptionsInput, EventObjectInput, EventSourceInput } from './types/input-types'
+import { getLocale } from './datelib/locale'
 import { DateEnv, DateInput } from './datelib/env'
-import { DateMarker } from './datelib/util'
+import { DateMarker, startOfDay } from './datelib/marker'
 import { Duration, createDuration } from './datelib/duration'
 
 export default class Calendar {
@@ -876,9 +877,9 @@ export default class Calendar {
       '?firstDay', '?weekNumberCalculation'
     ], (opts) => {
       this.dateEnv = new DateEnv({
-        calendarSystem: 'gregorian',
+        calendarSystem: 'gregory',
         timeZone: opts.timezone,
-        locale: opts.locale,
+        locale: getLocale(opts.locale),
         weekNumberCalculation: opts.weekNumberCalculation,
         firstDay: opts.firstDay
       })
@@ -890,7 +891,6 @@ export default class Calendar {
   Assumes the footprint is non-open-ended.
   */
   footprintToDateProfile(componentFootprint, ignoreEnd = false) {
-    const dateEnv = this.dateEnv
     let startMarker = componentFootprint.unzonedRange.start
     let endMarker
 
@@ -899,10 +899,10 @@ export default class Calendar {
     }
 
     if (componentFootprint.isAllDay) {
-      startMarker = dateEnv.startOfDay(startMarker)
+      startMarker = startOfDay(startMarker)
 
       if (endMarker) {
-        endMarker = dateEnv.startOfDay(endMarker)
+        endMarker = startOfDay(endMarker)
       }
     }
 
@@ -913,9 +913,15 @@ export default class Calendar {
   // Returns a DateMarker for the current date, as defined by the client's computer or from the `now` option
   getNow(): DateMarker {
     let now = this.opt('now')
+
     if (typeof now === 'function') {
       now = now()
     }
+
+    if (now == null) {
+      return this.dateEnv.createNowMarker()
+    }
+
     return this.dateEnv.createMarker(now)
   }
 
@@ -995,7 +1001,7 @@ export default class Calendar {
     let end = marker
 
     if (allDay) {
-      end = this.dateEnv.startOfDay(end)
+      end = startOfDay(end)
       end = this.dateEnv.add(end, this.defaultAllDayEventDuration)
     } else {
       end = this.dateEnv.add(end, this.defaultTimedEventDuration)

+ 9 - 9
src/DateProfileGenerator.ts

@@ -1,7 +1,7 @@
 import View from './View'
 import UnzonedRange from './models/UnzonedRange'
-import { Duration, createDuration, getWeeksFromInput, asRoughDays, computeGreatestUnit } from './datelib/duration'
-import { computeGreatestDurationDenominator, DateMarker, startOfDay, addDays } from './datelib/util'
+import { DateMarker, startOfDay, addDays } from './datelib/marker'
+import { Duration, createDuration, getWeeksFromInput, asRoughDays, greatestDurationDenominator } from './datelib/duration'
 
 
 export interface DateProfile {
@@ -184,10 +184,10 @@ export default class DateProfileGenerator {
       unit = 'day'
       unzonedRange = this.buildRangeFromDayCount(date, direction, dayCount)
     } else if ((unzonedRange = this.buildCustomVisibleRange(date))) {
-      unit = dateEnv.computeGreatestDenominator(unzonedRange.start, unzonedRange.end).unit
+      unit = dateEnv.greatestWholeUnit(unzonedRange.start, unzonedRange.end).unit
     } else {
       duration = this.getFallbackDuration()
-      unit = computeGreatestUnit(duration)
+      unit = greatestDurationDenominator(duration).unit
       unzonedRange = this.buildRangeFromDuration(date, direction, duration, unit)
     }
 
@@ -211,13 +211,13 @@ export default class DateProfileGenerator {
 
       // expand active range if minTime is negative (why not when positive?)
       if (asRoughDays(minTime) < 0) {
-        start = dateEnv.startOfDay(start) // necessary?
+        start = startOfDay(start) // necessary?
         start = dateEnv.add(start, minTime)
       }
 
       // expand active range if maxTime is beyond one day (why not when positive?)
       if (asRoughDays(maxTime) > 1) {
-        end = dateEnv.startOfDay(end) // necessary?
+        end = startOfDay(end) // necessary?
         end = addDays(end, -1)
         end = dateEnv.add(end, maxTime)
       }
@@ -228,7 +228,7 @@ export default class DateProfileGenerator {
 
 
   // Builds the "current" range when it is specified as an explicit duration.
-  // `unit` is the already-computed computeGreatestUnit value of duration.
+  // `unit` is the already-computed greatestDurationDenominator unit of duration.
   buildRangeFromDuration(date: DateMarker, direction, duration: Duration, unit) {
     const dateEnv = this._view.calendar.dateEnv
     let alignment = this.opt('dateAlignment')
@@ -247,9 +247,9 @@ export default class DateProfileGenerator {
 
         // use the smaller of the two units
         if (dateIncrementDuration < duration) {
-          alignment = computeGreatestDurationDenominator(
+          alignment = greatestDurationDenominator(
             dateIncrementDuration,
-            Boolean(getWeeksFromInput(dateIncrementInput))
+            !getWeeksFromInput(dateIncrementInput)
           ).unit
         } else {
           alignment = unit

+ 4 - 4
src/View.ts

@@ -9,10 +9,9 @@ import InteractiveDateComponent from './component/InteractiveDateComponent'
 import GlobalEmitter from './common/GlobalEmitter'
 import UnzonedRange from './models/UnzonedRange'
 import EventInstance from './models/event/EventInstance'
-import { DateMarker, addDays, addMs } from './datelib/util'
+import { DateMarker, addDays, addMs, diffDays } from './datelib/marker'
 import { createDuration } from './datelib/duration'
 import { createFormatter } from './datelib/formatting'
-import { diffDays } from './datelib/env'
 
 
 /* An abstract class from which other views inherit from
@@ -163,6 +162,7 @@ export default abstract class View extends InteractiveDateComponent {
 
   // Computes what the title at the top of the calendar should be for this view
   computeTitle(dateProfile) {
+    const dateEnv = this.calendar.dateEnv
     let unzonedRange
 
     // for views that span a large unit of time, show the proper interval, ignoring stray days before and after
@@ -182,11 +182,11 @@ export default abstract class View extends InteractiveDateComponent {
       )
     }
 
-    return this.calendar.dateEnv.toRangeFormat(
+    return dateEnv.formatRange(
       unzonedRange.start,
       unzonedRange.end,
       createFormatter(rawTitleFormat),
-      { isExclusive: dateProfile.isRangeAllDay }
+      { isEndExclusive: dateProfile.isRangeAllDay }
     )
   }
 

+ 4 - 4
src/ViewSpecManager.ts

@@ -1,8 +1,8 @@
 import { viewHash } from './ViewRegistry'
 import { mergeProps } from './util/object'
 import { mergeOptions, globalDefaults } from './options'
-import { Duration, createDuration, getWeeksFromInput } from './datelib/duration'
-import { computeGreatestDurationDenominator, unitsDesc } from './datelib/util'
+import { Duration, createDuration, getWeeksFromInput, greatestDurationDenominator } from './datelib/duration'
+import { unitsDesc } from './datelib/util'
 
 
 export default class ViewSpecManager {
@@ -112,9 +112,9 @@ export default class ViewSpecManager {
 
       if (duration) { // valid?
 
-        let denom = computeGreatestDurationDenominator(
+        let denom = greatestDurationDenominator(
           duration,
-          Boolean(getWeeksFromInput(durationInput))
+          !getWeeksFromInput(durationInput)
         )
 
         spec.duration = duration

+ 1 - 1
src/agenda/AgendaView.ts

@@ -389,7 +389,7 @@ agendaTimeGridMethods = {
     let weekText
 
     if (this.opt('weekNumbers')) {
-      weekText = dateEnv.formatWeek(weekStart, true)
+      weekText = dateEnv.formatWeek(weekStart, 'short')
 
       return '' +
         '<th class="fc-axis fc-week-number ' + calendar.theme.getClass('widgetHeader') + '" ' + view.axisStyleAttr() + '>' +

+ 6 - 6
src/agenda/TimeGrid.ts

@@ -10,8 +10,8 @@ import ComponentFootprint from '../models/ComponentFootprint'
 import TimeGridEventRenderer from './TimeGridEventRenderer'
 import TimeGridHelperRenderer from './TimeGridHelperRenderer'
 import TimeGridFillRenderer from './TimeGridFillRenderer'
-import { Duration, createDuration, addDurations, wholeDivideDurationByDuration, asRoughMs } from '../datelib/duration'
-import { startOfDay, DateMarker, addMs } from '../datelib/util'
+import { Duration, createDuration, addDurations, wholeDivideDurations, asRoughMs } from '../datelib/duration'
+import { startOfDay, DateMarker, addMs } from '../datelib/marker'
 import { createFormatter, DateFormatter } from '../datelib/formatting'
 
 /* A component that renders one or more columns of vertical time slots
@@ -179,7 +179,7 @@ export default class TimeGrid extends InteractiveDateComponent {
     // find the smallest stock label interval that results in more than one slots-per-label
     for (i = AGENDA_STOCK_SUB_DURATIONS.length - 1; i >= 0; i--) {
       labelInterval = createDuration(AGENDA_STOCK_SUB_DURATIONS[i])
-      slotsPerLabel = wholeDivideDurationByDuration(labelInterval, slotDuration)
+      slotsPerLabel = wholeDivideDurations(labelInterval, slotDuration)
       if (slotsPerLabel !== null && slotsPerLabel > 1) {
         return labelInterval
       }
@@ -257,20 +257,20 @@ export default class TimeGrid extends InteractiveDateComponent {
     // Calculate the time for each slot
     while (asRoughMs(slotTime) < asRoughMs(dateProfile.maxTime)) {
       slotDate = dateEnv.add(dayStart, slotTime)
-      isLabeled = wholeDivideDurationByDuration(slotIterator, this.labelInterval) !== null
+      isLabeled = wholeDivideDurations(slotIterator, this.labelInterval) !== null
 
       axisHtml =
         '<td class="fc-axis fc-time ' + theme.getClass('widgetContent') + '" ' + view.axisStyleAttr() + '>' +
           (isLabeled ?
             '<span>' + // for matchCellWidths
-              htmlEscape(dateEnv.toFormat(slotDate, this.labelFormat)) +
+              htmlEscape(dateEnv.format(slotDate, this.labelFormat)) +
             '</span>' :
             ''
             ) +
         '</td>'
 
       html +=
-        '<tr data-time="' + dateEnv.toFormat(slotDate, HMS_FORMAT) + '"' +
+        '<tr data-time="' + dateEnv.format(slotDate, HMS_FORMAT) + '"' +
           (isLabeled ? '' : ' class="fc-minor"') +
           '>' +
           (!isRTL ? axisHtml : '') +

+ 1 - 1
src/basic/BasicViewDateProfileGenerator.ts

@@ -1,6 +1,6 @@
 import UnzonedRange from '../models/UnzonedRange'
 import DateProfileGenerator from '../DateProfileGenerator'
-import { addWeeks } from '../datelib/util'
+import { addWeeks } from '../datelib/marker'
 
 
 export default class BasicViewDateProfileGenerator extends DateProfileGenerator {

+ 9 - 8
src/basic/DayGrid.ts

@@ -9,6 +9,7 @@ import {
   removeElement,
   ElementContent
 } from '../util/dom-manip'
+import View from '../View'
 import CoordCache from '../common/CoordCache'
 import Popover from '../common/Popover'
 import UnzonedRange from '../models/UnzonedRange'
@@ -21,7 +22,7 @@ import { default as DayTableMixin, DayTableInterface } from '../component/DayTab
 import DayGridEventRenderer from './DayGridEventRenderer'
 import DayGridHelperRenderer from './DayGridHelperRenderer'
 import DayGridFillRenderer from './DayGridFillRenderer'
-import { addDays } from '../datelib/util'
+import { addDays } from '../datelib/marker'
 import { createFormatter } from '../datelib/formatting'
 
 const DAY_NUM_FORMAT = createFormatter({ day: 'numeric' })
@@ -46,7 +47,7 @@ export default class DayGrid extends InteractiveDateComponent {
   bookendCells: DayTableInterface['bookendCells']
   breakOnWeeks: DayTableInterface['breakOnWeeks']
 
-  view: any // TODO: make more general and/or remove
+  view: View // TODO: make more general and/or remove
   helperRenderer: any
 
   cellWeekNumbersVisible: boolean = false // display week numbers in day cell?
@@ -240,7 +241,7 @@ export default class DayGrid extends InteractiveDateComponent {
     let isDateValid = this.dateProfile.activeUnzonedRange.containsDate(date) // TODO: called too frequently. cache somehow.
     let isDayNumberVisible = this.getIsDayNumbersVisible() && isDateValid
     let classes
-    let weekCalcFirstDoW
+    let weekCalcFirstDow
 
     if (!isDayNumberVisible && !this.cellWeekNumbersVisible) {
       // no numbers in day cell (week number must be along the side)
@@ -251,17 +252,17 @@ export default class DayGrid extends InteractiveDateComponent {
     classes.unshift('fc-day-top')
 
     if (this.cellWeekNumbersVisible) {
-      weekCalcFirstDoW = dateEnv.weekMeta.dow
+      weekCalcFirstDow = dateEnv.weekDow
     }
 
     html += '<td class="' + classes.join(' ') + '"' +
       (isDateValid ?
-        ' data-date="' + dateEnv.toIso(date, { omitTime: true }) + '"' :
+        ' data-date="' + dateEnv.formatIso(date, { omitTime: true }) + '"' :
         ''
         ) +
       '>'
 
-    if (this.cellWeekNumbersVisible && (date.day() === weekCalcFirstDoW)) {
+    if (this.cellWeekNumbersVisible && (date.day() === weekCalcFirstDow)) {
       html += view.buildGotoAnchorHtml(
         { date: date, type: 'week' },
         { 'class': 'fc-week-number' },
@@ -273,7 +274,7 @@ export default class DayGrid extends InteractiveDateComponent {
       html += view.buildGotoAnchorHtml(
         date,
         { 'class': 'fc-day-number' },
-        dateEnv.toFormat(date, DAY_NUM_FORMAT) // inner HTML
+        dateEnv.format(date, DAY_NUM_FORMAT) // inner HTML
       )
     }
 
@@ -698,7 +699,7 @@ export default class DayGrid extends InteractiveDateComponent {
     let view = this.view
     const dateEnv = view.calendar.dateEnv
     let theme = view.calendar.theme
-    let title = dateEnv.toFormat(
+    let title = dateEnv.format(
       this.getCellDate(row, col),
       createFormatter(this.opt('dayPopoverFormat')) // TODO: cache
     )

+ 1 - 1
src/basic/MonthView.ts

@@ -1,7 +1,7 @@
 import { distributeHeight } from '../util/misc'
 import BasicView from './BasicView'
 import MonthViewDateProfileGenerator from './MonthViewDateProfileGenerator'
-import { DateMarker } from '../datelib/util'
+import { DateMarker } from '../datelib/marker'
 
 
 /* A month view with day cells running in rows (one-per-week) and columns

+ 1 - 2
src/basic/MonthViewDateProfileGenerator.ts

@@ -1,7 +1,6 @@
 import BasicViewDateProfileGenerator from './BasicViewDateProfileGenerator'
 import UnzonedRange from '../models/UnzonedRange'
-import { diffWeeks } from '../datelib/env'
-import { addWeeks } from '../datelib/util'
+import { addWeeks, diffWeeks } from '../datelib/marker'
 
 
 export default class MonthViewDateProfileGenerator extends BasicViewDateProfileGenerator {

+ 10 - 9
src/component/DateComponent.ts

@@ -1,10 +1,12 @@
 import { attrsToStr, htmlEscape } from '../util/html'
 import Component from './Component'
+import Calendar from '../Calendar'
+import View from '../View'
 import { eventRangeToEventFootprint } from '../models/event/util'
 import EventFootprint from '../models/event/EventFootprint'
 import { DateProfile } from '../DateProfileGenerator'
-import { addDays, DateMarker, startOfDay, dayIDs } from '../datelib/util'
-import { diffDays } from '../datelib/env'
+import { DateMarker, addDays, startOfDay, diffDays, diffWholeDays } from '../datelib/marker'
+import { dayIDs } from '../datelib/util'
 import { Duration, createDuration, asRoughMs } from '../datelib/duration'
 
 
@@ -655,13 +657,13 @@ export default abstract class DateComponent extends Component {
   }
 
 
-  _getCalendar() { // TODO: strip out. move to generic parent.
+  _getCalendar(): Calendar { // TODO: strip out. move to generic parent.
     let t = (this as any)
     return t.calendar || t.view.calendar
   }
 
 
-  _getView() { // TODO: strip out. move to generic parent.
+  _getView(): View { // TODO: strip out. move to generic parent.
     return (this as any).view
   }
 
@@ -694,7 +696,7 @@ export default abstract class DateComponent extends Component {
     date = dateEnv.createMarker(date) // if a string, parse it
 
     finalOptions = { // for serialization into the link
-      date: dateEnv.toIso(date, { omitTime: true }),
+      date: dateEnv.formatIso(date, { omitTime: true }),
       type: type || 'day'
     }
 
@@ -774,7 +776,7 @@ export default abstract class DateComponent extends Component {
     } else if (unit === 'week') {
       res = dateEnv.diffWholeMonths(range.start, range.end)
     } else if (unit === 'day') {
-      res = dateEnv.diffWholeDays(range.start, range.end)
+      res = diffWholeDays(range.start, range.end)
     }
 
     return res || 0
@@ -784,10 +786,9 @@ export default abstract class DateComponent extends Component {
   // Returns the date range of the full days the given range visually appears to occupy.
   // Returns a plain object with start/end, NOT an UnzonedRange!
   computeDayRange(unzonedRange): { start: DateMarker, end: DateMarker } {
-    const dateEnv = this._getCalendar().dateEnv
-    let startDay: DateMarker = dateEnv.startOfDay(unzonedRange.start) // the beginning of the day the range starts
+    let startDay: DateMarker = startOfDay(unzonedRange.start) // the beginning of the day the range starts
     let end: DateMarker = unzonedRange.end
-    let endDay: DateMarker = dateEnv.startOfDay(end)
+    let endDay: DateMarker = startOfDay(end)
     let endTimeMS: number = end.valueOf() - endDay.valueOf() // # of milliseconds into `endDay`
 
     // If the end time is actually inclusively part of the next day and is equal to or

+ 5 - 5
src/component/DayTableMixin.ts

@@ -1,8 +1,8 @@
 import { htmlEscape } from '../util/html'
 import { prependToElement, appendToElement } from '../util/dom-manip'
 import Mixin from '../common/Mixin'
-import { DateMarker, addDays, dayIDs } from '../datelib/util'
-import { diffDays } from '../datelib/env'
+import { DateMarker, addDays, diffDays } from '../datelib/marker'
+import { dayIDs } from '../datelib/util'
 import { createFormatter } from '../datelib/formatting'
 
 export interface DayTableInterface {
@@ -334,7 +334,7 @@ export default class DayTableMixin extends Mixin implements DayTableInterface {
         t.opt('columnHeaderText')(date)
       )
     } else {
-      innerHtml = htmlEscape(dateEnv.toFormat(date, t.colHeadFormat))
+      innerHtml = htmlEscape(dateEnv.format(date, t.colHeadFormat))
     }
 
     // if only one row of days, the classNames on the header can represent the specific days beneath
@@ -351,7 +351,7 @@ export default class DayTableMixin extends Mixin implements DayTableInterface {
     return '' +
       '<th class="' + classNames.join(' ') + '"' +
         ((isDateValid && t.rowCnt) === 1 ?
-          ' data-date="' + dateEnv.toIso(date, { omitTime: true }) + '"' :
+          ' data-date="' + dateEnv.formatIso(date, { omitTime: true }) + '"' :
           '') +
         (colspan > 1 ?
           ' colspan="' + colspan + '"' :
@@ -417,7 +417,7 @@ export default class DayTableMixin extends Mixin implements DayTableInterface {
 
     return '<td class="' + classes.join(' ') + '"' +
       (isDateValid ?
-        ' data-date="' + dateEnv.toIso(date, { omitTime: true }) + '"' : // if date has a time, won't format it
+        ' data-date="' + dateEnv.formatIso(date, { omitTime: true }) + '"' : // if date has a time, won't format it
         '') +
       (otherAttrs ?
         ' ' + otherAttrs :

+ 3 - 2
src/component/InteractiveDateComponent.ts

@@ -2,6 +2,7 @@ import { elementClosest } from '../util/dom-manip'
 import { getEvIsTouch, listenBySelector, listenToHoverBySelector } from '../util/dom-event'
 import DateComponent from './DateComponent'
 import GlobalEmitter from '../common/GlobalEmitter'
+import { diffDayAndTime } from '../datelib/marker'
 import { Duration, createDuration } from '../datelib/duration'
 
 
@@ -165,7 +166,7 @@ export default abstract class InteractiveDateComponent extends DateComponent {
     // the touchend never fires because the elements gets removed mid-touch-interaction (my theory).
     // HACK: simply don't allow this to happen.
     // ALSO: prevent selection when an *event* is already raised.
-    return view.isSelected || view.selectedEvent
+    return view.isSelected || Boolean(view.selectedEventInstance)
   }
 
 
@@ -326,7 +327,7 @@ export default abstract class InteractiveDateComponent extends DateComponent {
     const dateEnv = this._getCalendar().dateEnv
 
     if (!this.largeUnit) {
-      return dateEnv.diffDayAndTime(a, b) // returns a duration
+      return diffDayAndTime(a, b) // returns a duration
     } else if (this.largeUnit === 'year') {
       return createDuration(dateEnv.diffWholeYears(a, b), 'year')
     } else if (this.largeUnit === 'month') {

+ 2 - 1
src/component/interactions/EventDragging.ts

@@ -5,6 +5,7 @@ import DragListener from '../../common/DragListener'
 import HitDragListener from '../../common/HitDragListener'
 import MouseFollower from '../../common/MouseFollower'
 import Interaction from './Interaction'
+import { startOfDay } from '../../datelib/marker'
 
 
 export default class EventDragging extends Interaction {
@@ -313,7 +314,7 @@ export default class EventDragging extends Interaction {
 
       if (endFootprint.isAllDay) {
         forceAllDay = true
-        date0 = this.view.calendar.dateEnv.startOfDay(date0)
+        date0 = startOfDay(date0)
       } else {
         forceTimed = true
       }

+ 1 - 1
src/component/interactions/ExternalDropping.ts

@@ -6,7 +6,7 @@ import SingleEventDef from '../../models/event/SingleEventDef'
 import EventInstanceGroup from '../../models/event/EventInstanceGroup'
 import EventSource from '../../models/event-source/EventSource'
 import Interaction from './Interaction'
-import { startOfDay } from '../../datelib/util'
+import { startOfDay } from '../../datelib/marker'
 import { createDuration } from '../../datelib/duration'
 
 

+ 3 - 3
src/component/renderers/EventRenderer.ts

@@ -1,5 +1,5 @@
 import View from '../../View'
-import { DateMarker } from '../../datelib/util'
+import { DateMarker } from '../../datelib/marker'
 import { createFormatter, DateFormatter } from '../../datelib/formatting'
 import { htmlToElements } from '../../util/dom-manip'
 import { compareByFieldSpecs } from '../../util/misc'
@@ -306,12 +306,12 @@ export default class EventRenderer {
 
     if (this.displayEventTime && !isAllDay) {
       if (displayEnd && end) {
-        return dateEnv.toRangeFormat(start, end, formatter, {
+        return dateEnv.formatRange(start, end, formatter, {
           forcedStartTimeZoneOffset,
           forcedEndTimeZoneOffset
         })
       } else {
-        return dateEnv.toFormat(start, formatter, {
+        return dateEnv.format(start, formatter, {
           forcedTimeZoneOffset: forcedStartTimeZoneOffset
         })
       }

+ 4 - 1
src/datelib/duration.ts

@@ -194,7 +194,7 @@ export function wholeDivideDurations(numerator: Duration, denominator: Duration)
   return res0
 }
 
-export function greatestDurationDenominator(dur: Duration, considerWeeks: boolean = false) {
+export function greatestDurationDenominator(dur: Duration, dontReturnWeeks?: boolean) {
   let time = dur.time
   if (time) {
     if (time % 1000 !== 0) {
@@ -211,6 +211,9 @@ export function greatestDurationDenominator(dur: Duration, considerWeeks: boolea
     }
   }
   if (dur.day) {
+    if (!dontReturnWeeks && dur.day % 7 === 0) {
+      return { unit: 'week', value: dur.day / 7 }
+    }
     return { unit: 'day', value: dur.day }
   }
   if (dur.month) {

+ 3 - 3
src/datelib/env.ts

@@ -346,13 +346,13 @@ export class DateEnv {
     )
   }
 
-  formatWeek(marker: DateMarker, fit?: 'numeric' | 'narrow' | 'short'): string {
+  formatWeek(marker: DateMarker, display?: 'numeric' | 'narrow' | 'short'): string {
     let { locale } = this
     let parts = []
 
-    if (fit === 'narrow') {
+    if (display === 'narrow') {
       parts.push(locale.options.weekHeader)
-    } else if (fit === 'short') {
+    } else if (display === 'short') {
       parts.push(locale.options.weekHeader, ' ')
     }
     // otherwise, considered 'numeric'

+ 1 - 1
src/datelib/formatting-native.ts

@@ -76,7 +76,7 @@ function separateExtendedSettings(settings) {
 // General Formatting Utils
 
 function formatZonedMarker(date: ZonedMarker, context: DateFormattingContext, standardSettings) {
-  let s = date.marker.toLocaleString(context.locale, standardSettings)
+  let s = date.marker.toLocaleString(context.locale.query, standardSettings)
 
   if (standardSettings.timeZoneName && date.timeZoneOffset != null && context.timeZone !== 'UTC') {
     s = s.replace(/UTC|GMT/, formatTimeZoneOffset(date.timeZoneOffset))

+ 11 - 7
src/datelib/locale.ts

@@ -1,8 +1,9 @@
 import { mergeProps } from '../util/object'
 
-export type LocaleQuery = string | string[]
+export type LocaleQuery = string | string[] | null
 
 export interface Locale {
+  query: LocaleQuery
   ids: string[]
   week: { dow: number, doy: number }
   simpleNumberFormat: Intl.NumberFormat
@@ -36,13 +37,15 @@ const RAW_EN_LOCALE = {
 let rawMap = {}
 
 export function getLocale(query: LocaleQuery): Locale {
-  let nativeQuery = query === 'auto' ? null : query // for instantiating Intl objects
+  if (query === 'auto') {
+    query = null
+  }
 
   let ids
-  if (Array.isArray(nativeQuery)) {
-    ids = nativeQuery
-  } else if (typeof nativeQuery === 'string') {
-    ids = [ nativeQuery ]
+  if (Array.isArray(query)) {
+    ids = query
+  } else if (typeof query === 'string') {
+    ids = [ query ]
   } else {
     ids = []
   }
@@ -54,9 +57,10 @@ export function getLocale(query: LocaleQuery): Locale {
   delete merged.week
 
   return {
+    query,
     ids,
     week,
-    simpleNumberFormat: new Intl.NumberFormat(nativeQuery),
+    simpleNumberFormat: new Intl.NumberFormat(query),
     options: merged
   }
 }

+ 6 - 4
src/exports.ts

@@ -122,9 +122,11 @@ export { default as BasicView } from './basic/BasicView'
 export { default as MonthView } from './basic/MonthView'
 export { default as ListView } from './list/ListView'
 
-export { DateMarker, addDays, startOfDay, addMs } from './datelib/util'
-export { DateEnv } from './datelib/env'
+export { DateMarker, addDays, startOfDay, addMs } from './datelib/marker'
 export {
-  wholeDivideDurationByDuration, isSingleDay, createDuration, multiplyDuration,
-  asRoughMinutes, asRoughSeconds
+  Duration, createDuration,
+  isSingleDay, multiplyDuration,
+  asRoughMinutes, asRoughSeconds,
+  wholeDivideDurations, greatestDurationDenominator
 } from './datelib/duration'
+export { DateEnv } from './datelib/env'

+ 5 - 6
src/list/ListView.ts

@@ -6,7 +6,7 @@ import View from '../View'
 import Scroller from '../common/Scroller'
 import ListEventRenderer from './ListEventRenderer'
 import ListEventPointing from './ListEventPointing'
-import { addDays, DateMarker } from '../datelib/util'
+import { DateMarker, addDays, startOfDay } from '../datelib/marker'
 import { createFormatter } from '../datelib/formatting'
 
 /*
@@ -75,8 +75,7 @@ export default class ListView extends View {
 
 
   renderDates(dateProfile) {
-    let calendar = this.calendar
-    let dayStart = calendar.dateEnv.startOfDay(dateProfile.renderUnzonedRange.start)
+    let dayStart = startOfDay(dateProfile.renderUnzonedRange.start)
     let viewEnd = dateProfile.renderUnzonedRange.end
     let dayDates = []
     let dayRanges = []
@@ -211,7 +210,7 @@ export default class ListView extends View {
 
     return createElement('tr', {
       className: 'fc-list-heading',
-      'data-date': dateEnv.toIso(dayDate, { omitTime: true })
+      'data-date': dateEnv.formatIso(dayDate, { omitTime: true })
     }, '<td class="' + (
       this.calendar.theme.getClass('tableListHeading') ||
       this.calendar.theme.getClass('widgetHeader')
@@ -220,14 +219,14 @@ export default class ListView extends View {
         this.buildGotoAnchorHtml(
           dayDate,
           { 'class': 'fc-list-heading-main' },
-          htmlEscape(dateEnv.toFormat(dayDate, mainFormat)) // inner HTML
+          htmlEscape(dateEnv.format(dayDate, mainFormat)) // inner HTML
         ) :
         '') +
       (altFormat ?
         this.buildGotoAnchorHtml(
           dayDate,
           { 'class': 'fc-list-heading-alt' },
-          htmlEscape(dateEnv.toFormat(dayDate, altFormat)) // inner HTML
+          htmlEscape(dateEnv.format(dayDate, altFormat)) // inner HTML
         ) :
         '') +
     '</td>') as HTMLTableRowElement

+ 1 - 3
src/list/config.ts

@@ -5,9 +5,7 @@ defineView('list', {
   'class': ListView,
   buttonTextKey: 'list', // what to lookup in locale files
   defaults: {
-    buttonText: 'list', // text to display for English
-    listDayFormat: { month: 'long', day: 'numeric', year: 'numeric' }, // like "January 1, 2016"
-    noEventsMessage: 'No events to display'
+    listDayFormat: { month: 'long', day: 'numeric', year: 'numeric' } // like "January 1, 2016"
   }
 })
 

+ 1 - 1
src/models/EventPeriod.ts

@@ -4,7 +4,7 @@ import { default as EmitterMixin, EmitterInterface } from '../common/EmitterMixi
 import UnzonedRange from './UnzonedRange'
 import EventInstanceGroup from './event/EventInstanceGroup'
 import { DateEnv } from '../datelib/env'
-import { DateMarker } from '../datelib/util'
+import { DateMarker } from '../datelib/marker'
 
 export default class EventPeriod {
 

+ 1 - 1
src/models/UnzonedRange.ts

@@ -1,4 +1,4 @@
-import { DateMarker } from '../datelib/util'
+import { DateMarker } from '../datelib/marker'
 
 export default class UnzonedRange {
 

+ 1 - 1
src/models/event-source/EventSource.ts

@@ -5,7 +5,7 @@ import {
 import Class from '../../common/Class'
 import Calendar from '../../Calendar'
 import EventDefParser from '../event/EventDefParser'
-import { DateMarker } from '../../datelib/util'
+import { DateMarker } from '../../datelib/marker'
 import { DateEnv } from '../../datelib/env'
 
 

+ 1 - 1
src/models/event-source/FuncEventSource.ts

@@ -1,6 +1,6 @@
 import { unpromisify } from '../../util/promise'
 import EventSource from './EventSource'
-import { DateMarker } from '../../datelib/util'
+import { DateMarker } from '../../datelib/marker'
 import { DateEnv } from '../../datelib/env'
 
 export default class FuncEventSource extends EventSource {

+ 3 - 3
src/models/event-source/JsonFeedEventSource.ts

@@ -2,7 +2,7 @@ import * as request from 'superagent'
 import { assignTo } from '../../util/object'
 import { applyAll } from '../../util/misc'
 import EventSource from './EventSource'
-import { DateMarker } from '../../datelib/util'
+import { DateMarker } from '../../datelib/marker'
 import { DateEnv } from '../../datelib/env'
 
 
@@ -112,8 +112,8 @@ export default class JsonFeedEventSource extends EventSource {
 
     assignTo(params, customRequestParams)
 
-    params[startParam] = dateEnv.toIso(start)
-    params[endParam] = dateEnv.toIso(end)
+    params[startParam] = dateEnv.formatIso(start)
+    params[endParam] = dateEnv.formatIso(end)
 
     if (dateEnv.timeZone !== 'local') {
       params[timezoneParam] = dateEnv.timeZone

+ 4 - 4
src/models/event/EventDateProfile.ts

@@ -1,6 +1,6 @@
 import UnzonedRange from '../UnzonedRange'
 import Calendar from '../../Calendar'
-import { DateMarker } from '../../datelib/util'
+import { DateMarker, startOfDay } from '../../datelib/marker'
 
 /*
 Meant to be immutable
@@ -37,7 +37,7 @@ export default class EventDateProfile {
       return false
     }
 
-    let calendar = source.calendar
+    let calendar: Calendar = source.calendar
     let startMeta = calendar.dateEnv.createMarkerMeta(startInput)
     let startMarker = startMeta.marker
     let endMeta = endInput ? calendar.dateEnv.createMarkerMeta(endInput) : null
@@ -57,10 +57,10 @@ export default class EventDateProfile {
     }
 
     if (forcedAllDay === true) {
-      startMarker = calendar.dateEnv.startOfDay(startMarker)
+      startMarker = startOfDay(startMarker)
 
       if (endMarker) {
-        endMarker = calendar.dateEnv.startOfDay(endMarker)
+        endMarker = startOfDay(endMarker)
       }
     }
 

+ 9 - 7
src/models/event/EventDefDateMutation.ts

@@ -1,5 +1,7 @@
+import Calendar from '../../Calendar'
 import EventDateProfile from './EventDateProfile'
-import { diffDurations, Duration } from '../../datelib/duration'
+import { startOfDay, diffWholeDays, diffDayAndTime } from '../../datelib/marker'
+import { Duration, diffDurations } from '../../datelib/duration'
 
 export default class EventDefDateMutation {
 
@@ -14,7 +16,7 @@ export default class EventDefDateMutation {
   endDelta: Duration
 
 
-  static createFromDiff(dateProfile0, dateProfile1, largeUnit, calendar) {
+  static createFromDiff(dateProfile0, dateProfile1, largeUnit, calendar: Calendar) {
     const dateEnv = calendar.dateEnv
     let clearEnd = dateProfile0.end && !dateProfile1.end
     let forceTimed = dateProfile0.isAllDay && !dateProfile1.isAllDay
@@ -31,9 +33,9 @@ export default class EventDefDateMutation {
       } else if (largeUnit === 'month') {
         return dateEnv.diffWholeMonths(date0, date1)
       } else if (dateProfile1.isAllDay) {
-        return dateEnv.diffWholeDays(date0, date1)
+        return diffWholeDays(date0, date1)
       } else {
-        return dateEnv.diffDayAndTime(date0, date1)
+        return diffDayAndTime(date0, date1)
       }
     }
 
@@ -62,7 +64,7 @@ export default class EventDefDateMutation {
   /*
   returns an undo function.
   */
-  buildNewDateProfile(eventDateProfile, calendar) {
+  buildNewDateProfile(eventDateProfile, calendar: Calendar) {
     const dateEnv = calendar.dateEnv
     let isAllDay = eventDateProfile.isAllDay
     let startMarker = eventDateProfile.unzonedRange.start
@@ -81,10 +83,10 @@ export default class EventDefDateMutation {
     }
 
     if (this.forceAllDay) {
-      startMarker = dateEnv.startOfDay(startMarker)
+      startMarker = startOfDay(startMarker)
 
       if (endMarker) {
-        endMarker = dateEnv.startOfDay(endMarker)
+        endMarker = startOfDay(endMarker)
       }
     }
 

+ 2 - 2
src/models/event/RecurringEventDef.ts

@@ -3,7 +3,7 @@ import EventDef from './EventDef'
 import EventInstance from './EventInstance'
 import EventDateProfile from './EventDateProfile'
 import { createDuration, Duration } from '../../datelib/duration'
-import { DateMarker } from '../../datelib/util'
+import { DateMarker, startOfDay } from '../../datelib/marker'
 
 const ONE_DAY = createDuration({ days: 1 })
 
@@ -22,7 +22,7 @@ export default class RecurringEventDef extends EventDef {
   buildInstances(unzonedRange) {
     let calendar = this.source.calendar
     const dateEnv = calendar.dateEnv
-    let dateMarker: DateMarker = dateEnv.startOfDay(unzonedRange.start)
+    let dateMarker: DateMarker = startOfDay(unzonedRange.start)
     let endMarker: DateMarker = unzonedRange.end
     let instanceStart: DateMarker
     let instanceEnd: DateMarker

+ 1 - 15
src/options.ts

@@ -45,23 +45,10 @@ export const globalDefaults = {
   // allDayDefault: undefined,
 
   // locale
-  locale: null,
+  locale: 'en',
   isRTL: false,
-  buttonText: {
-    prev: 'prev',
-    next: 'next',
-    prevYear: 'prev year',
-    nextYear: 'next year',
-    year: 'year', // TODO: locale files need to specify this
-    today: 'today',
-    month: 'month',
-    week: 'week',
-    day: 'day'
-  },
   // buttonIcons: null,
 
-  allDayText: 'all-day',
-
   // allows setting a min-height to the event segment to prevent short events overlapping each other
   agendaEventMinHeight: 0,
 
@@ -84,7 +71,6 @@ export const globalDefaults = {
   // eventRenderWait: null,
 
   eventLimit: false,
-  eventLimitText: 'more',
   eventLimitClick: 'popover',
   dayPopoverFormat: { month: 'long', day: 'numeric', year: 'numeric' },
 

+ 1 - 1
src/util/object.ts

@@ -42,7 +42,7 @@ function hasOwnProp(obj, name) {
 
 // Merges an array of objects into a single object.
 // The second argument allows for an array of property names who's object values will be merged together.
-export function mergeProps(propObjs, complexProps?) {
+export function mergeProps(propObjs, complexProps?): any {
   let dest = {}
   let i
   let name

+ 8 - 8
tests/automated/datelib/main.js

@@ -158,7 +158,7 @@ describe('datelib', function() {
 
     it('outputs ISO8601 formatting', function() {
       var marker = env.createMarker('2018-06-08T00:00:00')
-      var s = env.toIso(marker)
+      var s = env.formatIso(marker)
       expect(s).toBe('2018-06-08T00:00:00Z')
     })
 
@@ -171,7 +171,7 @@ describe('datelib', function() {
         year: 'numeric',
         timeZoneName: 'short'
       })
-      var s = env.toFormat(marker, formatter)
+      var s = env.format(marker, formatter)
       expect(s).toBe('Friday, June 8, 2018, UTC')
     })
 
@@ -186,21 +186,21 @@ describe('datelib', function() {
       it('works with different days of same month', function() {
         var m0 = env.createMarker('2018-06-08')
         var m1 = env.createMarker('2018-06-09')
-        var s = env.toRangeFormat(m0, m1, formatter)
+        var s = env.formatRange(m0, m1, formatter)
         expect(s).toBe('June 8 - 9, 2018')
       })
 
       it('works with different day/month of same year', function() {
         var m0 = env.createMarker('2018-06-08')
         var m1 = env.createMarker('2018-07-09')
-        var s = env.toRangeFormat(m0, m1, formatter)
+        var s = env.formatRange(m0, m1, formatter)
         expect(s).toBe('June 8 - July 9, 2018')
       })
 
       it('works with completely different dates', function() {
         var m0 = env.createMarker('2018-06-08')
         var m1 = env.createMarker('2020-07-09')
-        var s = env.toRangeFormat(m0, m1, formatter)
+        var s = env.formatRange(m0, m1, formatter)
         expect(s).toBe('June 8, 2018 - July 9, 2020')
       })
 
@@ -482,7 +482,7 @@ describe('datelib', function() {
 
     it('outputs ISO8601 formatting', function() {
       var marker = env.createMarker('2018-06-08T00:00:00')
-      var s = env.toIso(marker)
+      var s = env.formatIso(marker)
       var realTzo = getFormattedTimzoneOffset(new Date(2018, 5, 8))
       expect(s).toBe('2018-06-08T00:00:00' + realTzo)
     })
@@ -496,7 +496,7 @@ describe('datelib', function() {
         year: 'numeric',
         timeZoneName: 'short'
       })
-      var s = env.toFormat(marker, formatter)
+      var s = env.format(marker, formatter)
       expect(s).toBe('Friday, June 8, 2018, ' + getFormattedTimzoneOffset2(new Date(2018, 5, 8)))
     })
 
@@ -550,7 +550,7 @@ describe('datelib', function() {
         year: 'numeric',
         timeZoneName: 'short'
       })
-      var s = env.toFormat(marker, formatter)
+      var s = env.format(marker, formatter)
       expect(s).toBe('Friday, June 8, 2018')
     })