Adam Shaw 7 лет назад
Родитель
Сommit
122085ebbc

+ 0 - 6
src/Calendar.ts

@@ -325,12 +325,6 @@ export default class Calendar {
   }
 
 
-  formatWeek(d: Date, display?: string) {
-    const { dateEnv } = this
-    return dateEnv.formatWeek(dateEnv.createMarker(d), display as any)
-  }
-
-
   // Loading Triggering
   // -----------------------------------------------------------------------------------------------------------------
 

+ 3 - 1
src/agenda/AgendaView.ts

@@ -12,8 +12,10 @@ import View from '../View'
 import TimeGrid from './TimeGrid'
 import DayGrid from '../basic/DayGrid'
 import { createDuration } from '../datelib/duration'
+import { createFormatter } from '../datelib/formatting'
 
 const AGENDA_ALL_DAY_EVENT_LIMIT = 5
+const WEEK_HEADER_FORMAT = createFormatter({ week: 'short' })
 
 let agendaTimeGridMethods
 let agendaDayGridMethods
@@ -389,7 +391,7 @@ agendaTimeGridMethods = {
     let weekText
 
     if (this.opt('weekNumbers')) {
-      weekText = dateEnv.formatWeek(weekStart, 'short')
+      weekText = dateEnv.format(weekStart, WEEK_HEADER_FORMAT)
 
       return '' +
         '<th class="fc-axis fc-week-number ' + calendar.theme.getClass('widgetHeader') + '" ' + view.axisStyleAttr() + '>' +

+ 4 - 1
src/basic/BasicView.ts

@@ -8,11 +8,14 @@ import {
   distributeHeight,
   undistributeHeight
 } from '../util/misc'
+import { createFormatter } from '../datelib/formatting'
 import Scroller from '../common/Scroller'
 import View from '../View'
 import BasicViewDateProfileGenerator from './BasicViewDateProfileGenerator'
 import DayGrid from './DayGrid'
 
+const WEEK_NUM_FORMAT = createFormatter({ week: 'numeric' })
+
 
 /* An abstract class for the "basic" views, as well as month view. Renders one or more rows of day cells.
 ----------------------------------------------------------------------------------------------------------------------*/
@@ -300,7 +303,7 @@ function makeDayGridSubclass(SuperClass) {
           '<td class="fc-week-number" ' + view.weekNumberStyleAttr() + '>' +
             view.buildGotoAnchorHtml( // aside from link, important for matchCellWidths
               { date: weekStart, type: 'week', forceOff: this.colCnt === 1 },
-              dateEnv.formatWeek(weekStart) // inner HTML
+              dateEnv.format(weekStart, WEEK_NUM_FORMAT) // inner HTML
             ) +
           '</td>'
       }

+ 2 - 1
src/basic/DayGrid.ts

@@ -26,6 +26,7 @@ import { addDays } from '../datelib/marker'
 import { createFormatter } from '../datelib/formatting'
 
 const DAY_NUM_FORMAT = createFormatter({ day: 'numeric' })
+const WEEK_NUM_FORMAT = createFormatter({ week: 'numeric' })
 
 
 /* A component that renders a grid of whole-days that runs horizontally. There can be multiple rows, one per week.
@@ -267,7 +268,7 @@ export default class DayGrid extends InteractiveDateComponent {
       html += view.buildGotoAnchorHtml(
         { date: date, type: 'week' },
         { 'class': 'fc-week-number' },
-        dateEnv.formatWeek(date) // inner HTML
+        dateEnv.format(date, WEEK_NUM_FORMAT) // inner HTML
       )
     }
 

+ 0 - 22
src/datelib/env.ts

@@ -305,7 +305,6 @@ export class DateEnv {
   }
 
   // TODO: choke on timeZoneName: long
-  // TODO: accept just { timeZoneName: 'short' } and do the right thing
   format(marker: DateMarker, formatter: DateFormatter, dateOptions: any = {}) {
     return formatter.format(
       {
@@ -351,27 +350,6 @@ export class DateEnv {
     )
   }
 
-  // TODO: somehow roll this into format() ?
-  formatWeek(marker: DateMarker, display?: 'numeric' | 'narrow' | 'short'): string {
-    let { locale } = this
-    let parts = []
-
-    if (display === 'narrow') {
-      parts.push(locale.options.weekHeader)
-    } else if (display === 'short') {
-      parts.push(locale.options.weekHeader, ' ')
-    }
-    // otherwise, considered 'numeric'
-
-    parts.push(this.computeWeekNumber(marker))
-
-    if (locale.options.isRTL) {
-      parts.reverse()
-    }
-
-    return parts.join('')
-  }
-
 
   // TimeZone
 

+ 96 - 31
src/datelib/formatting-native.ts

@@ -1,25 +1,98 @@
+import { assignTo } from '../util/object'
 import { DateMarker, timeAsMs } from './marker'
 import { CalendarSystem } from './calendar-system'
+import { Locale } from './locale'
 import { DateFormatter, DateFormattingContext, ZonedMarker, formatTimeZoneOffset } from './formatting'
 
 
+const STANDARD_DATE_PROP_RE = /^(weekday|era|year|month|day|hour|minute|second|timeZoneName)$/
 const DEFAULT_SEPARATOR = ' - '
+const EXTENDED_SETTINGS = {
+  separator: null,
+  fake: function(s) {
+    return s.toLowerCase() + ' --- test'
+  }
+}
 
 
 export class NativeFormatter implements DateFormatter {
 
   standardSettings: any
   extendedSettings: any
+  transformations: any
+  datePropCnt: number
 
   constructor(formatSettings) {
-    let groups = separateExtendedSettings(formatSettings)
-    this.standardSettings = groups.standard
-    this.standardSettings.timeZone = 'UTC'
-    this.extendedSettings = groups.extended
+    let standardSettings: any = {}
+    let extendedSettings: any = {}
+    let transformations = []
+    let datePropCnt = 0
+
+    for (let name in formatSettings) {
+      if (typeof EXTENDED_SETTINGS[name] === 'function') {
+        transformations.push(formatSettings[name])
+      } else if (EXTENDED_SETTINGS[name]) {
+        extendedSettings[name] = formatSettings[name]
+      } else {
+        standardSettings[name] = formatSettings[name]
+
+        if (STANDARD_DATE_PROP_RE.test(name)) {
+          datePropCnt++
+        }
+      }
+    }
+
+    standardSettings.timeZone = 'UTC'
+
+    this.standardSettings = standardSettings
+    this.extendedSettings = extendedSettings
+    this.transformations = transformations
+    this.datePropCnt = datePropCnt
   }
 
-  format(date: ZonedMarker, context: DateFormattingContext) {
-    return formatZonedMarker(date, context, this.standardSettings)
+  format(date: ZonedMarker, context: DateFormattingContext, standardOverrides?) {
+    let standardSettings = standardOverrides || this.standardSettings
+    let { extendedSettings, transformations } = this
+
+    if (this.datePropCnt === 1) {
+      if (standardSettings.timeZoneName === 'short') {
+        return formatTimeZoneOffset(date.timeZoneOffset)
+      }
+      if (extendedSettings.week) {
+        return formatWeekNumber(
+          context.computeWeekNumber(date.marker),
+          context.locale,
+          extendedSettings.week
+        )
+      }
+    }
+
+    // if trying to display a timezone but don't have enough information, don't try
+    if (
+      context.timeZone !== 'UTC' && (
+        standardSettings.timeZoneName === 'long' ||
+        standardSettings.timeZoneName === 'short' && date.timeZoneOffset == null
+      )
+    ) {
+      standardSettings = assignTo({}, standardSettings) // copy
+      delete standardSettings.timeZoneName
+    }
+
+    let s = date.marker.toLocaleString(context.locale.codeArg, standardSettings)
+
+    if (
+      context.timeZone !== 'UTC' && // the current timezone is something other than UTC
+      standardSettings.timeZoneName === 'short' // and want to display the timezone offset
+    ) {
+      // then inject the timezone offset into the string
+      s = s.replace(/UTC|GMT/, formatTimeZoneOffset(date.timeZoneOffset))
+    }
+
+    transformations.forEach(function(transformation) {
+      s = transformation(s)
+    })
+
+    return s
   }
 
   formatRange(start: ZonedMarker, end: ZonedMarker, context: DateFormattingContext) {
@@ -27,7 +100,7 @@ export class NativeFormatter implements DateFormatter {
 
     let diffSeverity = computeMarkerDiffSeverity(start.marker, end.marker, context.calendarSystem)
     if (!diffSeverity) {
-      return formatZonedMarker(start, context, standardSettings)
+      return this.format(start, context)
     }
 
     let biggestUnitForPartial = diffSeverity
@@ -40,16 +113,16 @@ export class NativeFormatter implements DateFormatter {
       biggestUnitForPartial = 1 // make it look like the dates are only different in terms of time
     }
 
-    let full0 = formatZonedMarker(start, context, standardSettings)
-    let full1 = formatZonedMarker(end, context, standardSettings)
+    let full0 = this.format(start, context)
+    let full1 = this.format(end, context)
 
     if (full0 === full1) {
       return full0
     }
 
     let partialFormatSettings = computePartialFormattingOptions(standardSettings, biggestUnitForPartial)
-    let partial0 = formatZonedMarker(start, context, partialFormatSettings)
-    let partial1 = formatZonedMarker(end, context, partialFormatSettings)
+    let partial0 = this.format(start, context, partialFormatSettings)
+    let partial1 = this.format(end, context, partialFormatSettings)
 
     let insertion = findCommonInsertion(full0, partial0, full1, partial1)
     let separator = this.extendedSettings.separator || DEFAULT_SEPARATOR
@@ -63,32 +136,24 @@ export class NativeFormatter implements DateFormatter {
 
 }
 
-function separateExtendedSettings(settings) {
-  let standardSettings = {}
-  let extendedSettings = {}
 
-  for (let name in settings) {
-    if (name === 'separator') {
-      extendedSettings[name] = settings[name]
-    } else {
-      standardSettings[name] = settings[name]
-    }
-  }
+function formatWeekNumber(num: number, locale: Locale, display?: 'numeric' | 'narrow' | 'short'): string {
+  let parts = []
 
-  return { standard: standardSettings, extended: extendedSettings }
-}
-
-
-// General Formatting Utils
+  if (display === 'narrow') {
+    parts.push(locale.options.weekHeader)
+  } else if (display === 'short') {
+    parts.push(locale.options.weekHeader, ' ')
+  }
+  // otherwise, considered 'numeric'
 
-function formatZonedMarker(date: ZonedMarker, context: DateFormattingContext, standardSettings) {
-  let s = date.marker.toLocaleString(context.locale.codeArg, standardSettings)
+  parts.push(locale.simpleNumberFormat.format(num))
 
-  if (standardSettings.timeZoneName && date.timeZoneOffset != null && context.timeZone !== 'UTC') {
-    s = s.replace(/UTC|GMT/, formatTimeZoneOffset(date.timeZoneOffset))
+  if (locale.options.isRTL) {
+    parts.reverse()
   }
 
-  return s
+  return parts.join('')
 }
 
 

+ 1 - 0
src/datelib/formatting.ts

@@ -33,6 +33,7 @@ export interface DateFormattingContext {
   timeZone: string,
   locale: Locale,
   calendarSystem: CalendarSystem
+  computeWeekNumber: (d: DateMarker) => number
 }
 
 export interface DateFormatter {

+ 25 - 14
tests/automated/datelib/main.js

@@ -556,20 +556,31 @@ fdescribe('datelib', function() {
 
     })
 
-    // it('outputs pretty format with no timezone even tho specified', function() {
-    //   var marker = env.createMarker('2018-06-08')
-    //   var formatter = createFormatter({
-    //     weekday: 'long',
-    //     day: 'numeric',
-    //     month: 'long',
-    //     year: 'numeric',
-    //     timeZoneName: 'short'
-    //   })
-    //   var s = env.format(marker, formatter)
-    //   expect(s).toBe('Friday, June 8, 2018')
-    // })
-
-    // TODO: when trying to do 'long' timezone
+    it('outputs pretty format with no timezone even tho specified', function() {
+      var marker = env.createMarker('2018-06-08')
+      var formatter = createFormatter({
+        weekday: 'long',
+        day: 'numeric',
+        month: 'long',
+        year: 'numeric',
+        timeZoneName: 'short'
+      })
+      var s = env.format(marker, formatter)
+      expect(s).toBe('Friday, June 8, 2018')
+    })
+
+    it('outputs pretty format with no timezone even tho specified as long', function() {
+      var marker = env.createMarker('2018-06-08')
+      var formatter = createFormatter({
+        weekday: 'long',
+        day: 'numeric',
+        month: 'long',
+        year: 'numeric',
+        timeZoneName: 'long'
+      })
+      var s = env.format(marker, formatter)
+      expect(s).toBe('Friday, June 8, 2018')
+    })
 
   })