[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"verticals":3,"article-intl-relativetimeformat-relative-dates":32,"related-intl-relativetimeformat-relative-dates":208,"code:js:true:jprx92":347,"code:js:true:sa46vr":348,"code:js:true:xxmtex":349,"code:js:true:1451yhs":350},[4,20],{"id":5,"slug":6,"name":7,"tagline":8,"description":9,"accentFrom":10,"accentTo":11,"icon":12,"defaultLocale":13,"locales":14,"features":16,"position":19},"019fe637-3d33-714b-b57f-23e163ffca0c","dev","Web Development","Build. Learn. Ship.","Practical courses, engineering-grade articles and open-source tools for people who ship.","violet-500","cyan-400","◇","en",[13,15],"fa",{"courses":17,"paths":17,"articles":17,"exams":18,"flashcards":18,"packages":17,"community":17,"certificates":17,"teams":17,"commerce":17},true,false,0,{"id":21,"slug":22,"name":23,"tagline":24,"description":25,"accentFrom":26,"accentTo":10,"icon":27,"defaultLocale":13,"locales":28,"features":30,"position":31},"019fe637-3dc2-754c-8657-0f175bfee7c6","lang","Languages","Learn a language the way you learn a codebase.","Structured paths, listening drills and spaced repetition that actually sticks.","amber-400","⌘",[13,15,29],"es",{"courses":18,"paths":18,"articles":17,"exams":18,"flashcards":17,"packages":18,"community":17,"certificates":17,"teams":18,"commerce":18},2,{"id":33,"slug":34,"title":35,"subtitle":36,"excerpt":37,"coverUrl":38,"locale":13,"readingMinutes":39,"publishedAt":40,"viewCount":41,"likeCount":19,"commentCount":19,"author":42,"vertical":47,"topic":48,"tags":51,"_count":63,"playground":65,"body":67,"bodyMd":190,"seo":191,"translationGroupId":195,"thread":196,"assessments":198,"translations":204,"quiz":206},"019fe660-edbb-714e-b0e8-8488ccbb6940","intl-relativetimeformat-relative-dates","You're installing date-fns for 'X hours ago'. `Intl.RelativeTimeFormat` does it natively.",null,"Most apps display relative timestamps — '3 minutes ago', 'last week'. Developers still reach for date-fns or moment for this. The Intl.RelativeTimeFormat API handles it natively, with full locale support and zero dependencies.","\u002Fmedia\u002Fcovers\u002Fintl-relativetimeformat-relative-dates.png",4,"2026-08-07T07:22:54.352Z",59,{"id":43,"name":44,"username":45,"avatarUrl":36,"headline":46},"019fe637-3c25-7088-9034-39c9f15dc3c8","Parsa Jiravand","parsa","Frontend engineer · building bestpractic",{"slug":6,"name":7,"accentFrom":10,"accentTo":11},{"slug":49,"name":50},"javascript","JavaScript",[52,54,57,60],{"slug":49,"name":53,"color":36},"Javascript",{"slug":55,"name":56,"color":36},"webdev","Webdev",{"slug":58,"name":59,"color":36},"frontend","Frontend",{"slug":61,"name":62,"color":36},"intl","Intl",{"assessments":64},1,{"slug":34,"title":66},"Intl.RelativeTimeFormat — interactive playground",{"blocks":68,"version":64},[69,73,77,83,86,90,93,97,100,103,106,110,113,116,119,123,126,130,133,136,139,142,145,148,151,154,157,160,163,166,169,172,175,178,181],{"id":70,"html":71,"type":72},"b1","\u003Cp>When a comment timestamp reads &quot;3 hours ago&quot; instead of a raw ISO string, users stay oriented without thinking about it. Most teams reach for \u003Ccode>date-fns\u002FformatDistanceToNow\u003C\u002Fcode> or \u003Ccode>moment().fromNow()\u003C\u002Fcode> to get there. Both pull in a full library for something the browser can do natively — and has been able to do since 2020.\u003C\u002Fp>","paragraph",{"id":74,"html":75,"text":75,"type":76,"level":31},"b2","The API","heading",{"id":78,"code":79,"type":80,"language":81,"highlight":82},"b3","const rtf = new Intl.RelativeTimeFormat('en', { numeric: 'auto' });\n\nrtf.format(-3, 'hour');   \u002F\u002F \"3 hours ago\"\nrtf.format(1, 'day');     \u002F\u002F \"tomorrow\"\nrtf.format(-1, 'day');    \u002F\u002F \"yesterday\"\nrtf.format(-2, 'week');   \u002F\u002F \"2 weeks ago\"\nrtf.format(3, 'month');   \u002F\u002F \"in 3 months\"","code","js",[],{"id":84,"html":85,"type":72},"b4","\u003Cp>Two arguments: a number (negative = past, positive = future) and a unit string. The constructor takes a locale identifier and an options object. That&#39;s the whole surface area.\u003C\u002Fp>",{"id":87,"html":88,"text":89,"type":76,"level":31},"b5","The \u003Ccode>numeric: &#39;auto&#39;\u003C\u002Fcode> option","The numeric: 'auto' option",{"id":91,"html":92,"type":72},"b6","\u003Cp>The second constructor argument controls whether you get &quot;1 day ago&quot; or &quot;yesterday&quot;. With \u003Ccode>numeric: &#39;always&#39;\u003C\u002Fcode> (the default), every value is formatted as a number. With \u003Ccode>numeric: &#39;auto&#39;\u003C\u002Fcode>, the formatter substitutes natural language when it&#39;s available for that locale:\u003C\u002Fp>",{"id":94,"code":95,"type":80,"language":81,"highlight":96},"b7","const always = new Intl.RelativeTimeFormat('en', { numeric: 'always' });\nconst auto   = new Intl.RelativeTimeFormat('en', { numeric: 'auto' });\n\nalways.format(-1, 'day');  \u002F\u002F \"1 day ago\"\nauto.format(-1, 'day');    \u002F\u002F \"yesterday\"\n\nalways.format(0, 'day');   \u002F\u002F \"in 0 days\"\nauto.format(0, 'day');     \u002F\u002F \"today\"\n\nalways.format(1, 'day');   \u002F\u002F \"in 1 day\"\nauto.format(1, 'day');     \u002F\u002F \"tomorrow\"",[],{"id":98,"html":99,"type":72},"b8","\u003Cp>In most UIs, \u003Ccode>numeric: &#39;auto&#39;\u003C\u002Fcode> is what you want. Saying &quot;yesterday&quot; is more natural than &quot;1 day ago&quot; and it costs nothing extra.\u003C\u002Fp>",{"id":101,"html":102,"text":102,"type":76,"level":31},"b9","Picking the right unit automatically",{"id":104,"html":105,"type":72},"b10","\u003Cp>The API doesn&#39;t pick the unit for you — you pass \u003Ccode>&#39;hour&#39;\u003C\u002Fcode> or \u003Ccode>&#39;week&#39;\u003C\u002Fcode> explicitly. That means you need a helper that looks at the elapsed duration and decides which unit to use. Ten lines:\u003C\u002Fp>",{"id":107,"code":108,"type":80,"language":81,"highlight":109},"b11","const rtf = new Intl.RelativeTimeFormat('en', { numeric: 'auto' });\n\nconst THRESHOLDS = [\n  { unit: 'year',   ms: 365 * 24 * 60 * 60 * 1000 },\n  { unit: 'month',  ms:  30 * 24 * 60 * 60 * 1000 },\n  { unit: 'week',   ms:   7 * 24 * 60 * 60 * 1000 },\n  { unit: 'day',    ms:       24 * 60 * 60 * 1000  },\n  { unit: 'hour',   ms:            60 * 60 * 1000  },\n  { unit: 'minute', ms:                 60 * 1000  },\n  { unit: 'second', ms:                      1000  },\n];\n\nfunction timeAgo(date) {\n  const diffMs = date - Date.now();\n  for (const { unit, ms } of THRESHOLDS) {\n    if (Math.abs(diffMs) >= ms) {\n      return rtf.format(Math.round(diffMs \u002F ms), unit);\n    }\n  }\n  return rtf.format(0, 'second'); \u002F\u002F \"just now\"\n}\n\ntimeAgo(new Date(Date.now() - 2 * 60 * 60 * 1000)); \u002F\u002F \"2 hours ago\"\ntimeAgo(new Date(Date.now() + 3 * 24 * 60 * 60 * 1000)); \u002F\u002F \"in 3 days\"\ntimeAgo(new Date(Date.now() - 45 * 1000)); \u002F\u002F \"45 seconds ago\"",[],{"id":111,"html":112,"type":72},"b12","\u003Cp>You adjust the thresholds to your app&#39;s conventions — some UIs show minutes up to 90, others switch to hours at 60. The formatter handles the phrasing; the thresholds handle the unit selection.\u003C\u002Fp>",{"id":114,"html":115,"text":115,"type":76,"level":31},"b13","Locale support comes for free",{"id":117,"html":118,"type":72},"b14","\u003Cp>The formatter respects locale — the same code that prints &quot;3 hours ago&quot; in English prints &quot;il y a 3 heures&quot; in French, &quot;vor 3 Stunden&quot; in German, and &quot;۳ ساعت پیش&quot; in Persian, without any translation strings in your bundle.\u003C\u002Fp>",{"id":120,"code":121,"type":80,"language":81,"highlight":122},"b15","const locales = ['en', 'fr', 'de', 'ja', 'ar'];\nconst twoHoursAgo = -2;\n\nfor (const locale of locales) {\n  const rtf = new Intl.RelativeTimeFormat(locale, { numeric: 'auto' });\n  console.log(`${locale}: ${rtf.format(twoHoursAgo, 'hour')}`);\n}\n\u002F\u002F en: 2 hours ago\n\u002F\u002F fr: il y a 2 heures\n\u002F\u002F de: vor 2 Stunden\n\u002F\u002F ja: 2 時間前\n\u002F\u002F ar: قبل ساعتين",[],{"id":124,"html":125,"type":72},"b16","\u003Cp>Most date libraries ship locale data as separate imports or packages — kilobytes of JSON per language. \u003Ccode>Intl.RelativeTimeFormat\u003C\u002Fcode> uses the locale data already in the JavaScript engine. Nothing extra to load.\u003C\u002Fp>",{"id":127,"html":128,"text":129,"type":76,"level":31},"b17","What it doesn&#39;t do","What it doesn't do",{"id":131,"html":132,"type":72},"b18","\u003Cp>\u003Ccode>Intl.RelativeTimeFormat\u003C\u002Fcode> formats a pre-computed duration. It doesn&#39;t parse date strings, calculate diffs, or understand &quot;last Monday.&quot; If you need date arithmetic — adding months, finding the start of a week, working with time zones — you still need a library or the upcoming \u003Ccode>Temporal\u003C\u002Fcode> API. But if you already have two timestamps and just want to display the difference as human text, \u003Ccode>Intl.RelativeTimeFormat\u003C\u002Fcode> is the right tool.\u003C\u002Fp>",{"id":134,"html":135,"text":135,"type":76,"level":31},"b19","Browser support",{"id":137,"html":138,"type":72},"b20","\u003Cp>\u003Ccode>Intl.RelativeTimeFormat\u003C\u002Fcode> is \u003Cstrong>Baseline 2020\u003C\u002Fstrong>: Chrome 71 (2018), Firefox 65 (2019), Safari 14 (2020), Node.js 12. It&#39;s been in every major environment for years. No polyfill needed for any currently-supported browser.\u003C\u002Fp>",{"id":140,"html":141,"type":72},"b21","\u003C!-- playground:start -->",{"id":143,"html":144,"text":144,"type":76,"level":31},"b22","🎮 Try it yourself",{"id":146,"html":147,"type":72},"b23","\u003Cp>\u003Cstrong>\u003Ca href=\"https:\u002F\u002Fbestpractic.org\u002Fblog\u002Fintl-relativetimeformat-relative-dates\u002Fplayground\">▶️ Open the interactive playground →\u003C\u002Fa>\u003C\u002Fstrong>\u003C\u002Fp>",{"id":149,"html":150,"type":72},"b24","\u003Cp>\u003Cem>Runs right in your browser — poke at it and watch the concept react live.\u003C\u002Fem>\u003C\u002Fp>",{"id":152,"html":153,"type":72},"b25","\u003C!-- playground:end -->",{"id":155,"html":156,"type":72},"b26","\u003C!-- quiz:start -->",{"id":158,"html":159,"text":159,"type":76,"level":31},"b27","🧠 Test yourself",{"id":161,"html":162,"type":72},"b28","\u003Cp>Think it clicked? \u003Cstrong>\u003Ca href=\"https:\u002F\u002Fbestpractic.org\u002Fblog\u002Fintl-relativetimeformat-relative-dates\u002Fquiz\">Take the 9-question quiz →\u003C\u002Fa>\u003C\u002Fstrong>\u003C\u002Fp>",{"id":164,"html":165,"type":72},"b29","\u003Cp>\u003Cem>Instant feedback, a hint on every question, and an explanation for each answer — right or wrong.\u003C\u002Fem>\u003C\u002Fp>",{"id":167,"html":168,"type":72},"b30","\u003C!-- quiz:end -->",{"id":170,"html":171,"text":171,"type":76,"level":31},"b31","The takeaway",{"id":173,"html":174,"type":72},"b32","\u003Cp>Search your codebase for \u003Ccode>formatDistanceToNow\u003C\u002Fcode>, \u003Ccode>fromNow()\u003C\u002Fcode>, or any home-grown &quot;X minutes ago&quot; function. If the logic is &quot;compute a diff, format it as human text,&quot; replace it with \u003Ccode>Intl.RelativeTimeFormat\u003C\u002Fcode> and a unit-picking helper. You get correct pluralization, locale-aware phrasing, and natural-language output like &quot;yesterday&quot; and &quot;tomorrow&quot; — with no added dependency and no locale bundle to manage.\u003C\u002Fp>",{"id":176,"type":177},"b33","divider",{"id":179,"html":180,"type":72},"b34","\u003Cp>\u003Cem>Thanks for reading! Let&#39;s stay connected:\u003C\u002Fem>\u003C\u002Fp>",{"id":182,"type":183,"items":184,"ordered":18},"b35","list",[185,186,187,188,189],"⭐ \u003Cstrong>GitHub\u003C\u002Fstrong> — follow me and star the projects: \u003Ca href=\"https:\u002F\u002Fgithub.com\u002Fparsajiravand\">github.com\u002Fparsajiravand\u003C\u002Fa>","💬 \u003Cstrong>Discord\u003C\u002Fstrong> — join the frontend best-practices community: \u003Ca href=\"https:\u002F\u002Fdiscord.gg\u002Fd9KRhuAwQ\">discord.gg\u002Fd9KRhuAwQ\u003C\u002Fa>","📸 \u003Cstrong>Instagram\u003C\u002Fstrong> — frontend best practices, daily: \u003Ca href=\"https:\u002F\u002Fwww.instagram.com\u002Fbestpractice___\u002F\">@bestpractice___\u003C\u002Fa>","💼 \u003Cstrong>LinkedIn\u003C\u002Fstrong> — \u003Ca href=\"https:\u002F\u002Fwww.linkedin.com\u002Fin\u002Fparsa-jiravand\u002F\">linkedin.com\u002Fin\u002Fparsa-jiravand\u003C\u002Fa>","✉️ \u003Cstrong>Email\u003C\u002Fstrong> (work &amp; contract inquiries): \u003Ca href=\"mailto:bestpractice2026@gmail.com\">bestpractice2026@gmail.com\u003C\u002Fa>","When a comment timestamp reads \"3 hours ago\" instead of a raw ISO string, users stay oriented without thinking about it. Most teams reach for `date-fns\u002FformatDistanceToNow` or `moment().fromNow()` to get there. Both pull in a full library for something the browser can do natively — and has been able to do since 2020.\n\n## The API\n\n```js\nconst rtf = new Intl.RelativeTimeFormat('en', { numeric: 'auto' });\n\nrtf.format(-3, 'hour');   \u002F\u002F \"3 hours ago\"\nrtf.format(1, 'day');     \u002F\u002F \"tomorrow\"\nrtf.format(-1, 'day');    \u002F\u002F \"yesterday\"\nrtf.format(-2, 'week');   \u002F\u002F \"2 weeks ago\"\nrtf.format(3, 'month');   \u002F\u002F \"in 3 months\"\n```\n\nTwo arguments: a number (negative = past, positive = future) and a unit string. The constructor takes a locale identifier and an options object. That's the whole surface area.\n\n## The `numeric: 'auto'` option\n\nThe second constructor argument controls whether you get \"1 day ago\" or \"yesterday\". With `numeric: 'always'` (the default), every value is formatted as a number. With `numeric: 'auto'`, the formatter substitutes natural language when it's available for that locale:\n\n```js\nconst always = new Intl.RelativeTimeFormat('en', { numeric: 'always' });\nconst auto   = new Intl.RelativeTimeFormat('en', { numeric: 'auto' });\n\nalways.format(-1, 'day');  \u002F\u002F \"1 day ago\"\nauto.format(-1, 'day');    \u002F\u002F \"yesterday\"\n\nalways.format(0, 'day');   \u002F\u002F \"in 0 days\"\nauto.format(0, 'day');     \u002F\u002F \"today\"\n\nalways.format(1, 'day');   \u002F\u002F \"in 1 day\"\nauto.format(1, 'day');     \u002F\u002F \"tomorrow\"\n```\n\nIn most UIs, `numeric: 'auto'` is what you want. Saying \"yesterday\" is more natural than \"1 day ago\" and it costs nothing extra.\n\n## Picking the right unit automatically\n\nThe API doesn't pick the unit for you — you pass `'hour'` or `'week'` explicitly. That means you need a helper that looks at the elapsed duration and decides which unit to use. Ten lines:\n\n```js\nconst rtf = new Intl.RelativeTimeFormat('en', { numeric: 'auto' });\n\nconst THRESHOLDS = [\n  { unit: 'year',   ms: 365 * 24 * 60 * 60 * 1000 },\n  { unit: 'month',  ms:  30 * 24 * 60 * 60 * 1000 },\n  { unit: 'week',   ms:   7 * 24 * 60 * 60 * 1000 },\n  { unit: 'day',    ms:       24 * 60 * 60 * 1000  },\n  { unit: 'hour',   ms:            60 * 60 * 1000  },\n  { unit: 'minute', ms:                 60 * 1000  },\n  { unit: 'second', ms:                      1000  },\n];\n\nfunction timeAgo(date) {\n  const diffMs = date - Date.now();\n  for (const { unit, ms } of THRESHOLDS) {\n    if (Math.abs(diffMs) >= ms) {\n      return rtf.format(Math.round(diffMs \u002F ms), unit);\n    }\n  }\n  return rtf.format(0, 'second'); \u002F\u002F \"just now\"\n}\n\ntimeAgo(new Date(Date.now() - 2 * 60 * 60 * 1000)); \u002F\u002F \"2 hours ago\"\ntimeAgo(new Date(Date.now() + 3 * 24 * 60 * 60 * 1000)); \u002F\u002F \"in 3 days\"\ntimeAgo(new Date(Date.now() - 45 * 1000)); \u002F\u002F \"45 seconds ago\"\n```\n\nYou adjust the thresholds to your app's conventions — some UIs show minutes up to 90, others switch to hours at 60. The formatter handles the phrasing; the thresholds handle the unit selection.\n\n## Locale support comes for free\n\nThe formatter respects locale — the same code that prints \"3 hours ago\" in English prints \"il y a 3 heures\" in French, \"vor 3 Stunden\" in German, and \"۳ ساعت پیش\" in Persian, without any translation strings in your bundle.\n\n```js\nconst locales = ['en', 'fr', 'de', 'ja', 'ar'];\nconst twoHoursAgo = -2;\n\nfor (const locale of locales) {\n  const rtf = new Intl.RelativeTimeFormat(locale, { numeric: 'auto' });\n  console.log(`${locale}: ${rtf.format(twoHoursAgo, 'hour')}`);\n}\n\u002F\u002F en: 2 hours ago\n\u002F\u002F fr: il y a 2 heures\n\u002F\u002F de: vor 2 Stunden\n\u002F\u002F ja: 2 時間前\n\u002F\u002F ar: قبل ساعتين\n```\n\nMost date libraries ship locale data as separate imports or packages — kilobytes of JSON per language. `Intl.RelativeTimeFormat` uses the locale data already in the JavaScript engine. Nothing extra to load.\n\n## What it doesn't do\n\n`Intl.RelativeTimeFormat` formats a pre-computed duration. It doesn't parse date strings, calculate diffs, or understand \"last Monday.\" If you need date arithmetic — adding months, finding the start of a week, working with time zones — you still need a library or the upcoming `Temporal` API. But if you already have two timestamps and just want to display the difference as human text, `Intl.RelativeTimeFormat` is the right tool.\n\n## Browser support\n\n`Intl.RelativeTimeFormat` is **Baseline 2020**: Chrome 71 (2018), Firefox 65 (2019), Safari 14 (2020), Node.js 12. It's been in every major environment for years. No polyfill needed for any currently-supported browser.\n\n\n\u003C!-- playground:start -->\n\n## 🎮 Try it yourself\n\n**[▶️ Open the interactive playground →](https:\u002F\u002Fbestpractic.org\u002Fblog\u002Fintl-relativetimeformat-relative-dates\u002Fplayground)**\n\n_Runs right in your browser — poke at it and watch the concept react live._\n\n\u003C!-- playground:end -->\n\n\u003C!-- quiz:start -->\n\n## 🧠 Test yourself\n\nThink it clicked? **[Take the 9-question quiz →](https:\u002F\u002Fbestpractic.org\u002Fblog\u002Fintl-relativetimeformat-relative-dates\u002Fquiz)**\n\n_Instant feedback, a hint on every question, and an explanation for each answer — right or wrong._\n\n\u003C!-- quiz:end -->\n## The takeaway\n\nSearch your codebase for `formatDistanceToNow`, `fromNow()`, or any home-grown \"X minutes ago\" function. If the logic is \"compute a diff, format it as human text,\" replace it with `Intl.RelativeTimeFormat` and a unit-picking helper. You get correct pluralization, locale-aware phrasing, and natural-language output like \"yesterday\" and \"tomorrow\" — with no added dependency and no locale bundle to manage.\n\n---\n\n*Thanks for reading! Let's stay connected:*\n\n- ⭐ **GitHub** — follow me and star the projects: [github.com\u002Fparsajiravand](https:\u002F\u002Fgithub.com\u002Fparsajiravand)\n- 💬 **Discord** — join the frontend best-practices community: [discord.gg\u002Fd9KRhuAwQ](https:\u002F\u002Fdiscord.gg\u002Fd9KRhuAwQ)\n- 📸 **Instagram** — frontend best practices, daily: [@bestpractice___](https:\u002F\u002Fwww.instagram.com\u002Fbestpractice___\u002F)\n- 💼 **LinkedIn** — [linkedin.com\u002Fin\u002Fparsa-jiravand](https:\u002F\u002Fwww.linkedin.com\u002Fin\u002Fparsa-jiravand\u002F)\n- ✉️ **Email** (work & contract inquiries): [bestpractice2026@gmail.com](mailto:bestpractice2026@gmail.com)",{"title":192,"canonical":193,"description":194},"You're installing date-fns for 'X hours ago'. `Intl.RelativeTimeFormat","https:\u002F\u002Fbestpractic.org\u002Fblog\u002Fintl-relativetimeformat-relative-dates","Most apps display relative timestamps — '3 minutes ago', 'last week'. Developers still reach for date-fns or moment for this. The Intl.RelativeTimeFormat API handles it natively, w","019fe660-edbb-714e-b0e8-886fc45deaa0",{"id":197,"locked":18},"019fe660-f4c3-720e-902c-d8822ceccdd3",[199],{"id":200,"slug":34,"title":201,"_count":202},"019fe776-c669-72d9-97e1-f3bdd80238c1","Intl.RelativeTimeFormat — relative timestamps without a library",{"questions":203},9,[205],{"locale":13,"slug":34},{"id":200,"slug":34,"title":201,"_count":207,"questionCount":203},{"questions":203},{"items":209,"meta":344},[210,231,251,271,291,313,332],{"id":211,"slug":212,"title":213,"subtitle":36,"excerpt":214,"coverUrl":215,"locale":13,"readingMinutes":39,"publishedAt":216,"viewCount":217,"likeCount":19,"commentCount":19,"author":218,"vertical":219,"topic":220,"tags":223,"_count":229,"playground":230,"hasQuiz":17,"hasPlayground":17},"019ff19b-f763-70e0-abdf-eded59c8e69a","overscroll-behavior-scroll-containment","You're blocking touchmove events to contain scroll. `overscroll-behavior` does it natively.","When a scrollable container hits its edge, the page behind it starts scrolling too. Developers block this with JavaScript event handlers or body overflow tricks. overscroll-behavior is the CSS property that turns off scroll chaining in one line.","\u002Fmedia\u002Fcovers\u002Foverscroll-behavior-scroll-containment.png","2026-08-12T07:38:53.786Z",52,{"id":43,"name":44,"username":45,"avatarUrl":36,"headline":46},{"slug":6,"name":7,"accentFrom":10,"accentTo":11},{"slug":221,"name":222},"css","CSS",[224,226,227,228],{"slug":221,"name":225,"color":36},"Css",{"slug":55,"name":56,"color":36},{"slug":58,"name":59,"color":36},{"slug":49,"name":53,"color":36},{"assessments":64},{"slug":212},{"id":232,"slug":233,"title":234,"subtitle":36,"excerpt":235,"coverUrl":236,"locale":13,"readingMinutes":39,"publishedAt":237,"viewCount":238,"likeCount":19,"commentCount":19,"author":239,"vertical":240,"topic":241,"tags":242,"_count":249,"playground":250,"hasQuiz":17,"hasPlayground":17},"019ff19b-f68d-77ea-9a2c-70e14c5c7a05","mutation-observer-dom-change-detection","You're polling setInterval to detect DOM changes. `MutationObserver` fires when they happen.","Watching for DOM mutations with setInterval or custom event dispatch is fragile and imprecise. The MutationObserver API delivers a callback exactly when attributes, text content, or child elements change — with full control over which types of mutations you watch.","\u002Fmedia\u002Fcovers\u002Fmutation-observer-dom-change-detection.png","2026-08-11T15:48:01.781Z",334,{"id":43,"name":44,"username":45,"avatarUrl":36,"headline":46},{"slug":6,"name":7,"accentFrom":10,"accentTo":11},{"slug":49,"name":50},[243,244,245,246],{"slug":49,"name":53,"color":36},{"slug":55,"name":56,"color":36},{"slug":58,"name":59,"color":36},{"slug":247,"name":248,"color":36},"dom","Dom",{"assessments":64},{"slug":233},{"id":252,"slug":253,"title":254,"subtitle":36,"excerpt":255,"coverUrl":256,"locale":13,"readingMinutes":39,"publishedAt":257,"viewCount":258,"likeCount":19,"commentCount":19,"author":259,"vertical":260,"topic":261,"tags":262,"_count":269,"playground":270,"hasQuiz":17,"hasPlayground":17},"019ff19b-f5b3-7569-8cc8-22b1136aa9b2","compressionstream-native-gzip","You're importing pako to gzip data. `CompressionStream` does it natively.","pako is one of npm's most downloaded packages — pulled in by thousands of projects to compress data before storing or sending it. CompressionStream and DecompressionStream do the same job natively, in any modern browser and Node.js 18+, with no dependencies and native C-speed execution.","\u002Fmedia\u002Fcovers\u002Fcompressionstream-native-gzip.png","2026-08-10T07:49:27.000Z",193,{"id":43,"name":44,"username":45,"avatarUrl":36,"headline":46},{"slug":6,"name":7,"accentFrom":10,"accentTo":11},{"slug":49,"name":50},[263,264,265,266],{"slug":49,"name":53,"color":36},{"slug":55,"name":56,"color":36},{"slug":58,"name":59,"color":36},{"slug":267,"name":268,"color":36},"performance","Performance",{"assessments":64},{"slug":253},{"id":272,"slug":273,"title":274,"subtitle":36,"excerpt":275,"coverUrl":276,"locale":13,"readingMinutes":39,"publishedAt":277,"viewCount":278,"likeCount":19,"commentCount":19,"author":279,"vertical":280,"topic":281,"tags":282,"_count":289,"playground":290,"hasQuiz":17,"hasPlayground":17},"019fe660-fcbe-745e-a443-5ae33ac10aaf","broadcast-channel-cross-tab-messaging","Stop using the localStorage hack to sync browser tabs. BroadcastChannel does it natively.","Syncing state across browser tabs with localStorage events is a widely-used trick that requires JSON.stringify, event filtering, and careful cleanup. The Broadcast Channel API delivers messages between tabs directly, with none of the side effects.","\u002Fmedia\u002Fcovers\u002Fbroadcast-channel-cross-tab-messaging.png","2026-08-09T07:02:41.629Z",203,{"id":43,"name":44,"username":45,"avatarUrl":36,"headline":46},{"slug":6,"name":7,"accentFrom":10,"accentTo":11},{"slug":49,"name":50},[283,284,285,286],{"slug":49,"name":53,"color":36},{"slug":55,"name":56,"color":36},{"slug":58,"name":59,"color":36},{"slug":287,"name":288,"color":36},"apis","Apis",{"assessments":64},{"slug":273},{"id":292,"slug":293,"title":294,"subtitle":36,"excerpt":295,"coverUrl":296,"locale":13,"readingMinutes":297,"publishedAt":298,"viewCount":299,"likeCount":19,"commentCount":19,"author":300,"vertical":301,"topic":302,"tags":305,"_count":311,"playground":312,"hasQuiz":17,"hasPlayground":17},"019ff19b-f388-73f8-aa5b-93d73337d6fd","dialog-element-native-modal","You built your modal with a `\u003Cdiv>` and a focus trap library. The native `\u003Cdialog>` does all of that.","The `\u003Cdialog>` element ships with focus trapping, Escape-to-close, backdrop rendering, and correct ARIA semantics — no library, no boilerplate. It's been Baseline since 2022.","\u002Fmedia\u002Fcovers\u002Fdialog-element-native-modal.png",5,"2026-08-08T07:00:10.810Z",178,{"id":43,"name":44,"username":45,"avatarUrl":36,"headline":46},{"slug":6,"name":7,"accentFrom":10,"accentTo":11},{"slug":303,"name":304},"html","HTML",[306,308,309,310],{"slug":303,"name":307,"color":36},"Html",{"slug":55,"name":56,"color":36},{"slug":58,"name":59,"color":36},{"slug":49,"name":53,"color":36},{"assessments":64},{"slug":293},{"id":314,"slug":315,"title":316,"subtitle":36,"excerpt":317,"coverUrl":318,"locale":13,"readingMinutes":319,"publishedAt":320,"viewCount":321,"likeCount":19,"commentCount":19,"author":322,"vertical":323,"topic":324,"tags":325,"_count":330,"playground":331,"hasQuiz":17,"hasPlayground":17},"019fe660-f552-73c8-9f52-d036e672c053","crypto-randomuuid-native-uuid","Stop importing `uuid`. `crypto.randomUUID()` has been native since 2021.","The `uuid` package is downloaded hundreds of millions of times a week. Most installs exist to call uuid\u002Fv4 — exactly what `crypto.randomUUID()` does natively, with no import, no bundle cost, and guaranteed cryptographic randomness.","\u002Fmedia\u002Fcovers\u002Fcrypto-randomuuid-native-uuid.png",3,"2026-08-08T07:00:09.988Z",160,{"id":43,"name":44,"username":45,"avatarUrl":36,"headline":46},{"slug":6,"name":7,"accentFrom":10,"accentTo":11},{"slug":49,"name":50},[326,327,328,329],{"slug":49,"name":53,"color":36},{"slug":55,"name":56,"color":36},{"slug":58,"name":59,"color":36},{"slug":267,"name":268,"color":36},{"assessments":64},{"slug":315},{"id":33,"slug":34,"title":35,"subtitle":36,"excerpt":37,"coverUrl":38,"locale":13,"readingMinutes":39,"publishedAt":40,"viewCount":333,"likeCount":19,"commentCount":19,"author":334,"vertical":335,"topic":336,"tags":337,"_count":342,"playground":343,"hasQuiz":17,"hasPlayground":17},60,{"id":43,"name":44,"username":45,"avatarUrl":36,"headline":46},{"slug":6,"name":7,"accentFrom":10,"accentTo":11},{"slug":49,"name":50},[338,339,340,341],{"slug":49,"name":53,"color":36},{"slug":55,"name":56,"color":36},{"slug":58,"name":59,"color":36},{"slug":61,"name":62,"color":36},{"assessments":64},{"slug":34},{"page":64,"perPage":345,"total":346,"totalPages":345},7,46,"\u003Cdiv class=\"shj shj-lang-js shj-multiline\" data-lang=\"js\">\u003Cdiv class=\"shj-scroll\">\u003Cdiv class=\"shj-numbers\">\u003Cdiv>1\u003C\u002Fdiv>\u003Cdiv>2\u003C\u002Fdiv>\u003Cdiv>3\u003C\u002Fdiv>\u003Cdiv>4\u003C\u002Fdiv>\u003Cdiv>5\u003C\u002Fdiv>\u003Cdiv>6\u003C\u002Fdiv>\u003Cdiv>7\u003C\u002Fdiv>\u003C\u002Fdiv>\u003Cdiv class=\"shj-code\">\u003Cspan class=\"shj-kwd\">const\u003C\u002Fspan> rtf \u003Cspan class=\"shj-oper\">=\u003C\u002Fspan> \u003Cspan class=\"shj-kwd\">new\u003C\u002Fspan> \u003Cspan class=\"shj-class\">Intl\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>\u003Cspan class=\"shj-class\">RelativeTimeFormat\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-str\">'en'\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">,\u003C\u002Fspan> \u003Cspan class=\"shj-bracket\">{\u003C\u002Fspan> numeric\u003Cspan class=\"shj-oper\">:\u003C\u002Fspan> \u003Cspan class=\"shj-str\">'auto'\u003C\u002Fspan> \u003Cspan class=\"shj-bracket\">}\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>;\n\nrtf\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>\u003Cspan class=\"shj-func\">format\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">-\u003C\u002Fspan>\u003Cspan class=\"shj-num\">3\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">,\u003C\u002Fspan> \u003Cspan class=\"shj-str\">'hour'\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>;   \u003Cspan class=\"shj-cmnt\">\u002F\u002F \"3 hours ago\"\n\u003C\u002Fspan>rtf\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>\u003Cspan class=\"shj-func\">format\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-num\">1\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">,\u003C\u002Fspan> \u003Cspan class=\"shj-str\">'day'\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>;     \u003Cspan class=\"shj-cmnt\">\u002F\u002F \"tomorrow\"\n\u003C\u002Fspan>rtf\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>\u003Cspan class=\"shj-func\">format\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">-\u003C\u002Fspan>\u003Cspan class=\"shj-num\">1\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">,\u003C\u002Fspan> \u003Cspan class=\"shj-str\">'day'\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>;    \u003Cspan class=\"shj-cmnt\">\u002F\u002F \"yesterday\"\n\u003C\u002Fspan>rtf\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>\u003Cspan class=\"shj-func\">format\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">-\u003C\u002Fspan>\u003Cspan class=\"shj-num\">2\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">,\u003C\u002Fspan> \u003Cspan class=\"shj-str\">'week'\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>;   \u003Cspan class=\"shj-cmnt\">\u002F\u002F \"2 weeks ago\"\n\u003C\u002Fspan>rtf\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>\u003Cspan class=\"shj-func\">format\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-num\">3\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">,\u003C\u002Fspan> \u003Cspan class=\"shj-str\">'month'\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>;   \u003Cspan class=\"shj-cmnt\">\u002F\u002F \"in 3 months\"\u003C\u002Fspan>\u003C\u002Fdiv>\u003C\u002Fdiv>\u003C\u002Fdiv>","\u003Cdiv class=\"shj shj-lang-js shj-multiline\" data-lang=\"js\">\u003Cdiv class=\"shj-scroll\">\u003Cdiv class=\"shj-numbers\">\u003Cdiv>1\u003C\u002Fdiv>\u003Cdiv>2\u003C\u002Fdiv>\u003Cdiv>3\u003C\u002Fdiv>\u003Cdiv>4\u003C\u002Fdiv>\u003Cdiv>5\u003C\u002Fdiv>\u003Cdiv>6\u003C\u002Fdiv>\u003Cdiv>7\u003C\u002Fdiv>\u003Cdiv>8\u003C\u002Fdiv>\u003Cdiv>9\u003C\u002Fdiv>\u003Cdiv>10\u003C\u002Fdiv>\u003Cdiv>11\u003C\u002Fdiv>\u003C\u002Fdiv>\u003Cdiv class=\"shj-code\">\u003Cspan class=\"shj-kwd\">const\u003C\u002Fspan> always \u003Cspan class=\"shj-oper\">=\u003C\u002Fspan> \u003Cspan class=\"shj-kwd\">new\u003C\u002Fspan> \u003Cspan class=\"shj-class\">Intl\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>\u003Cspan class=\"shj-class\">RelativeTimeFormat\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-str\">'en'\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">,\u003C\u002Fspan> \u003Cspan class=\"shj-bracket\">{\u003C\u002Fspan> numeric\u003Cspan class=\"shj-oper\">:\u003C\u002Fspan> \u003Cspan class=\"shj-str\">'always'\u003C\u002Fspan> \u003Cspan class=\"shj-bracket\">}\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>;\n\u003Cspan class=\"shj-kwd\">const\u003C\u002Fspan> auto   \u003Cspan class=\"shj-oper\">=\u003C\u002Fspan> \u003Cspan class=\"shj-kwd\">new\u003C\u002Fspan> \u003Cspan class=\"shj-class\">Intl\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>\u003Cspan class=\"shj-class\">RelativeTimeFormat\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-str\">'en'\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">,\u003C\u002Fspan> \u003Cspan class=\"shj-bracket\">{\u003C\u002Fspan> numeric\u003Cspan class=\"shj-oper\">:\u003C\u002Fspan> \u003Cspan class=\"shj-str\">'auto'\u003C\u002Fspan> \u003Cspan class=\"shj-bracket\">}\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>;\n\nalways\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>\u003Cspan class=\"shj-func\">format\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">-\u003C\u002Fspan>\u003Cspan class=\"shj-num\">1\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">,\u003C\u002Fspan> \u003Cspan class=\"shj-str\">'day'\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>;  \u003Cspan class=\"shj-cmnt\">\u002F\u002F \"1 day ago\"\n\u003C\u002Fspan>auto\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>\u003Cspan class=\"shj-func\">format\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">-\u003C\u002Fspan>\u003Cspan class=\"shj-num\">1\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">,\u003C\u002Fspan> \u003Cspan class=\"shj-str\">'day'\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>;    \u003Cspan class=\"shj-cmnt\">\u002F\u002F \"yesterday\"\n\u003C\u002Fspan>\nalways\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>\u003Cspan class=\"shj-func\">format\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-num\">0\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">,\u003C\u002Fspan> \u003Cspan class=\"shj-str\">'day'\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>;   \u003Cspan class=\"shj-cmnt\">\u002F\u002F \"in 0 days\"\n\u003C\u002Fspan>auto\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>\u003Cspan class=\"shj-func\">format\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-num\">0\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">,\u003C\u002Fspan> \u003Cspan class=\"shj-str\">'day'\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>;     \u003Cspan class=\"shj-cmnt\">\u002F\u002F \"today\"\n\u003C\u002Fspan>\nalways\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>\u003Cspan class=\"shj-func\">format\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-num\">1\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">,\u003C\u002Fspan> \u003Cspan class=\"shj-str\">'day'\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>;   \u003Cspan class=\"shj-cmnt\">\u002F\u002F \"in 1 day\"\n\u003C\u002Fspan>auto\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>\u003Cspan class=\"shj-func\">format\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-num\">1\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">,\u003C\u002Fspan> \u003Cspan class=\"shj-str\">'day'\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>;     \u003Cspan class=\"shj-cmnt\">\u002F\u002F \"tomorrow\"\u003C\u002Fspan>\u003C\u002Fdiv>\u003C\u002Fdiv>\u003C\u002Fdiv>","\u003Cdiv class=\"shj shj-lang-js shj-multiline\" data-lang=\"js\">\u003Cdiv class=\"shj-scroll\">\u003Cdiv class=\"shj-numbers\">\u003Cdiv>1\u003C\u002Fdiv>\u003Cdiv>2\u003C\u002Fdiv>\u003Cdiv>3\u003C\u002Fdiv>\u003Cdiv>4\u003C\u002Fdiv>\u003Cdiv>5\u003C\u002Fdiv>\u003Cdiv>6\u003C\u002Fdiv>\u003Cdiv>7\u003C\u002Fdiv>\u003Cdiv>8\u003C\u002Fdiv>\u003Cdiv>9\u003C\u002Fdiv>\u003Cdiv>10\u003C\u002Fdiv>\u003Cdiv>11\u003C\u002Fdiv>\u003Cdiv>12\u003C\u002Fdiv>\u003Cdiv>13\u003C\u002Fdiv>\u003Cdiv>14\u003C\u002Fdiv>\u003Cdiv>15\u003C\u002Fdiv>\u003Cdiv>16\u003C\u002Fdiv>\u003Cdiv>17\u003C\u002Fdiv>\u003Cdiv>18\u003C\u002Fdiv>\u003Cdiv>19\u003C\u002Fdiv>\u003Cdiv>20\u003C\u002Fdiv>\u003Cdiv>21\u003C\u002Fdiv>\u003Cdiv>22\u003C\u002Fdiv>\u003Cdiv>23\u003C\u002Fdiv>\u003Cdiv>24\u003C\u002Fdiv>\u003Cdiv>25\u003C\u002Fdiv>\u003C\u002Fdiv>\u003Cdiv class=\"shj-code\">\u003Cspan class=\"shj-kwd\">const\u003C\u002Fspan> rtf \u003Cspan class=\"shj-oper\">=\u003C\u002Fspan> \u003Cspan class=\"shj-kwd\">new\u003C\u002Fspan> \u003Cspan class=\"shj-class\">Intl\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>\u003Cspan class=\"shj-class\">RelativeTimeFormat\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-str\">'en'\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">,\u003C\u002Fspan> \u003Cspan class=\"shj-bracket\">{\u003C\u002Fspan> numeric\u003Cspan class=\"shj-oper\">:\u003C\u002Fspan> \u003Cspan class=\"shj-str\">'auto'\u003C\u002Fspan> \u003Cspan class=\"shj-bracket\">}\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>;\n\n\u003Cspan class=\"shj-kwd\">const\u003C\u002Fspan> \u003Cspan class=\"shj-num\">THRESHOLDS\u003C\u002Fspan> \u003Cspan class=\"shj-oper\">=\u003C\u002Fspan> \u003Cspan class=\"shj-bracket\">[\u003C\u002Fspan>\n  \u003Cspan class=\"shj-bracket\">{\u003C\u002Fspan> unit\u003Cspan class=\"shj-oper\">:\u003C\u002Fspan> \u003Cspan class=\"shj-str\">'year'\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">,\u003C\u002Fspan>   ms\u003Cspan class=\"shj-oper\">:\u003C\u002Fspan> \u003Cspan class=\"shj-num\">365\u003C\u002Fspan> \u003Cspan class=\"shj-oper\">*\u003C\u002Fspan> \u003Cspan class=\"shj-num\">24\u003C\u002Fspan> \u003Cspan class=\"shj-oper\">*\u003C\u002Fspan> \u003Cspan class=\"shj-num\">60\u003C\u002Fspan> \u003Cspan class=\"shj-oper\">*\u003C\u002Fspan> \u003Cspan class=\"shj-num\">60\u003C\u002Fspan> \u003Cspan class=\"shj-oper\">*\u003C\u002Fspan> \u003Cspan class=\"shj-num\">1000\u003C\u002Fspan> \u003Cspan class=\"shj-bracket\">}\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">,\u003C\u002Fspan>\n  \u003Cspan class=\"shj-bracket\">{\u003C\u002Fspan> unit\u003Cspan class=\"shj-oper\">:\u003C\u002Fspan> \u003Cspan class=\"shj-str\">'month'\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">,\u003C\u002Fspan>  ms\u003Cspan class=\"shj-oper\">:\u003C\u002Fspan>  \u003Cspan class=\"shj-num\">30\u003C\u002Fspan> \u003Cspan class=\"shj-oper\">*\u003C\u002Fspan> \u003Cspan class=\"shj-num\">24\u003C\u002Fspan> \u003Cspan class=\"shj-oper\">*\u003C\u002Fspan> \u003Cspan class=\"shj-num\">60\u003C\u002Fspan> \u003Cspan class=\"shj-oper\">*\u003C\u002Fspan> \u003Cspan class=\"shj-num\">60\u003C\u002Fspan> \u003Cspan class=\"shj-oper\">*\u003C\u002Fspan> \u003Cspan class=\"shj-num\">1000\u003C\u002Fspan> \u003Cspan class=\"shj-bracket\">}\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">,\u003C\u002Fspan>\n  \u003Cspan class=\"shj-bracket\">{\u003C\u002Fspan> unit\u003Cspan class=\"shj-oper\">:\u003C\u002Fspan> \u003Cspan class=\"shj-str\">'week'\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">,\u003C\u002Fspan>   ms\u003Cspan class=\"shj-oper\">:\u003C\u002Fspan>   \u003Cspan class=\"shj-num\">7\u003C\u002Fspan> \u003Cspan class=\"shj-oper\">*\u003C\u002Fspan> \u003Cspan class=\"shj-num\">24\u003C\u002Fspan> \u003Cspan class=\"shj-oper\">*\u003C\u002Fspan> \u003Cspan class=\"shj-num\">60\u003C\u002Fspan> \u003Cspan class=\"shj-oper\">*\u003C\u002Fspan> \u003Cspan class=\"shj-num\">60\u003C\u002Fspan> \u003Cspan class=\"shj-oper\">*\u003C\u002Fspan> \u003Cspan class=\"shj-num\">1000\u003C\u002Fspan> \u003Cspan class=\"shj-bracket\">}\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">,\u003C\u002Fspan>\n  \u003Cspan class=\"shj-bracket\">{\u003C\u002Fspan> unit\u003Cspan class=\"shj-oper\">:\u003C\u002Fspan> \u003Cspan class=\"shj-str\">'day'\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">,\u003C\u002Fspan>    ms\u003Cspan class=\"shj-oper\">:\u003C\u002Fspan>       \u003Cspan class=\"shj-num\">24\u003C\u002Fspan> \u003Cspan class=\"shj-oper\">*\u003C\u002Fspan> \u003Cspan class=\"shj-num\">60\u003C\u002Fspan> \u003Cspan class=\"shj-oper\">*\u003C\u002Fspan> \u003Cspan class=\"shj-num\">60\u003C\u002Fspan> \u003Cspan class=\"shj-oper\">*\u003C\u002Fspan> \u003Cspan class=\"shj-num\">1000\u003C\u002Fspan>  \u003Cspan class=\"shj-bracket\">}\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">,\u003C\u002Fspan>\n  \u003Cspan class=\"shj-bracket\">{\u003C\u002Fspan> unit\u003Cspan class=\"shj-oper\">:\u003C\u002Fspan> \u003Cspan class=\"shj-str\">'hour'\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">,\u003C\u002Fspan>   ms\u003Cspan class=\"shj-oper\">:\u003C\u002Fspan>            \u003Cspan class=\"shj-num\">60\u003C\u002Fspan> \u003Cspan class=\"shj-oper\">*\u003C\u002Fspan> \u003Cspan class=\"shj-num\">60\u003C\u002Fspan> \u003Cspan class=\"shj-oper\">*\u003C\u002Fspan> \u003Cspan class=\"shj-num\">1000\u003C\u002Fspan>  \u003Cspan class=\"shj-bracket\">}\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">,\u003C\u002Fspan>\n  \u003Cspan class=\"shj-bracket\">{\u003C\u002Fspan> unit\u003Cspan class=\"shj-oper\">:\u003C\u002Fspan> \u003Cspan class=\"shj-str\">'minute'\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">,\u003C\u002Fspan> ms\u003Cspan class=\"shj-oper\">:\u003C\u002Fspan>                 \u003Cspan class=\"shj-num\">60\u003C\u002Fspan> \u003Cspan class=\"shj-oper\">*\u003C\u002Fspan> \u003Cspan class=\"shj-num\">1000\u003C\u002Fspan>  \u003Cspan class=\"shj-bracket\">}\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">,\u003C\u002Fspan>\n  \u003Cspan class=\"shj-bracket\">{\u003C\u002Fspan> unit\u003Cspan class=\"shj-oper\">:\u003C\u002Fspan> \u003Cspan class=\"shj-str\">'second'\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">,\u003C\u002Fspan> ms\u003Cspan class=\"shj-oper\">:\u003C\u002Fspan>                      \u003Cspan class=\"shj-num\">1000\u003C\u002Fspan>  \u003Cspan class=\"shj-bracket\">}\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">,\u003C\u002Fspan>\n\u003Cspan class=\"shj-bracket\">]\u003C\u002Fspan>;\n\n\u003Cspan class=\"shj-kwd\">function\u003C\u002Fspan> \u003Cspan class=\"shj-func\">timeAgo\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>date\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan> \u003Cspan class=\"shj-bracket\">{\u003C\u002Fspan>\n  \u003Cspan class=\"shj-kwd\">const\u003C\u002Fspan> diffMs \u003Cspan class=\"shj-oper\">=\u003C\u002Fspan> date \u003Cspan class=\"shj-oper\">-\u003C\u002Fspan> \u003Cspan class=\"shj-class\">Date\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>\u003Cspan class=\"shj-func\">now\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>;\n  \u003Cspan class=\"shj-kwd\">for\u003C\u002Fspan> \u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-kwd\">const\u003C\u002Fspan> \u003Cspan class=\"shj-bracket\">{\u003C\u002Fspan> unit\u003Cspan class=\"shj-oper\">,\u003C\u002Fspan> ms \u003Cspan class=\"shj-bracket\">}\u003C\u002Fspan> \u003Cspan class=\"shj-kwd\">of\u003C\u002Fspan> \u003Cspan class=\"shj-num\">THRESHOLDS\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan> \u003Cspan class=\"shj-bracket\">{\u003C\u002Fspan>\n    \u003Cspan class=\"shj-kwd\">if\u003C\u002Fspan> \u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-class\">Math\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>\u003Cspan class=\"shj-func\">abs\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>diffMs\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan> \u003Cspan class=\"shj-oper\">&gt;=\u003C\u002Fspan> ms\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan> \u003Cspan class=\"shj-bracket\">{\u003C\u002Fspan>\n      \u003Cspan class=\"shj-kwd\">return\u003C\u002Fspan> rtf\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>\u003Cspan class=\"shj-func\">format\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-class\">Math\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>\u003Cspan class=\"shj-func\">round\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>diffMs \u003Cspan class=\"shj-oper\">\u002F\u003C\u002Fspan> ms\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">,\u003C\u002Fspan> unit\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>;\n    \u003Cspan class=\"shj-bracket\">}\u003C\u002Fspan>\n  \u003Cspan class=\"shj-bracket\">}\u003C\u002Fspan>\n  \u003Cspan class=\"shj-kwd\">return\u003C\u002Fspan> rtf\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>\u003Cspan class=\"shj-func\">format\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-num\">0\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">,\u003C\u002Fspan> \u003Cspan class=\"shj-str\">'second'\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>; \u003Cspan class=\"shj-cmnt\">\u002F\u002F \"just now\"\n\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">}\u003C\u002Fspan>\n\n\u003Cspan class=\"shj-func\">timeAgo\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-kwd\">new\u003C\u002Fspan> \u003Cspan class=\"shj-class\">Date\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-class\">Date\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>\u003Cspan class=\"shj-func\">now\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan> \u003Cspan class=\"shj-oper\">-\u003C\u002Fspan> \u003Cspan class=\"shj-num\">2\u003C\u002Fspan> \u003Cspan class=\"shj-oper\">*\u003C\u002Fspan> \u003Cspan class=\"shj-num\">60\u003C\u002Fspan> \u003Cspan class=\"shj-oper\">*\u003C\u002Fspan> \u003Cspan class=\"shj-num\">60\u003C\u002Fspan> \u003Cspan class=\"shj-oper\">*\u003C\u002Fspan> \u003Cspan class=\"shj-num\">1000\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>; \u003Cspan class=\"shj-cmnt\">\u002F\u002F \"2 hours ago\"\n\u003C\u002Fspan>\u003Cspan class=\"shj-func\">timeAgo\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-kwd\">new\u003C\u002Fspan> \u003Cspan class=\"shj-class\">Date\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-class\">Date\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>\u003Cspan class=\"shj-func\">now\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan> \u003Cspan class=\"shj-oper\">+\u003C\u002Fspan> \u003Cspan class=\"shj-num\">3\u003C\u002Fspan> \u003Cspan class=\"shj-oper\">*\u003C\u002Fspan> \u003Cspan class=\"shj-num\">24\u003C\u002Fspan> \u003Cspan class=\"shj-oper\">*\u003C\u002Fspan> \u003Cspan class=\"shj-num\">60\u003C\u002Fspan> \u003Cspan class=\"shj-oper\">*\u003C\u002Fspan> \u003Cspan class=\"shj-num\">60\u003C\u002Fspan> \u003Cspan class=\"shj-oper\">*\u003C\u002Fspan> \u003Cspan class=\"shj-num\">1000\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>; \u003Cspan class=\"shj-cmnt\">\u002F\u002F \"in 3 days\"\n\u003C\u002Fspan>\u003Cspan class=\"shj-func\">timeAgo\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-kwd\">new\u003C\u002Fspan> \u003Cspan class=\"shj-class\">Date\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-class\">Date\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>\u003Cspan class=\"shj-func\">now\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan> \u003Cspan class=\"shj-oper\">-\u003C\u002Fspan> \u003Cspan class=\"shj-num\">45\u003C\u002Fspan> \u003Cspan class=\"shj-oper\">*\u003C\u002Fspan> \u003Cspan class=\"shj-num\">1000\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>; \u003Cspan class=\"shj-cmnt\">\u002F\u002F \"45 seconds ago\"\u003C\u002Fspan>\u003C\u002Fdiv>\u003C\u002Fdiv>\u003C\u002Fdiv>","\u003Cdiv class=\"shj shj-lang-js shj-multiline\" data-lang=\"js\">\u003Cdiv class=\"shj-scroll\">\u003Cdiv class=\"shj-numbers\">\u003Cdiv>1\u003C\u002Fdiv>\u003Cdiv>2\u003C\u002Fdiv>\u003Cdiv>3\u003C\u002Fdiv>\u003Cdiv>4\u003C\u002Fdiv>\u003Cdiv>5\u003C\u002Fdiv>\u003Cdiv>6\u003C\u002Fdiv>\u003Cdiv>7\u003C\u002Fdiv>\u003Cdiv>8\u003C\u002Fdiv>\u003Cdiv>9\u003C\u002Fdiv>\u003Cdiv>10\u003C\u002Fdiv>\u003Cdiv>11\u003C\u002Fdiv>\u003Cdiv>12\u003C\u002Fdiv>\u003C\u002Fdiv>\u003Cdiv class=\"shj-code\">\u003Cspan class=\"shj-kwd\">const\u003C\u002Fspan> locales \u003Cspan class=\"shj-oper\">=\u003C\u002Fspan> \u003Cspan class=\"shj-bracket\">[\u003C\u002Fspan>\u003Cspan class=\"shj-str\">'en'\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">,\u003C\u002Fspan> \u003Cspan class=\"shj-str\">'fr'\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">,\u003C\u002Fspan> \u003Cspan class=\"shj-str\">'de'\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">,\u003C\u002Fspan> \u003Cspan class=\"shj-str\">'ja'\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">,\u003C\u002Fspan> \u003Cspan class=\"shj-str\">'ar'\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">]\u003C\u002Fspan>;\n\u003Cspan class=\"shj-kwd\">const\u003C\u002Fspan> twoHoursAgo \u003Cspan class=\"shj-oper\">=\u003C\u002Fspan> \u003Cspan class=\"shj-oper\">-\u003C\u002Fspan>\u003Cspan class=\"shj-num\">2\u003C\u002Fspan>;\n\n\u003Cspan class=\"shj-kwd\">for\u003C\u002Fspan> \u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-kwd\">const\u003C\u002Fspan> locale \u003Cspan class=\"shj-kwd\">of\u003C\u002Fspan> locales\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan> \u003Cspan class=\"shj-bracket\">{\u003C\u002Fspan>\n  \u003Cspan class=\"shj-kwd\">const\u003C\u002Fspan> rtf \u003Cspan class=\"shj-oper\">=\u003C\u002Fspan> \u003Cspan class=\"shj-kwd\">new\u003C\u002Fspan> \u003Cspan class=\"shj-class\">Intl\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>\u003Cspan class=\"shj-class\">RelativeTimeFormat\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>locale\u003Cspan class=\"shj-oper\">,\u003C\u002Fspan> \u003Cspan class=\"shj-bracket\">{\u003C\u002Fspan> numeric\u003Cspan class=\"shj-oper\">:\u003C\u002Fspan> \u003Cspan class=\"shj-str\">'auto'\u003C\u002Fspan> \u003Cspan class=\"shj-bracket\">}\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>;\n  console\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>\u003Cspan class=\"shj-func\">log\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-str\">`\u003C\u002Fspan>\u003Cspan class=\"shj-kwd\">${\u003C\u002Fspan>locale\u003Cspan class=\"shj-kwd\">}\u003C\u002Fspan>\u003Cspan class=\"shj-str\">: \u003C\u002Fspan>\u003Cspan class=\"shj-kwd\">${\u003C\u002Fspan>rtf\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>\u003Cspan class=\"shj-func\">format\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>twoHoursAgo\u003Cspan class=\"shj-oper\">,\u003C\u002Fspan> \u003Cspan class=\"shj-str\">'hour'\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>\u003Cspan class=\"shj-kwd\">}\u003C\u002Fspan>\u003Cspan class=\"shj-str\">`\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>;\n\u003Cspan class=\"shj-bracket\">}\u003C\u002Fspan>\n\u003Cspan class=\"shj-cmnt\">\u002F\u002F en: 2 hours ago\n\u003C\u002Fspan>\u003Cspan class=\"shj-cmnt\">\u002F\u002F fr: il y a 2 heures\n\u003C\u002Fspan>\u003Cspan class=\"shj-cmnt\">\u002F\u002F de: vor 2 Stunden\n\u003C\u002Fspan>\u003Cspan class=\"shj-cmnt\">\u002F\u002F ja: 2 時間前\n\u003C\u002Fspan>\u003Cspan class=\"shj-cmnt\">\u002F\u002F ar: قبل ساعتين\u003C\u002Fspan>\u003C\u002Fdiv>\u003C\u002Fdiv>\u003C\u002Fdiv>"]