Introduction

Representing time in a human-readable format in the fast-paced digital world is essential to enhance user experience. In this blog post, we will delve into a TypeScript function that takes a JavaScript Date object and pretty-prints it into more readable strings like “Just Now”, “Today”, “Yesterday”, etc., depending on the input date’s proximity to the current date and time. Moreover, we will create a suite of Vitest unit tests to verify the function’s behavior in different scenarios. Let’s get started!

Creating the Pretty Print Date Function

To initiate, let’s explore the TypeScript function that pretty-prints JavaScript Date objects. Here is the function:

export function prettyPrintDate(inputDate: Date): string {
    const now = new Date();
  
    const diffInSeconds = (now.getTime() - inputDate.getTime()) / 1000;
    const diffInMinutes = Math.round(diffInSeconds / 60);
    const diffInHours = Math.round(diffInMinutes / 60);
  
    if (diffInSeconds < 60) {
      return 'Just Now';
    } else if (diffInHours < 1) {
      return diffInMinutes === 1 ? '1 minute ago' : `${diffInMinutes} minutes ago`;
    } else if (now.toDateString() === inputDate.toDateString()) {
      return 'Today';
    } else if (
      new Date(now.getFullYear(), now.getMonth(), now.getDate() - 1).toDateString() ===
      inputDate.toDateString()
    ) {
      return 'Yesterday';
    } else {
      return inputDate.toLocaleTimeString([], {
        year: 'numeric',
        month: 'numeric',
        day: 'numeric',
        hour: 'numeric',
        minute: 'numeric',
      });
    }
  }

Function Explanation

  1. Retrieving Current Date and Time: The current date and time are retrieved using new Date().
  2. Calculating Time Differences: The differences in seconds, minutes, and hours between the current date and the input date are calculated and rounded accordingly.
  3. Conditional Statements: Depending on the calculated differences, the function returns human-readable strings, such as “Just Now”, “Today”, and “Yesterday”.
  4. Fallback: If the input date does not satisfy any of the earlier conditions, it falls back to a formatted date string using toLocaleTimeString.

Creating Vitest Unit Tests

import { prettyPrintDate } from './prettyPrintDate'
import { vi } from 'vitest'

describe('prettyPrintDate', () => {
  const originalNow = Date.now

  beforeAll(() => {
    const now = new Date(2023, 8, 14, 12, 0, 0)
    vi.setSystemTime(now)
  })

  afterAll(() => {
    Date.now = originalNow
  })

  it('should return "Just Now" for dates less than 60 seconds ago', () => {
    const date = new Date(2023, 8, 14, 11, 59, 30)
    expect(prettyPrintDate(date)).toBe('Just Now')
  })

  it('should return "1 minute ago" for dates 1 minute ago', () => {
    const date = new Date(2023, 8, 14, 11, 59, 0)
    expect(prettyPrintDate(date)).toBe('1 minute ago')
  })

  it('should return "X minutes ago" for dates less than 1 hour ago', () => {
    const date = new Date(2023, 8, 14, 11, 30, 0)
    expect(prettyPrintDate(date)).toBe('30 minutes ago')
  })

  it('should return "Today" for dates that are from today', () => {
    const date = new Date(2023, 8, 14, 0, 0, 0)
    expect(prettyPrintDate(date)).toBe('Today')
  })

  it('should return "Yesterday" for dates that are from yesterday', () => {
    const date = new Date(2023, 8, 13, 23, 59, 59)
    expect(prettyPrintDate(date)).toBe('Yesterday')
  })

  it('should return formatted date string for dates older than yesterday', () => {
    const date = new Date(2023, 8, 12, 12, 0, 0)
    expect(prettyPrintDate(date)).toBe('9/12/2023, 12:00 PM')
  })
})

We implement a series of Vitest unit tests to ensure our function operates correctly. Here is a snippet of the unit tests we created to cover different cases:

Testing Explanation

  1. Setting Up Vitest: We set up Vitest to mock the current date and time, enabling consistent test outcomes.
  2. Individual Test Cases: Separate test cases cover all branches of the function’s conditional statements, verifying that the function returns the correct string for various input dates.
  3. Singular and Plural Units: The tests include scenarios for singular units of time, ensuring correct grammatical representation in the output strings.

Conclusion

The pretty-printed date function enhances the representation of dates in JavaScript applications, providing a more user-friendly experience. Accompanied by a comprehensive suite of Jest unit tests, we ensure its robust performance across various scenarios. Try incorporating this function into your TypeScript or JavaScript project to improve date and time readability in your application. Let us know how it enhances your project’s user experience!