@@ -1982,6 +1982,7 @@ suite('relative-time', function () {
19821982 const el = document . createElement ( 'relative-time' )
19831983 el . setAttribute ( 'lang' , 'es-ES' )
19841984 el . setAttribute ( 'time-zone' , 'Europe/Madrid' )
1985+ el . setAttribute ( 'hour-cycle' , 'h23' )
19851986
19861987 el . setAttribute ( 'datetime' , '2023-01-15T17:00:00.000Z' )
19871988 await Promise . resolve ( )
@@ -2815,6 +2816,134 @@ suite('relative-time', function () {
28152816 }
28162817 } )
28172818
2819+ suite ( '[hourCycle]' , function ( ) {
2820+ test ( 'formats with 24-hour cycle when hour-cycle is h23' , async ( ) => {
2821+ const el = document . createElement ( 'relative-time' )
2822+ el . setAttribute ( 'datetime' , '2020-01-01T15:00:00.000Z' )
2823+ el . setAttribute ( 'time-zone' , 'UTC' )
2824+ el . setAttribute ( 'format' , 'datetime' )
2825+ el . setAttribute ( 'hour' , 'numeric' )
2826+ el . setAttribute ( 'minute' , '2-digit' )
2827+ el . setAttribute ( 'hour-cycle' , 'h23' )
2828+ await Promise . resolve ( )
2829+ assert . notMatch ( el . shadowRoot . textContent , / A M | P M / i)
2830+ assert . match ( el . shadowRoot . textContent , / 1 5 : 0 0 / )
2831+ } )
2832+
2833+ test ( 'formats with 12-hour cycle when hour-cycle is h12' , async ( ) => {
2834+ const el = document . createElement ( 'relative-time' )
2835+ el . setAttribute ( 'datetime' , '2020-01-01T15:00:00.000Z' )
2836+ el . setAttribute ( 'time-zone' , 'UTC' )
2837+ el . setAttribute ( 'format' , 'datetime' )
2838+ el . setAttribute ( 'hour' , 'numeric' )
2839+ el . setAttribute ( 'minute' , '2-digit' )
2840+ el . setAttribute ( 'hour-cycle' , 'h12' )
2841+ await Promise . resolve ( )
2842+ assert . match ( el . shadowRoot . textContent , / 3 : 0 0 / )
2843+ assert . match ( el . shadowRoot . textContent , / P M / i)
2844+ } )
2845+
2846+ test ( 'formats with 12-hour cycle when hour-cycle is h11' , async ( ) => {
2847+ const el = document . createElement ( 'relative-time' )
2848+ el . setAttribute ( 'datetime' , '2020-01-01T15:00:00.000Z' )
2849+ el . setAttribute ( 'time-zone' , 'UTC' )
2850+ el . setAttribute ( 'format' , 'datetime' )
2851+ el . setAttribute ( 'hour' , 'numeric' )
2852+ el . setAttribute ( 'minute' , '2-digit' )
2853+ el . setAttribute ( 'hour-cycle' , 'h11' )
2854+ await Promise . resolve ( )
2855+ assert . match ( el . shadowRoot . textContent , / 3 : 0 0 / )
2856+ assert . match ( el . shadowRoot . textContent , / P M / i)
2857+ } )
2858+
2859+ test ( 'formats with 24-hour cycle when hour-cycle is h24' , async ( ) => {
2860+ const el = document . createElement ( 'relative-time' )
2861+ el . setAttribute ( 'datetime' , '2020-01-01T15:00:00.000Z' )
2862+ el . setAttribute ( 'time-zone' , 'UTC' )
2863+ el . setAttribute ( 'format' , 'datetime' )
2864+ el . setAttribute ( 'hour' , 'numeric' )
2865+ el . setAttribute ( 'minute' , '2-digit' )
2866+ el . setAttribute ( 'hour-cycle' , 'h24' )
2867+ await Promise . resolve ( )
2868+ assert . notMatch ( el . shadowRoot . textContent , / A M | P M / i)
2869+ } )
2870+
2871+ test ( 'title uses hour-cycle setting' , async ( ) => {
2872+ const el = document . createElement ( 'relative-time' )
2873+ el . setAttribute ( 'datetime' , '2020-01-01T15:00:00.000Z' )
2874+ el . setAttribute ( 'time-zone' , 'UTC' )
2875+ el . setAttribute ( 'hour-cycle' , 'h23' )
2876+ await Promise . resolve ( )
2877+ assert . notMatch ( el . getAttribute ( 'title' ) , / A M | P M / i)
2878+ assert . match ( el . getAttribute ( 'title' ) , / 1 5 / )
2879+ } )
2880+
2881+ test ( 'inherits hour-cycle from ancestor' , async ( ) => {
2882+ const el = document . createElement ( 'relative-time' )
2883+ el . setAttribute ( 'datetime' , '2020-01-01T15:00:00.000Z' )
2884+ el . setAttribute ( 'time-zone' , 'UTC' )
2885+ el . setAttribute ( 'format' , 'datetime' )
2886+ el . setAttribute ( 'hour' , 'numeric' )
2887+ el . setAttribute ( 'minute' , '2-digit' )
2888+ const div = document . createElement ( 'div' )
2889+ div . setAttribute ( 'hour-cycle' , 'h23' )
2890+ div . appendChild ( el )
2891+ document . body . appendChild ( div )
2892+ await Promise . resolve ( )
2893+ assert . notMatch ( el . shadowRoot . textContent , / A M | P M / i)
2894+ assert . match ( el . shadowRoot . textContent , / 1 5 : 0 0 / )
2895+ div . remove ( )
2896+ } )
2897+
2898+ test ( 'inherits hour-cycle from documentElement' , async ( ) => {
2899+ const el = document . createElement ( 'relative-time' )
2900+ el . setAttribute ( 'datetime' , '2020-01-01T15:00:00.000Z' )
2901+ el . setAttribute ( 'time-zone' , 'UTC' )
2902+ el . setAttribute ( 'format' , 'datetime' )
2903+ el . setAttribute ( 'hour' , 'numeric' )
2904+ el . setAttribute ( 'minute' , '2-digit' )
2905+ document . documentElement . setAttribute ( 'hour-cycle' , 'h23' )
2906+ await Promise . resolve ( )
2907+ assert . notMatch ( el . shadowRoot . textContent , / A M | P M / i)
2908+ assert . match ( el . shadowRoot . textContent , / 1 5 : 0 0 / )
2909+ document . documentElement . removeAttribute ( 'hour-cycle' )
2910+ } )
2911+
2912+ test ( 'element attribute overrides ancestor' , async ( ) => {
2913+ const el = document . createElement ( 'relative-time' )
2914+ el . setAttribute ( 'datetime' , '2020-01-01T15:00:00.000Z' )
2915+ el . setAttribute ( 'time-zone' , 'UTC' )
2916+ el . setAttribute ( 'format' , 'datetime' )
2917+ el . setAttribute ( 'hour' , 'numeric' )
2918+ el . setAttribute ( 'minute' , '2-digit' )
2919+ el . setAttribute ( 'hour-cycle' , 'h12' )
2920+ const div = document . createElement ( 'div' )
2921+ div . setAttribute ( 'hour-cycle' , 'h23' )
2922+ div . appendChild ( el )
2923+ document . body . appendChild ( div )
2924+ await Promise . resolve ( )
2925+ assert . match ( el . shadowRoot . textContent , / 3 : 0 0 / )
2926+ assert . match ( el . shadowRoot . textContent , / P M / i)
2927+ div . remove ( )
2928+ } )
2929+
2930+ test ( 're-renders when hour-cycle attribute changes' , async ( ) => {
2931+ const el = document . createElement ( 'relative-time' )
2932+ el . setAttribute ( 'datetime' , '2020-01-01T15:00:00.000Z' )
2933+ el . setAttribute ( 'time-zone' , 'UTC' )
2934+ el . setAttribute ( 'format' , 'datetime' )
2935+ el . setAttribute ( 'hour' , 'numeric' )
2936+ el . setAttribute ( 'minute' , '2-digit' )
2937+ el . setAttribute ( 'hour-cycle' , 'h12' )
2938+ await Promise . resolve ( )
2939+ assert . match ( el . shadowRoot . textContent , / P M / i)
2940+ el . setAttribute ( 'hour-cycle' , 'h23' )
2941+ await Promise . resolve ( )
2942+ assert . notMatch ( el . shadowRoot . textContent , / A M | P M / i)
2943+ assert . match ( el . shadowRoot . textContent , / 1 5 : 0 0 / )
2944+ } )
2945+ } )
2946+
28182947 suite ( '[timeZone]' , function ( ) {
28192948 test ( 'updates when the time-zone attribute is set' , async ( ) => {
28202949 const el = document . createElement ( 'relative-time' )
0 commit comments