GithubHelp home page GithubHelp logo

metonym / svelte-time Goto Github PK

View Code? Open in Web Editor NEW
130.0 4.0 8.0 1.2 MB

Svelte component and action to format a timestamp using day.js

Home Page: https://metonym.github.io/svelte-time

License: MIT License

JavaScript 13.29% Svelte 26.72% TypeScript 59.99%
svelte svelte-component svelte-action dayjs time-formatting timestamp relative ago

svelte-time's Introduction

svelte-time

NPM

svelte-time is a Svelte component and action to make a timestamp human-readable while encoding the machine-parseable value in the semantic time element.

Under the hood, it uses day.js, a lightweight date-time library.

<!-- Input -->
<Time relative />

<!-- Output rendered in the DOM -->
<time title="May 15, 2022" datetime="2022-05-15T18:03:57.430Z">
  a few seconds ago
</time>

Try it in the Svelte REPL.


Installation

# npm
npm i -D svelte-time

# pnpm
pnpm i -D svelte-time dayjs

# Bun
bun i -D svelte-time

# Yarn
yarn add -D svelte-time

Note that pnpm users must also install dayjs.

Usage

Time component

The displayed time defaults to new Date().toISOString() and is formatted as "MMM DD, YYYY".

<script>
  import Time from "svelte-time";
</script>

<Time />

The timestamp prop can be any of the following dayjs values: string | number | Date | Dayjs.

<Time timestamp="2020-02-01" />

<Time timestamp={new Date()} />

<Time timestamp={1e10} />

Use the format prop to format the timestamp. Refer to the dayjs format documentation for acceptable formats.

<Time timestamp="2020-02-01" format="dddd @ h:mm A · MMMM D, YYYY" />

<Time timestamp={new Date()} format="YYYY/MM/DD" />

<Time timestamp={1e10} format="ddd" />

Relative time

Set the relative prop value to true for the relative time displayed in a human-readable format.

<Time relative />

<Time relative timestamp="2021-02-02" />

<Time relative timestamp={1e10} />

When using relative time, the title attribute will display a formatted timestamp.

Use the format prop to customize the format.

<Time relative format="dddd @ h:mm A · MMMM D, YYYY" />

When using relative, the time element will set the formatted timestamp as the title attribute. Specify a custom title to override this.

<Time relative title="Custom title" />

Set the value to undefined to omit the title altogether.

<Time relative title={undefined} />

Live updates

Set live to true for a live updating relative timestamp. The default refresh interval is 60 seconds.

<Time live relative />

To customize the interval, pass a value to live in milliseconds (ms).

<!-- Update every 30 seconds -->
<Time live={30 * 1_000} relative />

<!-- Update every 10 minutes -->
<Time live={10 * 60 * 1_000} relative />

svelteTime action

An alternative to the Time component is to use the svelteTime action to format a timestamp in a raw HTML element.

The API is the same as the Time component.

<script>
  import { svelteTime } from "svelte-time";
</script>

<time use:svelteTime />

<time
  use:svelteTime={{
    timestamp: "2021-02-02",
    format: "dddd @ h:mm A · MMMM D, YYYY",
  }}
/>

Relative time

Set relative to true to use relative time.

<time
  use:svelteTime={{
    relative: true,
    timestamp: "2021-02-02",
  }}
/>

<time
  use:svelteTime={{
    relative: true,
    timestamp: "2021-02-02",
    format: "dddd @ h:mm A · MMMM D, YYYY",
  }}
/>

To customize or omit the title attribute, use the title prop.

<time
  use:svelteTime={{
    relative: true,
    title: "Custom title",
    timestamp: "2021-02-02",
  }}
/>

<time
  use:svelteTime={{
    relative: true,
    title: undefined,
    timestamp: "2021-02-02",
  }}
/>

Similar to the Time component, the live prop only works with relative time.

<time
  use:svelteTime={{
    relative: true,
    live: true,
  }}
/>

Specify a custom update interval using the live prop.

<time
  use:svelteTime={{
    relative: true,
    live: 30 * 1_000, // Update every 30 seconds
  }}
/>

dayjs export

The dayjs library is exported from this package for your convenience.

Note: the exported dayjs function already extends the relativeTime plugin.

<script>
  import { dayjs } from "svelte-time";

  let timestamp = "";
</script>

<button on:click={() => (timestamp = dayjs().format("HH:mm:ss.SSSSSS"))}>
  Update {timestamp}
</button>

Custom locale

The default dayjs locale is English. No other locale is loaded by default for performance reasons.

To use a custome locale, import the relevant language from dayjs. See a list of supported locales.

<script>
  import "dayjs/locale/de"; // German locale
  import Time, { dayjs } from "svelte-time";
</script>

<Time timestamp={dayjs().locale("de")} />

Custom locale (global)

Use the dayjs.locale method to set a custom locale as the default.

<script>
  import "dayjs/locale/de"; // German locale
  import { dayjs } from "svelte-time";

  // Set the default locale to German.
  dayjs.locale("de");
</script>

Custom timezone

To use a custom timezone, import the utc and timezone plugins from dayjs.

<script>
  import utc from "dayjs/plugin/utc";
  import timezone from "dayjs/plugin/timezone";

  import Time, { dayjs } from "svelte-time";

  dayjs.extend(utc);
  dayjs.extend(timezone);
</script>

<Time
  timestamp={dayjs("2013-11-18 11:55:20").tz("America/Toronto")}
  format="YYYY-MM-DDTHH:mm:ss"
/>

Custom timezone (global)

Use the dayjs.tz.setDefault method to set a custom timezone as the default.

<script>
  import utc from "dayjs/plugin/utc";
  import timezone from "dayjs/plugin/timezone";

  import Time, { dayjs } from "svelte-time";

  dayjs.extend(utc);
  dayjs.extend(timezone);
  dayjs.tz.setDefault("America/New_York");
</script>

User timezone

Use the dayjs.ts.guess method to guess the user's timezone.

import utc from "dayjs/plugin/utc";
import timezone from "dayjs/plugin/timezone";

dayjs.extend(utc);
dayjs.extend(timezone);

dayjs.tz.guess(); // America/New_York

To retrieve the abbreviated time zone, extend the advancedFormat plugin.

  import utc from "dayjs/plugin/utc";
  import timezone from "dayjs/plugin/timezone";
+ import advancedFormat from "dayjs/plugin/advancedFormat";

  import { dayjs } from "svelte-time";

  dayjs.extend(utc);
  dayjs.extend(timezone);
+ dayjs.extend(advancedFormat);

Then, use the dayjs().local method to get the user's local time zone and format it using the "z" advanced option.

dayjs().local().format("z"); // EST
dayjs().local().format("zzz"); // Eastern Standard Time

API

Props

Name Type Default value
timestamp string | number | Date | Dayjs new Date().toISOString()
format string "MMM DD, YYYY" (See dayjs display format)
relative boolean false
live boolean | number false
formatted string ""

Examples

Changelog

CHANGELOG.md

License

MIT

svelte-time's People

Contributors

imbolc avatar metonym avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

svelte-time's Issues

SvelteKit build fails on dayjs ES module import not supported

Hi,

Thanks for this cool lib/component. It works great in dev mode for a Sveltekit project I am developping, but when running npm run build it fails with the following error :

Error [ERR_UNSUPPORTED_DIR_IMPORT]: Directory import '/home/.../node_modules/dayjs/esm' is not supported resolving ES modules imported from /home/.../.svelte-kit/output/server/chunks/index-5e596d58.js
Did you mean to import dayjs/esm/index.js?
    at new NodeError (internal/errors.js:322:7)
    at finalizeResolution (internal/modules/esm/resolve.js:304:17)
    at moduleResolve (internal/modules/esm/resolve.js:731:10)
    at Loader.defaultResolve [as _resolve] (internal/modules/esm/resolve.js:842:11)
    at Loader.resolve (internal/modules/esm/loader.js:89:40)
    at Loader.getModuleJob (internal/modules/esm/loader.js:242:28)
    at ModuleWrap.<anonymous> (internal/modules/esm/module_job.js:76:40)
    at link (internal/modules/esm/module_job.js:75:36)

Any idea how this could be fixed? 🙏

Cannot import Time with updated SvelteKit

Hi.

I'm using svelte-time in two projects.
The first project uses the SvelteKit version 1.0.0-next.445 and everything works fine.
However, the later project is using SvelteKit version 1.0.0-next.507 and when I add import Time from "svelte-time";, immediately I'm getting 500 Internal Error with an error message in the console saying SyntaxError: The requested module '/node_modules/dayjs/plugin/relativeTime.js?v=175ce1d1' does not provide an export named 'default' (at dayjs.js?v=175ce1d1:2:8)

Node version: 16.14.1
npm version: 8.19.2

Cheers.

`svelte-time` version 0.7.1 doesn't work with Snowpack

I'm recording this as a known issue. Version 0.7.1 switched back to using CJS instead of ESM imports from dayjs in order to unblock usage with SvelteKit.

Running snowpack in development works fine; however, building the app for production will throw the following error:

Duplicate export 'default... in node_modules/dayjs/dayjs.min.js

The workaround is to either pin the svelte-time version to v0.7.0 or copy the source code and update src/dayjs.js to the following:

- import dayjs from "dayjs";
- import relativeTime from "dayjs/plugin/relativeTime.js";
+ import dayjs from "dayjs/esm";
+ import relativeTime from "dayjs/esmplugin/relativeTime";

Cannot read properties of undefined (reading '$i')

I'm using the latest release of Sveltekit and I've installed svelte-time as a dev dependency. I'm getting this error at the most basic usage of the module:

<Time relative timestamp="2020-02-01" />

500

Cannot read properties of undefined (reading '$i')

TypeError: Cannot read properties of undefined (reading '$i')
    at Function.w.extend (\node_modules\.pnpm\[email protected]\node_modules\dayjs\dayjs.min.js:1:6457)
    at /node_modules/.pnpm/[email protected]/node_modules/svelte-time/src/dayjs.js:1:26
    at async instantiateModule (/node_modules/.pnpm/[email protected]/node_modules/vite/dist/node/chunks/dep-d66eb979.js:53333:9

Error code 500: Cannot use import statement outside a module

Hey Metonym,

one sweet package you wrote there! I'm tinkering with it but for some reason I always end up having issues with the dayjs module. I'm importing within the module context ala

<script context="module">
  import Time from "svelte-time";
</script>

but always get the following error, when I first navigate to a page using it:

23:03:04 [vite] Error when evaluating SSR module /node_modules/svelte-time/src/dayjs.js:
C:\Users\froeb\Desktop\blog\frontend\node_modules\dayjs\esm\index.js:1
import * as C from './constant';
^^^^^^

SyntaxError: Cannot use import statement outside a module
    at wrapSafe (internal/modules/cjs/loader.js:979:16)
    at Module._compile (internal/modules/cjs/loader.js:1027:27)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:1092:10)
    at Module.load (internal/modules/cjs/loader.js:928:32)
    at Function.Module._load (internal/modules/cjs/loader.js:769:14)
    at Module.require (internal/modules/cjs/loader.js:952:19)
    at require (internal/modules/cjs/helpers.js:88:18)
    at nodeRequire (C:\Users\froeb\Desktop\blog\frontend\node_modules\vite\dist\node\chunks\dep-e9a16784.js:68211:17)
    at ssrImport (C:\Users\froeb\Desktop\blog\frontend\node_modules\vite\dist\node\chunks\dep-e9a16784.js:68164:20)
    at eval (/node_modules/svelte-time/src/dayjs.js:3:31) (x2)

Any idea?

Best,
George

Package will break in future Svelte versions

See the following output from Svelte:

9:35:03 p.m. [vite-plugin-svelte] WARNING: The following packages have a svelte field in their package.json but no exports condition for svelte.

[email protected]

Please see https://github.com/sveltejs/vite-plugin-svelte/blob/main/docs/faq.md#missing-exports-condition for details.

https://github.com/sveltejs/vite-plugin-svelte/blob/main/docs/faq.md#missing-exports-condition

Action is required to update this package to use the new standard otherwise it will break in future versions.

How to use this inside <title>

I'm trying to use this within the title header but getting an error saying only 'text' and {tags} can be used inside the <title>

Any ideas?

export error relativeTime

The requested module '/node_modules/dayjs/plugin/relativeTime.js?v=14ef3dca' does not provide an export named 'default'
SyntaxError: The requested module '/node_modules/dayjs/plugin/relativeTime.js?v=14ef3dca' does not provide an export named 'default'

Relative mode title format

Now the timestamp is used as a title in the relative mode. Would you consider changing it to something easy parsable by non-programmers eyes? A title_format prop maybe with the Date.toLocaleString() by default?

Different with the actual data

Why its Different from the actual data? how to fix it?
the screen like bellow:

{#if item.PreparedAt} 
    Show: <Time relative={false} timestamp="{item.PreparedAt}" format="YYYY-MM-DDTHH:mm:ssZ[Z]" />
   Actual: {item.PreparedAt}
 {/if}

image

How to NOT render the title global attribute.

Hello, 👋

First off, I really love the lib and use it often for its simplicity. 🙂

From MDN, I understand the title attribute is basically a tooltip for representing advisory information related to the element it belongs to. In our case, the time element. (Thanks for making this semantic.)

But here is my issue; I wanted to provide my own tooltip, but trying to override the rendered title doesn't seem to work.

I tried passing null and an empty string '' to the title prop, but nothing seemed to work.

						<Time
							relative
							format="D MMMM, YYYY"
							timestamp={created_at}
							class="text-sm text-muted-foreground"
							title={null}
						/>

The result, in my case, is repetitive information and I would like to avoid this:

Screenshot 2024-04-18 at 19 54 25

Do you know of a way to:

  1. disable the tooltip, but retain the element title in the DOM (for accessibility's sake?)
  1. forego on adding the title altogether

I appreciate the help.

Suggestion: Use a single global readable store for live updates

Somewhat like this:

import { readable } from "svelte/store"

const NOW = readable(new Date(), (set) => {
  const timer = setInterval(() => set(new Date()), 1000)
  return () => clearInterval(timer)
})

Effectively eliminating the NEED for configurable granularity (could still support special cases) while reducing the number of timers required for like a large list of things to 1.

Locale options?

I think it's better to add locale options considering dayjs already have it, so other timezone can use relative time format too.

Thanks!^^

Uncaught SyntaxError: ambiguous indirect export: default

Hello,
I wonder if you can help with this.

Here are snippets of my code

  import Time, { svelteTime } from "svelte-time";
  import { dayjs } from "svelte-time";
......
{#if first}
    <p>
      {first.publish_date} 
      <time
          use:svelteTime="{{
          timestamp: first.publish_date,
        }}"
      />
     </p>
{/if}

without the svelteTime code, all is well, first.publish_date is printed.
With the extra code, I get an error in firefox console of above. It is a line two of days.js.

So I changed first.publish_date with "2021-02-14" and got the same error. Obviously this works in the repl.

Any ideas what I am doing wrong?

Can't get relative time with locale

I installed Svelte with bun, it uses recent versions:

    "@sveltejs/adapter-auto": "^2.1.1",
    "@sveltejs/kit": "^1.27.3",
    "flowbite-svelte": "^0.44.19",
    "svelte": "^4.2.2",
    "svelte-check": "^3.5.2",
    "svelte-time": "^0.8.0",
    "vite": "^4.5.0"

It runs in a lxd container.

I created this test pages +page.svelte to test various cases:

  • Time is Ok
  • relative is Ok with standard language
  • Time displays the date correctly in another locale (case 3 - but only with a dayjs date), not with a regular date (case 4)
  • Last test to display a relative date in another locale triggers an Error 500
<script context="module">
    import "dayjs/esm/locale/uk"
    import dayjs from "dayjs/esm"

    dayjs.locale("uk") // Ukrainian locale to be sure

</script>

<script>js
    import Time from "svelte-time"

    let djsDate = dayjs()
    let djsDateFormatted = dayjs().format("DD MMMM YY")
</script>

ok <Time timestamp="2020-01-01" /><br />
ok <Time relative timestamp="2020-01-01" /><br />
ok <Time timestamp={dayjs("2020-01-01")} format="MMMM" /><br />
oko? <Time timestamp="2020-01-01" format="MMMM" /><br />
ko 
<!-- <Time relative timestamp={dayjs("2020-01-01")} format="MMMM" /><br /> -->
<!-- TypeError: __vite_ssr_import_1__.dayjs(timestamp).from is not a function. (In '__vite_ssr_import_1__.dayjs(timestamp).from()', '__vite_ssr_import_1__.dayjs(timestamp).from' is undefined) -->

Last lines triggers a console error: TypeError: __vite_ssr_import_1__.dayjs(timestamp).from is not a function. (In '__vite_ssr_import_1__.dayjs(timestamp).from()', '__vite_ssr_import_1__.dayjs(timestamp).from' is undefined)

I'm quite starting tinkering with svelte and javascript, so I might have missed something obvious (or my config is too exotic ?)
All my other tests about Svelte / Kit are ok.

Plus, I'm a bit surprised that not every date applies the locale defined? Is a format really mandatory?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.