Radish alpha
r
Radicle web interface
Radicle
Git (anonymous pull)
Log in to clone via SSH
Convert timestamp to relative format
Sebastian Martinez committed 3 years ago
commit 07d32f5cdef91ad7e2dc617858d5fa30ea2c97f0
parent 44193842fd197087441795328c6ae68dcbae8872
3 files changed +79 -3
modified src/base/projects/Commit/CommitAuthorship.svelte
@@ -61,6 +61,6 @@
      <span>&nbsp;committed</span>
    {/if}
  {/if}
-
  <span>&nbsp;at&nbsp;</span>
+
  <span>&nbsp;</span>
  <span class="desktop-inline text-xsmall time">{formatTimestamp(commit.header.committerTime)}</span>
</span>
modified src/utils.test.ts
@@ -156,6 +156,15 @@ describe("String Assertions", () => {
  });

  test.each([
+
    { id: "hnrkj4c35uoyceb3d1dsscx8qq55cikrd1aio", expected: true },
+
    { id: "0x1234567890123456789012345678901234567890", expected: false },
+
  ])("isPeerId $id => $expected", ({ id, expected }) => {
+
    expect(
+
      utils.isPeerId(id))
+
      .toEqual(expected);
+
  });
+

+
  test.each([
    { oid: "a64ae9c6d572e0ad906faa9a4a7a8d43f113278c", expected: true },
    { oid: "a64ae9c", expected: false }
  ])("isOid $oid => $expected", ({ oid, expected }) => {
@@ -293,3 +302,31 @@ describe("Path Manipulation", () => {
    ).toEqual(expected);
  });
});
+

+
describe("Date Manipulation", () => {
+
  test.each([
+
    { from: new Date("2022-01-01"), to: new Date("2022-02-01"), expected: 31 },
+
    { from: new Date("2022-01-01"), to: new Date("2022-01-02"), expected: 1 },
+
    { from: new Date("2022-01-01"), to: new Date("2022-01-01"), expected: 0 },
+
  ])("getDaysPassed expected: $expected ", ({ from, to, expected }) => {
+
    expect(
+
      utils.getDaysPassed(from, to)
+
    ).toEqual(expected);
+
  });
+
  test.each([
+
    { from: new Date("2022-01-01 12:00:00"), to: new Date("2022-01-01 12:00:00"), expected: "now" },
+
    { from: new Date("2022-01-01 12:00:00"), to: new Date("2022-01-01 12:00:01"), expected: "1 second ago" },
+
    { from: new Date("2022-01-01 12:00:00"), to: new Date("2022-01-01 12:01:01"), expected: "1 minute ago" },
+
    { from: new Date("2022-01-01 12:00:00"), to: new Date("2022-01-01 13:01:01"), expected: "1 hour ago" },
+
    { from: new Date("2022-01-01 12:00:00"), to: new Date("2022-01-02 13:01:01"), expected: "yesterday" },
+
    { from: new Date("2022-01-01 12:00:00"), to: new Date("2022-01-04 13:01:01"), expected: "3 days ago" },
+
    { from: new Date("2022-01-01 12:00:00"), to: new Date("2022-02-02 13:01:01"), expected: "last month" },
+
    { from: new Date("2022-01-01 12:00:00"), to: new Date("2022-04-02 13:01:01"), expected: "3 months ago" },
+
    { from: new Date("2022-01-01 12:00:00"), to: new Date("2023-04-02 12:00:00"), expected: "Sat, 01 Jan 2022 12:00:00 GMT" },
+
    { from: new Date("2022-03-05 12:00:00"), to: new Date("2026-04-02 12:00:00"), expected: "Sat, 05 Mar 2022 12:00:00 GMT" },
+
  ])("formatTimestamp expected: $expected", ({ from, to, expected }) => {
+
    expect(
+
      utils.formatTimestamp(from.getTime() / 1000, to.getTime())
+
    ).toEqual(expected);
+
  });
+
});
modified src/utils.ts
@@ -246,8 +246,35 @@ export function unixTime(): number {
  return Math.floor(Date.now() / 1000);
}

-
export const formatTimestamp = (t: number): string => {
-
  return new Date(t * 1000).toLocaleString("en-EN", { dateStyle: "full", timeStyle: "long" });
+
export const formatTimestamp = (timestamp: number, current = new Date().getTime()): string => {
+
  const units: Record<string, number> = {
+
    year: 24 * 60 * 60 * 1000 * 365,
+
    month: 24 * 60 * 60 * 1000 * 365 / 12,
+
    day: 24 * 60 * 60 * 1000,
+
    hour: 60 * 60 * 1000,
+
    minute: 60 * 1000,
+
    second: 1000
+
  };
+

+
  // Multiplying timestamp with 1000 to convert from seconds to milliseconds
+
  timestamp = timestamp * 1000;
+
  const rtf = new Intl.RelativeTimeFormat('en', { numeric: "auto", style: 'long' });
+
  const elapsed = current - timestamp;
+

+
  if (elapsed > units["year"]) {
+
    return new Date(timestamp).toUTCString(); // If it's more than a year we return early showing a Datetime string
+
  } else if (elapsed < 0) {
+
    return "now"; // If elapsed is a negative number we are dealing with an item from the future, and we return "now"
+
  }
+

+
  for (const u in units) {
+
    if (elapsed > units[u] || u == 'second') {
+
      // We convert the division result to a negative number to get "XX [unit] ago"
+
      return rtf.format(Math.round(elapsed / units[u]) * -1, u as Intl.RelativeTimeFormatUnit);
+
    }
+
  }
+

+
  return new Date(timestamp).toUTCString();
};

// Check whether the input is a Radicle ID.
@@ -255,6 +282,11 @@ export function isRadicleId(input: string): boolean {
  return /^rad:[a-z]+:[a-zA-Z0-9]+$/.test(input);
}

+
// Check whether the input is a Radicle Peer ID.
+
export function isPeerId(input: string): boolean {
+
  return /^h[a-zA-Z0-9]+$/.test(input);
+
}
+

// Check whether the input is a SHA1 commit.
export function isOid(input: string): boolean {
  return /^[a-fA-F0-9]{40}$/.test(input);
@@ -355,6 +387,13 @@ export function parseRadicleId(urn: string): string {
  return urn.replace(/^rad:[a-z]+:/, "");
}

+
// Get amount of days passed between two dates without including the end date
+
export function getDaysPassed(from: Date, to: Date): number {
+
  return Math.floor(
+
    (to.getTime() - from.getTime()) / (24 * 60 * 60 * 1000)
+
  );
+
}
+

// Decode a Radicle Id (URN).
export function decodeRadicleId(urn: string): Uint8Array {
  const encoded = parseRadicleId(urn);