Amphtml: Create amp-date-display

Created on 8 Aug 2017  Â·  31Comments  Â·  Source: ampproject/amphtml

Similar components: amp-date-countdown https://github.com/ampproject/amphtml/issues/10385
See presentation for a summary.

Requirements

  • Ability to specify a UTC date (ISO string or timestamp in ms or timestamp in seconds)
  • Ability to specify a local date (including now)
  • Ability to convert between utc/local
  • Ability to offset the date by x seconds
  • Ability to use CSS to style each part (number and text) of the date being display
  • Locale support

Examples

UTC

<amp-date-display datetime=”2017-08-02T15:15:15.000Z”>
// Wed Aug 02 2017 15:15:15 (UTC)

<amp-date-display datetime=”2017-08-02T15:15:15.000+01:00”>
// Wed Aug 02 2017 14:15:15 (UTC)

<amp-date-display datetime=”2017-08-02T15:15:15.000Z” display-in=”local”>
// Wed Aug 02 2017 08:15:15 (PDT)

Local

<amp-date-display datetime=”2017-08-02T15:15:15.000 ”>
// Wed Aug 02 2017 15:15:15 (PDT)

<amp-date-display datetime=”now”>
// Wed Aug 02 2017 13:10:10 (PDT) 

<amp-date-display datetime=”2017-08-03 ”>
// Wed Aug 03 2017 13:10:10 (PDT)

<amp-date-display datetime=”2017-08-02T15:15:15.000 ” display-in=”utc”>
// Wed Aug 02 2017 22:15:15 GMT-0700 (UTC)

Offset

<amp-date-display datetime=”now” offset-seconds=”172800”> // 2-days
// Wed Aug 04 2017 13:10:10 (PDT) (assume it is 1:30 PM right now)

<amp-date-display datetime=”2017-08-02T15:15:15.000Z” offset-seconds=”172800”> // 2-days
// Wed Aug 04 2017 15:15:15 (UTC)

<amp-date-display datetime=”2017-08-02T15:15:15.000Z” offset-seconds=”172800” display-in=”local”> // 2-days

// Wed Aug 04 2017 08:15:15 (PDT)

Format Design

<amp-date-display 
  datetime=”ISO with optional time/timezone offset”
  timestamp-ms="POSIX epoch in ms"
  timestamp-seconds="POSIX epoch in seconds" 
  display-in=”local|utc”
  offset-seconds=”seconds”
  locale=”en-US”
  layout="OnlySizedDefinedLayouts">
 <template type="amp-mustache">
    <div>{{dayName}}, {{monthNameShort}} {{day}} {{year}}</div>
    <div>{{hour12TwoDigit}}:{{minuteTwoDigit}}:{{secondTwoDigit}} {{dayPeriod}}</div>
 </template>
</amp-countdown>

possible outputs

Wednesday, Aug  2017
01:15:15 PM

Template Variables

This proposal handles "don't want to show 0" easily using mustache sections (e.g. {{#day}}) and does not need anything for grouping which are big advantages.

Variables | Meaning
--- | ---
year | 2017
yearTwoDigit | 17
month | month - 0, 1, 2, 3..., 12
monthTwoDigits | month - 00, 01, 02, 03...12
monthName | January - i18n string for long month name
monthNameShort | JAN - i18n string for short month name
<Similar for day> | ....
hour | 0-23
hourTwoDigit | 00-23
hour12 | 1-12
hour12TwoDigit | 01-12
<Similar for minute, seconds> | ...
dayPeriod | AM - i18n string for AM/PM

Attributes

datetime

  • One of now or <ISO datetime> with OPTIONAL time and timezone offset
  • If no time/timezone specified, assumes local otherwise utc

timestamp-ms

  • POSIX epoch value in milliseconds - will be assumed to be UTC

timestamp-seconds

  • POSIX epoch value in seconds - will be assumed to be UTC (essentially Unix time: https://en.wikipedia.org/wiki/Unix_time)

Note: _One_ of datetime, timestamp-ms, timestamp-seconds is required.

offset-seconds

  • Negative or poissive number of seconds to add/subtract from datetime

display-in (Defaults to local)

  • One of utc or local.
    _ Converts the date to either locale or utc

Open questions

  • This scheme does not support locale-aware formatting e.g. DD/MM/YY vs MM/DD/YY
  • Can we rely on JS IntlAPI? How good is the browser locale support? How big is the polyfill?
  • If we use JS Intl, should we also expose {{localeStandardDateShort}} {{localeStandardDateLong}} that would resolve to locale-aware formatting? (e.g. {{localeStandardDateShort}} -> 3/20/2017 for en-US or 20/3/2017 for en-CA)
When Possible Localization Feature Request

Most helpful comment

Quick update: I only need to add a basic documentation to open the PR!

All 31 comments

/cc @choumx @robinpokorny @ericlindley-g

@robinpokorny Thanks for taking this on! Couple of resources to get you started:

@aghassemi After some initial investigation, I found a small problem. If we want to use the native Date implementation–which is otherwise sufficient and convinient–it would be difficult to distinguish if the original input was in UTC or not.

So I would suggest using the default behaviour of Date.parse and showing all dates in local by default and use the attribute to show it in UTC (or the other way around).

Can we allow the date to be specified in epoch time (seconds and ms versions). The reason is that a lot of the existing API endpoints we deal with send dates that way and support for epoch time would allow us to render them via amp-list without changing the endpoint.

@choumx @robinpokorny (RE: https://github.com/ampproject/amphtml/issues/10385#issuecomment-321381124) I looked at moment.js and several date format libraries in JS and also JS's internalization API. Unfortunately JS's Intl API (which I was hoping to use for this component rather than including a 3P library) doesn't support format strings.

Intl API dooes however support options that can be used to construct locale-aware named formats such as fullDate shortDate longDate etc.. I think exposing parts and also these pre-formatted locale-aware formats as variables should cover most cases.

@jpettitt Added timestamp-ms="POXIS epoch in ms" timestamp-seconds="POXIS epoch in seconds" to the spec. Thanks for bringing it up importance of supporting different backends.

@robinpokorny Changed convert-to to display-in

If I've missed any of your suggestions from the review meeting, please let me know.

@aghassemi in this comment the name for ms version is just timestamp. What do you think is better?

@robinpokorny Changed to timestamp-ms everywhere. Initially had it as timestamp and timestamp-seconds but realized timestamp is ambiguous (well, Unix timestamp is in seconds, but JS getTime is in ms)

I think you mean POSIX not POXIS - you may also want to link to this https://en.wikipedia.org/wiki/Unix_time

@jpettitt updated.

@robinpokorny When we endup using JS Intl API to allow for locale-aware formats like localeStandardDateShort ( e.g. 3/20/2017 for en-US or 20/3/2017 for en-CA ), another feature we can add to make life easier is this:

Attribute format:
One of template| localeStandardDateShort | localeStandardDateLong | etc..

This way, user does not need to use amp-mustache in all cases and for simple date displays where the whole thing can be a single string in a single DOM node, they can use format instead.

I wish JS Intl API had the concept of format strings like moment.js and, well, other languages though :(

If you are interested I have a WIP implementation in this branch: https://github.com/robinpokorny/amphtml/tree/add-amp-date-display.

@robinpokorny Just wanted to touch base and see how this is progressing.

@aghassemi I have a working branch, I got stuck with the tests. I will continue with it.

another feature request for this: https://github.com/ampproject/amphtml/issues/12036

screenshot 2017-11-14 21 23 54


@aghassemi, this is the screenshot of the code I have.

What is missing:

  • [ ] validator-amp-date-display.protoascii (all)
  • [ ] amp-date-display.md (all)
  • [ ] test/test-amp-date-display.js (all)

Hi,

This looks very interesting and I was asking about this kind of thing in https://github.com/ampproject/amphtml/issues/12036 and pointed to https://github.com/ampproject/amp-by-example/issues/719 as a workaround for the short term.

Obviously this solution being proposed would be a better way to solve the problem I have is there anything I can do to help?

My issue is just to be able to take a time and covert it to local time for the user based on their system local time the time is simply 3pm UTC (4pm CET / 10am EST)

The question I have is how efficient will this approach be if I have 200 times on a page all of which need to be converted - where there are probably on 20 different actual times. This is for start times of matches where many matches start at the same time and the possible start times are limited.

@QES this component will be at least a few months out. The workaround with with amp-list does batching, so if multiple amp-lists with the same src get fired at once, only a single call happens. This means you can create a single endpoint and pass TIMEZONE to it and have it return a JSON with all the 20 so dates converted. Each amp-list then can target a specific key in that JSON result to render the converted date.

@aghassemi thanks - will take a look at that. It might be a possible work around.

Hi, any updates on this component? Thanks!

@mcmd, no, there's been no progress. I believe the component functionality is implemented. I couldn't get pass some docs-related issues.

@robinpokorny what issues? doc-related and in the documentation (ampproject/docs)?

If you update your fork and merge in latest master I'll take a look at your validator issue if you want.

@jpettitt, you guys are great. A help would be nice 🙏

The fork is here: https://github.com/robinpokorny/amphtml/tree/add-amp-date-display

Quick first pass TODO's

  • Input validation:

    • Use the user.assert() function to make sure the inputs are what you expect them to be (eg numbers are actually numbers). See amp-geo for an example of using asserts to throw users errors.

  • Unit tests:

    • You need to add some unit tests, check of all the expected outputs and and that all the asserts throw when they should. - the amp-geo tests have some examples you can base off.

  • Validator:

    • Add INTRINSIC to list of layouts.

    • In the ./validator directory run python byild.py --update_tests to update the validator output (then look at the file it generates to make sure it's right!!!). You'll need to crate an empty .out file first for this to work.

gulp pr-check is your friend.

@robinpokorny Any progress on this?

I give this a last chance, I want to open a PR by the end of the week. I will dedicate at least two hours every day to this.
Today, I rebased and fixed all warnings (mostly by lint). The next step is to add validations with user.assert().

Question: What should happen when the provided date could not be parsed? I guess, it should throw an error and not render at all to prevent showing a random date.

That sounds reasonable. We also have a user error system in src/log.js to show console errors for these cases. E.g. user().error('amp-date-display', 'Invalid date:', parsedDate);.

Thanks @robinpokorny! user().assert will log an error and prevent the component from rendering ( as it throws ). I think that would be fine to do when encountering invalid input.

Quick update: I only need to add a basic documentation to open the PR!

Any update on this? Looking forward to use it

Was this page helpful?
0 / 5 - 0 ratings

Related issues

sryze picture sryze  Â·  3Comments

Download picture Download  Â·  3Comments

choumx picture choumx  Â·  3Comments

mrjoro picture mrjoro  Â·  3Comments

edhollinghurst picture edhollinghurst  Â·  3Comments