Форматирование дат и чисел

SkateJS — это библиотека для создания веб-компонентов на основе стандартов Custom Elements, которая тесно интегрируется с современным JavaScript. Важной частью разработки компонентов является работа с датами и числами, особенно если требуется их корректное отображение с учётом локализации, форматирования и динамического обновления. SkateJS предоставляет удобные механизмы для организации реактивных данных, что делает форматирование данных гибким и масштабируемым.


Работа с числами

Использование Intl.NumberFormat

Для форматирования чисел стандартным и локализованным способом рекомендуется использовать встроенный объект Intl.NumberFormat. Он позволяет задавать:

  • локаль (locale),
  • стиль отображения (decimal, currency, percent),
  • количество знаков после запятой,
  • использование разделителей тысяч.

Пример создания реактивного свойства с форматированием числа в компоненте SkateJS:

import { define, props, Component } from 'skatejs';

class PriceDisplay extends Component {
  static props = {
    price: props.number
  };

  renderCallback() {
    const formatter = new Intl.NumberFormat('ru-RU', {
      style: 'currency',
      currency: 'RUB',
      minimumFractionDigits: 2,
      maximumFractionDigits: 2
    });
    return <span>{formatter.format(this.price)}</span>;
  }
}

define(PriceDisplay);

Ключевые моменты:

  • props.number обеспечивает реактивность: любое изменение свойства price автоматически вызывает перерисовку.
  • Intl.NumberFormat локализует формат автоматически, включая разделители тысяч и валютный символ.
  • Можно динамически менять локаль и стиль в зависимости от состояния компонента.

Форматирование процентов и пользовательские форматы

Для отображения процентов используется style: 'percent':

const percentFormatter = new Intl.NumberFormat('en-US', {
  style: 'percent',
  minimumFractionDigits: 1
});

percentFormatter.format(0.1234); // "12.3%"

Можно комбинировать форматы, создавать функции-обёртки для повторного использования в разных компонентах:

function formatCurrency(value, locale = 'ru-RU', currency = 'RUB') {
  return new Intl.NumberFormat(locale, { style: 'currency', currency }).format(value);
}

Работа с датами

Использование Intl.DateTimeFormat

Для форматирования дат и времени используется объект Intl.DateTimeFormat, который позволяет локализовать дату, управлять форматом дня, месяца, года, времени и т.д.

Пример компонента для отображения даты:

class DateDisplay extends Component {
  static props = {
    date: props.any
  };

  renderCallback() {
    const formatter = new Intl.DateTimeFormat('ru-RU', {
      year: 'numeric',
      month: 'long',
      day: 'numeric',
      weekday: 'long',
      hour: '2-digit',
      minute: '2-digit'
    });
    return <span>{formatter.format(this.date)}</span>;
  }
}

define(DateDisplay);

Особенности:

  • props.any используется для поддержки как объектов Date, так и строковых значений.
  • Форматирование полностью адаптируется под выбранную локаль.
  • Можно комбинировать с динамическими свойствами для поддержки мультиязычности.

Создание динамических форматов дат

В SkateJS удобно создавать реактивные геттеры, которые автоматически пересчитывают формат при изменении свойств:

class DynamicDate extends Component {
  static props = {
    date: props.any,
    locale: props.string
  };

  get formattedDate() {
    return new Intl.DateTimeFormat(this.locale || 'en-US', {
      year: 'numeric',
      month: 'short',
      day: 'numeric'
    }).format(this.date);
  }

  renderCallback() {
    return <time>{this.formattedDate}</time>;
  }
}

define(DynamicDate);

Преимущества такого подхода:

  • Пересчёт формата происходит автоматически при изменении locale или date.
  • Отделение логики форматирования от рендера делает код более читаемым и тестируемым.
  • Позволяет легко добавлять дополнительные форматы, например, для времени или относительных дат.

Интеграция с шаблонами SkateJS

SkateJS поддерживает JSX-подобный синтаксис для рендеринга, что упрощает вставку отформатированных чисел и дат прямо в шаблон:

renderCallback() {
  return (
    <div>
      <p>Цена: {formatCurrency(this.price)}</p>
      <p>Дата публикации: {this.formattedDate}</p>
    </div>
  );
}

Можно использовать условные форматы, например, показывать время только если оно задано:

renderCallback() {
  const options = this.date.getHours() === 0 ? { year: 'numeric', month: 'long', day: 'numeric' } : {};
  const formatted = new Intl.DateTimeFormat('ru-RU', options).format(this.date);
  return <span>{formatted}</span>;
}

Особенности реактивного форматирования

  1. Реактивные свойства: SkateJS автоматически вызывает renderCallback, когда изменяются props, что делает обновление форматирования прозрачным.
  2. Переиспользуемые функции форматирования: Вынос функций форматирования в отдельные утилиты упрощает поддержку и локализацию.
  3. Локализация: Использование Intl обеспечивает корректное отображение чисел и дат в разных странах без дополнительных библиотек.
  4. Производительность: Форматирование происходит только при изменении данных, минимизируя лишние перерасчёты.

Форматирование дат и чисел в SkateJS строится на сочетании реактивных свойств и стандартного API Intl, что позволяет создавать гибкие, локализованные и динамические компоненты, способные работать с любыми типами числовых и временных данных.