Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Normative: Add quarter option #345

Closed
wants to merge 2 commits into from
Closed

Conversation

FrankYFTang
Copy link
Contributor

No description provided.

@FrankYFTang
Copy link
Contributor Author

@zbraniecki @anba

@FrankYFTang
Copy link
Contributor Author

FrankYFTang commented May 20, 2019

Usage:

let d = new Date();
var dtf = new Intl.DateTimeFormat("en", {year: "numeric", quarter: "short"});
dtf.format(d);  // "Q2 2019"
dtf.formatToParts(d);
// [{type: "quarter", value: "Q2"}, 
//  {type: "literal", value: " "}, 
//  {type: "year", value: "2019"}]
dtf = new Intl.DateTimeFormat("en", {year: "numeric", quarter: "long"});
dtf.format(d);  // "2nd quarter 2019"
dtf.formatToParts(d);
// [{type: "quarter", value: "2nd quarter"}, 
//  {type: "literal", value: " "}, 
//  {type: "year", value: "2019"}]
dtf = new Intl.DateTimeFormat("zh-Hant", {year: "numeric", quarter: "short"});
dtf.format(d);  // "2019年第2季"
dtf.formatToParts(d);
// [{type: "year", value: "2019"}, 
//  {type: "literal", value: "年"}, 
//  {type: "quarter", value: "第2季"}]

@FrankYFTang FrankYFTang changed the title Add support to format quarter Normative: Add support to format quarter May 20, 2019
@FrankYFTang FrankYFTang added c: datetime Component: dates, times, timezones enhancement Small Smaller change solvable in a Pull Request labels May 20, 2019
@sffc sffc added the s: discuss Status: TG2 must discuss to move forward label May 20, 2019
@sffc
Copy link
Contributor

sffc commented May 20, 2019

LGTM; let's discuss in the next meeting to seek consensus.

@littledan
Copy link
Member

LGTM as well. Is the idea here to pursue this feature as a one-off, or did you have more Intl.DateTimeFormat feature proposals as well?

@FrankYFTang
Copy link
Contributor Author

LGTM as well. Is the idea here to pursue this feature as a one-off, or did you have more Intl.DateTimeFormat feature proposals as well?

That is the question I am not sure. There are 3 thing (or 4 if we count the relativeYear / yearName you proposed) we should address, all of them are kind of independent from each other:
2) another one is the "dayPeriod", which will have very similar change as this one.
3) an option "millisecondDigits" (0 to 3 ) to control the output of how many digits for millisecondDigits (default 0 as now. )

I wonder should I file one by one as PR or group them together as a proposal (see https://github.com/FrankYFTang/proposal-intl-datetimeformat-more-options/blob/master/README.md ). Should I also include the "yearName" into such proposal?

@FrankYFTang
Copy link
Contributor Author

How about I just file all the changes one by one as PR here so we will have a sense of what the changes look like. And if we all feel it need to be group into a bigger proposal I can just merge those changes there.

@FrankYFTang
Copy link
Contributor Author

@FrankYFTang FrankYFTang changed the title Normative: Add support to format quarter Normative: Add quarter option May 21, 2019
Copy link
Member

@leobalter leobalter left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@FrankYFTang
Copy link
Contributor Author

We have discussed this PR in Jun 5 2019 TC39 and decided this is small enough and align with pre-existing API already and therefore does not need to form a staged proposal but do require consensus with in ECMA402 committee + tests in test262 + 1 js engine implementation and no concern from other js implementation to land into ECMC402 as stage 4.

@FrankYFTang
Copy link
Contributor Author

Initial set of tests in tc39/test262#2194
V8 is now having this behind a flag --harmony_intl_dateformat_quarter

@leobalter
Copy link
Member

leobalter commented Jun 13, 2019

Questions from the Intl meeting:

How does this API behave in non gregorian calendars?

How do we handle extension to trimesters and more general periods in the future?

We need to find a reasonable answer to these questions before we achieve consensus for the PR

@FrankYFTang
Copy link
Contributor Author

FrankYFTang commented Jun 13, 2019

How does this API behave in non gregorian calendars?

Quarter, regardless which calendar system we are using, is defined as (month / 3) in zero-based quarter and zero-based month
month 0 (Jan) -> quarter 0 (Q1)
month 2 (March) -> quarter 0 (Q1)
month 3 (April) -> quarter 1 (Q2)
month 11 (Dec) -> quarter 3 (Q4)

I will make a spec change to clarify that quarter is calculated from month / 3.

How do we handle extension to trimesters and more general periods in the future?

Other periods are not being considered here, but neither will conflict with this proposal. For example, if there are strong demand, we can propose to add to format "decade" (e.g "80") , "century" ("21st century"), "semester" ("first semester"), or "trimester" and won't conflict with this. The scope of this PR is only tight to a frequently use period in the modern world:

  1. in the financial world (2019 Q1 Financial report of Apple Computer Inc - Ex https://www.boxinvestorrelations.com/financial-information/financial-reports/default.aspx )
  2. in company planning ( https://corvisio.com/wp-content/uploads/2019/04/OKR-Software-3.png )
    maybe in other usage.

It is not intend to be a general abstract period that cover other concept in different calendar system.
The quarter is supported in CLDR but not other more general abstract period.

@FrankYFTang
Copy link
Contributor Author

API behave in non gregorian calendars is now fully specified by 6c60ab7

llebout pushed a commit to llebout/chromium_v8 that referenced this pull request Jun 16, 2019
quarter option- see tc39/ecma402#345
dayPeriod option- see tc39/ecma402#346
fractionalSecondDigits option- see tc39/ecma402#347
2019-6-5 TC39 presentation- http://shorturl.at/mtB12
test262: tc39/test262#2194
I2I: http://shorturl.at/beCNV (for quarter)
I2I: http://shorturl.at/bekrZ (for dayPeriod)
I2I: http://shorturl.at/flwF5 (for fractionalSecondDigits)

Bug: v8:9282,v8:9283,v8:9284

Change-Id: I99f4c0f861507c7451497b735a276780bb8aead6
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1621445
Commit-Queue: Frank Tang <ftang@chromium.org>
Reviewed-by: Jakob Kummerow <jkummerow@chromium.org>
Cr-Commit-Position: refs/heads/master@{#62041}
@srl295
Copy link
Member

srl295 commented Jun 17, 2019

So we got feedback that in the UK there are 'financial years' which start April 1st, and companies use those quarters in their reporting, and so 'quarters' need to be calculated from a different start date than the calendar.

in the financial world (2019 Q1 Financial report of Apple Computer Inc )

Yes, but in the UK, here is a "1st Quarter" report that ends July 1st:

If the primary use for Quarters is financial, I think this may need some more thought. I know this is a longstanding ICU/CLDR and Java feature. But if it is not sufficient for a large number of cases, then we should probably rethink whether this feature should be simply named quarter: "short".

@srl295
Copy link
Member

srl295 commented Jun 17, 2019

I've opened CLDR-13109 to discuss these questions on the CLDR side. edit it turns out that some of these questions have been raised before (by myself and others). No concrete consensus.

@srl295
Copy link
Member

srl295 commented Jun 17, 2019

Quarter, regardless which calendar system we are using, is defined as (month / 3) in zero-based quarter and zero-based month

OK, but for say Hebrew calendar in a leap year, there are 13 months. so would that result in "5th Quarter"? (Note: There's no CLDR data for <quarter type="5" />) And actually, the numbering of the months internally (ICU fields + CLDR data) is something like 0,1,2,3,4,6,7,8,9,10,11,12 in non-leap years (skipping 5) and 0,1,2,3,4,5,6,7,8,9,10,11,12 in leap years. How are you proposing to handle this?

edit actually, it's 0-11 in non-leap, 0-12 in leap years. Still end up with a 5th 'quarter'. (test code and rer-inspection of ICU source)

@ashemedai
Copy link

ashemedai commented Jun 17, 2019

FYI: In the Netherlands we have a normal fiscal year (boekjaar; 1 Jan – 31 Dec), but also a "broken" fiscal year, which can start on 1 Apr, 1 Jul, whatever makes the most sense for an organisation. In addition a fiscal year might be shorter than 1 year but also longer, to a maximum of 24 months minus 1 day.

@@ -281,7 +286,10 @@ <h1>PartitionDateTimePattern ( _dateTimeFormat_, _x_ )</h1>
1. Let _p_ be the substring of _pattern_ from position _beginIndex_, exclusive, to position _endIndex_, exclusive.
1. If _p_ matches a Property column of the row in <emu-xref href="#table-datetimeformat-components"></emu-xref>, then
1. Let _f_ be the value of _dateTimeFormat_'s internal slot whose name is the Internal Slot column of the matching row.
1. Let _v_ be the value of _tm_'s field whose name is the Internal Slot column of the matching row.
1. If _p_ is `"quarter"`, then
1. Let _v_ be ( _tm_.[[month]] / 3 ) + 1.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

assumes only 12 months

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not really, it assume every 3 months is a quarter and won't prevent month 13 to be 5th quarter in the calendar have more than 12 months.

Also according to
https://www.ecma-international.org/ecma-262/9.0/index.html#sec-month-number
"Months are identified by an integer in the range 0 to 11, inclusive."

The ICU logic is in i18n/smpdtfmt.cpp

    case UDAT_QUARTER_FIELD:
        if (count >= 4)
            _appendSymbol(appendTo, value/3, fSymbols->fQuarters,
                          fSymbols->fQuartersCount);
        else if (count == 3)
            _appendSymbol(appendTo, value/3, fSymbols->fShortQuarters,
                          fSymbols->fShortQuartersCount);
        else
            zeroPaddingNumber(currentNumberFormat,appendTo, (value/3) + 1, count, maxIntCount);
        break;

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A quarter means a fourth of something. So a 5th quarter is not a quarter.

20.3.1.4 Month Number is also wrong for non-Gregorian calendars, then. because 0 to 11 inclusive is not sufficient. Perhaps you should spec this just for gregorian calendars?

Note my node (v8) example referenced above showing numeric formats from 1 to 13 inclusive: https://gist.github.com/srl295/4ce6860667770b5cf563c383897d1b20

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, the ICU logic for Java for quarter is broken for the Hebrew calendar, it produces garbage output.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the Ecma262 reference above binding on Ecma402 date formats? I wouldn't think so, otherwise non-12 month calendars would not be supported at all.

@srl295
Copy link
Member

srl295 commented Jun 17, 2019

@FrankYFTang can you comment on the use cases behind the proposal? I know it was added to CLDR 13 years ago, but it would be helpful to get the expected usage. If it is financial reports and company planning (above) I think that argues for at least a settable start date. There's a 2013 CLDR ticket that notes that Japan also has an Apr 1 fiscal start date used with quarters, and also a 2008 ICU ticket that I filed (which I only wrote a test case for now) that shows that formatting is broken for ICU4J

@FrankYFTang
Copy link
Contributor Author

So we got feedback that in the UK there are 'financial years' which start April 1st, and companies use those quarters in their reporting, and so 'quarters' need to be calculated from a different start date than the calendar.

in the financial world (2019 Q1 Financial report of Apple Computer Inc )

Yes, but in the UK, here is a "1st Quarter" report that ends July 1st:

If the primary use for Quarters is financial, I think this may need some more thought. I know this is a longstanding ICU/CLDR and Java feature. But if it is not sufficient for a large number of cases, then we should probably rethink whether this feature should be simply named quarter: "short".

If the year start with April 1st, instead of Jan 1st, then it is an issue of a different "calendar" rather than an issue with "quarter", right?

@FrankYFTang
Copy link
Contributor Author

@FrankYFTang can you comment on the use cases behind the proposal? I know it was added to CLDR 13 years ago, but it would be helpful to get the expected usage. If it is financial reports and company planning (above) I think that argues for at least a settable start date. There's a 2013 CLDR ticket that notes that Japan also has an Apr 1 fiscal start date used with quarters, and also a 2008 ICU ticket that I filed (which I only wrote a test case for now) that shows that formatting is broken for ICU4J

I think it is very common for people to think 2019 Q1 as Jan-March of 2019 and this is what this feature intend to support. Of course, there are other demand for different kind of "calendar system" to be support, but that is beyond what I intend to change here. All what you talk about fiscal year is related to a different calendar system, since it also change the week number and day number start from that year. That is beyond this feature is about.

@srl295
Copy link
Member

srl295 commented Jun 21, 2019

I think it is very common for people to think 2019 Q1 as Jan-March of 2019 and this is what this feature intend to support.

Which people, and for what example usage? Have you surveyed different regions? As an international standard, we need to consider more than specific regional usage. I think CLDR did not do this analysis in v1.4 when quarters were added, and should have.

If the year start with April 1st, instead of Jan 1st, then it is an issue of a different "calendar" rather than an issue with "quarter", right?

Possibly. But would month numbering be affected (i.e. April be month 0(1st)?) Or week numbering?

@Crissov
Copy link

Crissov commented Jun 27, 2019

Quarter, regardless which calendar system we are using, is defined as (month / 3) in zero-based quarter and zero-based month
month 0 (Jan) -> quarter 0 (Q1)
month 2 (March) -> quarter 0 (Q1)
month 3 (April) -> quarter 1 (Q2)
month 11 (Dec) -> quarter 3 (Q4)

No, a quarter(-year) is a (solar) year divided into 4 time spans of almost equal length, usually rounded to an integer multiple of another time unit: this does not have to be (3) months, but can also be (91+) days or (13+) weeks!

How do we handle extension to trimesters and more general periods in the future?

A trimester, by its very name, is 3 months long (which confusingly is about a third of the length of a human pregnancy), whereas a semester (not related to semi as often assumed) is 6 months. Bimester (2 months) and quadmester (4 months) are analogous terms that are used less frequently. Therefore, the proposed definition month / 3 is appropriate for trimester, but not for quarter(-year).

  1. calendar season: first trimester = Jan+Feb+Mar (90 or 91 days)
  2. calendar season: second trimester = Apr+May+Jun (91 days)
  3. calendar season: third trimester = Jul+Aug+Sep (92 days)
  4. calendar season: fourth trimester = Oct+Nov+Dec (92 days)

Alas, the first …mester does not need to start with January (or whatever the first month is called), because these terms are most frequently used with fiscal and academic years that not necessarily equate to the calendar year. Often, a (summer) break, despite having the same length as teaching terms, is not considered a trimester, which adds to the confusion about the number of trimesters per year and hence their length. In much of Europe, the academic year starts either with September or with October, and the terms may have traditional or local names:

  1. academic term: Michaelmas, Fall, Autumn = Oct+Nov+Dec (92 days) or Sep+Oct+Nov (91 days)
  2. academic term: Hilary, Epiphany, Lent, Winter = Jan+Feb+Mar or Dec+Jan+Feb (both 90 or 91 days)
  3. academic term: Easter, Spring = Apr+May+Jun (91 days) or Mar+Apr+May (92 days)
  4. academic term: Trinity, Summer = Jul+Aug+Sep or Jun+Jul+Aug (both 92 days)

European meteorological seasons are another example of offset trimesters:

  1. meteo season: winter = Dec+Jan+Feb (90 or 91 days)
  2. meteo season: spring = Mar+Apr+May (92 days)
  3. meteo season: summer = Jun+Jul+Aug (92 days)
  4. meteo season: autumn = Sep+Oct+Nov (91 days)

Astronomic seasons, lasting from an equinox to a solstice or vice versa (which may also be known by their pagan holidays Ostara, Litha (i.e. Midsummer), Mabon and Yule, have a similar length and contain about 3 zodiac signs (but not their eponymous constellations) each:

  1. classical, tropical season: spring = ~20 March Equinox – June Solstice (~92.75 ≤ 93 days) = ♈+♉+♊
  2. classical, tropical season: summer = 20–21 June Solstice – September Equinox (~93.65 ≥ 93 days) = ♋+♌+♍
  3. classical, tropical season: autumn = 22–23 September Equinox – December Solstice (~89.85 ≤ 90 days) = ♎+♏+♐
  4. classical, tropical season: winter = 21–22 December Solstice – March Equinox (~88.99 ≤ 89 days) = ♑+♒+♓

These tropical seasons must not be confused with wet and dry seasons or wet, hot and cold seasons in the tropics. While the tropical year is commonly used in Western astrology as well, sometimes astrological seasons are defined as parts of the sidereal year as in South Asia:

  1. visible, sidereal season: spring = mid-Apr – mid-Jul
  2. visible, sidereal season: summer = mid-Jul – mid-Oct
  3. visible, sidereal season: autumn = mid-Oct – mid-Jan
  4. visible, sidereal season: winter = mid-Jan – mid-Apr

Traditional (and sometimes still Julian) English quarter days, which are the origin of academic trimester names, usually are Christian holidays that lay between a solstice or equinox and the end of the month:

  1. quarter day: Lady Day (25 Mar)
  2. quarter day: Midsummer (24 Jun)
  3. quarter day: Michaelmas (29 Sep)
  4. quarter day: Christmas (25 Dec)

or in areas with stronger Celtic heritage, e.g. Scotland:

  1. (cross-)quarter day: Candlemas (2 Feb, *28 Feb)
  2. (cross-)quarter day: May Day / Roodmas (1 May) or nominal Whitsunday (15 May, *28 May)
  3. (cross-)quarter day: Lammas (1 Aug, *28 Aug)
  4. (cross-)quarter day: All Hallows (1 Nov) or Martinmas (11 Nov, *28 Nov)

Solar seasons, best known from Gaelic or Wiccan changeover feasts Imbolc, Beltane, Lammas and Samhain (i.e. Halloween), historically started at the midpoints between equinoxes and solstices – as they do in East Asia:

  1. solar season: spring, chūn (春) ≈ 4 Feb – 4 May
  2. solar season: summer, xià (夏) ≈ 5 May – 5 Aug
  3. solar season: autumn, qiū (秋) ≈ 6 Aug – 5 Nov
  4. solar season: winter, dōng (冬) ≈ 6 Nov – 3 Feb

They have since moved by less than a week to cover 3 complete Gregorian months each:

  1. Gaelic season: spring = Feb+Mar+Apr
  2. Gaelic season: summer = May+Jun+Jul
  3. Gaelic season: autumn = Aug+Sep+Oct
  4. Gaelic season: winter = Nov+Dec+Jan

The scope of this PR is only tight to a frequently use period in the modern world:

  1. in the financial world (2019 Q1 Financial report of Apple Computer Inc - ...)
  2. in company planning (...) maybe in other usage.

Apple's reporting quarters are infamously week-based (i.e. usually 13 weeks in each quarter, but every 5 to 6 years there is a 14th week in Q4), see e.g. Slate. The actual start of a country's or company's fiscal year varies, as does the definition of week start.

  1. fiscal quarter = W01–W13
  2. fiscal quarter = W14–W26
  3. fiscal quarter = W27–W39
  4. fiscal quarter = W40–W52 or W53

Old German montane or mining quarters, each named for a Christian holiday contained within itself and thus closely related to Catholic embertides, over time changed from being week-based (starting on a Sunday) to last 3 Gregorian calendar months each.

  1. embertide: Lent / Reminiscere (6/5 weeks before Easter: 15 February – 21 March, W07–W12) → Jan+Feb+Mar (~W01–W13)
  2. embertide: Whitsun / Trinitatis (7/8 weeks after Easter: 17 May – 20 June, W20–W25) → Apr+May+Jun (~W14–W26)
  3. embertide: Holyrood, Crucis (14 September, W37–W38) → Jul+Aug+Sep (~W27–W39)
  4. embertide: Luci(a)e (13 December, W50–W51) → Oct+Nov+Dec (~W40–W52)

In conclusion, it probably makes sense to specify at least three terms, e.g.:

  • trimester: 3 (out of 12) consecutive calendar months, starting with the first of the calendar year
  • quarter: a fourth of a (solar) calendar year, usually 91 days = 13 weeks, exceptionally 92 days or 14 weeks (= 98 days)
  • season: 3 (out of 12) consecutive zodiac signs, starting with the first of the astronomical year

@FrankYFTang
Copy link
Contributor Author

In conclusion, it probably makes sense to specify at least three terms, e.g.:

  • trimester: 3 (out of 12) consecutive calendar months, starting with the first of the calendar year
  • quarter: a fourth of a (solar) calendar year, usually 91 days = 13 weeks, exceptionally 92 days or 14 weeks (= 98 days)
  • season: 3 (out of 12) consecutive zodiac signs, starting with the first of the astronomical year

Thank you for your information. It is very informative.
Could we agree of the following?
A. The supporting for "quarter" should not be mixed with the supporting for trimester and season. In other words, we should not introduce a concept/term to represent any of these three different concept but should instead, keep them separated if we add the support.
B. The calculation of when such "quarter" start/end depending on each calendar system.
C. The calculation of when such "quarter" start/en may also require customization within the same calendar system for some usage.
D. There are no need to support all the three concepts (quarter/trimester/season) in the same time (same revision of spec or vai same PR). In other words, we could choose to add the support to format one of them first and others later.
E. The current PR need to be changed to ensure B and C above won't be restricted to a particular calendar and allows future customization of start/end time of quarter in a particular calendar system.

@sffc
Copy link
Contributor

sffc commented Sep 20, 2019

Since this PR is not actionable until the open questions are addressed, I am converting it to an issue, as discussed in ECMA-402 on September 5. Please direct future discussion to #374.

@sffc sffc closed this Sep 20, 2019
FrankYFTang added a commit to FrankYFTang/test262 that referenced this pull request Sep 25, 2019
leobalter pushed a commit to tc39/test262 that referenced this pull request Sep 26, 2019
backwardn pushed a commit to backwardn/v8 that referenced this pull request Oct 2, 2019
ECMA402 decided to abandon tc39/ecma402#345
so we should remove the code here.

Bug: v8:9282
Change-Id: I05cbad429ae01bf3debebfed07160b5f53f98a21
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1825827
Commit-Queue: Frank Tang <ftang@chromium.org>
Reviewed-by: Jakob Kummerow <jkummerow@chromium.org>
Cr-Commit-Position: refs/heads/master@{#64004}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
c: datetime Component: dates, times, timezones enhancement needs tests s: discuss Status: TG2 must discuss to move forward Small Smaller change solvable in a Pull Request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants