Skip to content

solidkit/date-core

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

13 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

date-core

A modern, compact date utilities library designed for React Native and web applications. Features comprehensive locale support with Arabic numerals, intelligent error handling, and production-ready logging. Efficient alternative to heavy date libraries.

npm version bundle size license downloads

📋 Table of Contents

🎯 Overview

A modern, performant date utilities library that replaces heavy date libraries with a compact, feature-rich alternative:

  • 🚀 Compact bundle size (Small library with tree-shaking)
  • 🌍 Dynamic locale registration - Add new locales at runtime
  • 📝 Custom locale files - Support for user-provided locale configurations
  • 🔢 Full Arabic locale support - Arabic numerals and RTL support
  • ⚙️ Centralized locale management - Single source of truth for app locale
  • 📱 Optimized for React Native - Built specifically for mobile performance
  • 🌐 Web Application Ready - Perfect for React, Vue, Angular, and vanilla JS
  • 🎯 Clean options object API - Modern destructuring syntax for better DX
  • 🛡️ Comprehensive error handling - Safe handling of invalid dates with fallbacks
  • 🚀 App initialization configuration - Configure everything during app startup

📦 Installation

# Using npm
npm install date-core

# Using yarn
yarn add date-core

# Using pnpm
pnpm add date-core

🚀 Quick Start

1. Initialize App with Configuration

// In your App.js or index.js
import { initializeApp } from 'date-core'

// Initialize with complete configuration
const result = initializeApp({
  // Locale configuration
  locale: 'ar', // Arabic locale with RTL support

  // Error handling configuration (all optional)
  logErrors: true,
  fallbackDate: new Date(),
  fallbackString: 'Invalid Date',
  messages: {
    invalidDate: 'Custom: Invalid date provided',
    invalidDateNull: 'Custom: Date cannot be null',
  },

  // Additional configuration
  strictMode: false,
  validateDates: true,
})

console.log('App initialized:', result)
// Console Output:
// App initialized: {
//   success: true,
//   locale: 'ar',
//   fallbackDate: Date object,
//   errorConfig: { logErrors: true, ... }
// }

2. Use Throughout Your App

import {
  formatDateLocalized,
  getRelativeTimeLocalized,
  getDayName,
  formatLongDate,
  isToday,
} from 'date-core'

// Basic formatting
const date = formatDateLocalized(new Date()) // "15 January 2024"
const dayName = getDayName(new Date(), { format: 'short' }) // "Mon"
const relativeTime = getRelativeTimeLocalized(someDate) // "2 hours ago"

// Advanced formatting
const longDate = formatLongDate(new Date(), { format: 'LLLL' }) // "Monday, 15 January 2024 14:30"
const isTodayCheck = isToday(someDate) // true/false

// Arabic locale example
const arabicDate = formatDateLocalized(new Date(), { locale: 'ar' }) // "١٥ يناير ٢٠٢٤"

// Smart formatting examples
formatDateSmart(new Date()) // "Today" (if today)
formatDateSmart(yesterday) // "Yesterday"
formatDateSmart(tomorrow) // "Tomorrow"
formatDateSmart(otherDate) // "15 January 2024" (if not today/yesterday/tomorrow)

// Arabic smart formatting
formatDateSmart(new Date(), { locale: 'ar' }) // "اليوم" (if today)
formatDateSmart(yesterday, { locale: 'ar' }) // "أمس"
formatDateSmart(tomorrow, { locale: 'ar' }) // "غداً"

🌐 Web Application Support

Perfect for React, Vue, Angular, and vanilla JavaScript applications:

Quick Examples

React.js

import { initializeApp, formatDateLocalized } from 'date-core'

// Initialize
initializeApp({ locale: 'en' })

// Use in component
function DateComponent() {
  const date = new Date()
  const locale = 'en'
  return (
    <div>
      <p>Date: {formatDateLocalized(date)}</p>
      <p>Locale: {locale}</p>
    </div>
    // Output: Date: 15 January 2024, Locale: en
  )
}

Vue.js

// main.js
import { initializeApp } from 'date-core'
initializeApp({ locale: 'en' })

// Component
import { formatDateLocalized } from 'date-core'
export default {
  data() {
    return { date: new Date(), locale: 'en' }
  },
  computed: {
    formattedDate() {
      return formatDateLocalized(this.date)
      // Output: "15 January 2024"
    },
  },
}

Vanilla JavaScript

import { initializeApp, formatDateLocalized } from 'date-core'

initializeApp({ locale: 'en' })
const date = new Date()
document.getElementById('date').textContent = formatDateLocalized(date)
// Output: "15 January 2024"

Key Features for Web Apps

  • ES6 Modules - Works with Webpack, Vite, Rollup
  • Tree Shaking - Only import what you need
  • TypeScript Ready - Full type definitions
  • Framework Agnostic - React, Vue, Angular, vanilla JS
  • Performance Optimized - Minimal overhead

🛡️ Error Handling

Comprehensive Invalid Date Protection

All functions now safely handle invalid dates with:

  • Automatic validation - Every date input is validated
  • Safe fallbacks - Invalid dates fallback to current date
  • Detailed error messages - Helpful debugging information
  • Configurable behavior - Customize error handling during app initialization
  • Performance optimized - Minimal overhead for valid dates

What Happens with Invalid Dates

import { formatDate, isValidDate, getDateValidationInfo } from 'date-core'

// Invalid dates are handled safely
formatDate('invalid-date') // Returns current date formatted
formatDate(null) // Returns current date formatted
formatDate('2024-13-45') // Returns current date formatted

// Check if date is valid
isValidDate('invalid-date') // false
isValidDate('2024-12-25') // true

// Get detailed validation info
const info = getDateValidationInfo('invalid-date')
console.log(info)
// Console Output:
// {
//   isValid: false,
//   error: 'Date results in NaN',
//   fallback: Date object
// }

Error Handling Configuration During App Initialization

import { initializeApp } from 'date-core'

// Configure error handling during app initialization
initializeApp({
  locale: 'en',

  // Error handling configuration
  logErrors: true, // Enable/disable console error logging
  fallbackDate: new Date('2024-01-01'), // Custom fallback date
  fallbackString: 'Date Error', // Custom fallback string
  fallbackNumber: 0, // Custom fallback number
  messages: {
    invalidDate: 'Custom: Invalid date provided',
    invalidDateNull: 'Custom: Date cannot be null',
    invalidDateEmpty: 'Custom: Date cannot be empty',
    invalidDateNaN: 'Custom: Date results in NaN',
    // ... more custom messages
  },
})

Real-World Error Scenarios

// Scenario 1: API returns null date
const apiResponse = { createdAt: null, updatedAt: undefined }
formatDateLocalized(apiResponse.createdAt) // Safe fallback
formatDateLocalized(apiResponse.updatedAt) // Safe fallback

// Scenario 2: User input validation
const userInputs = ['', 'invalid', '2024-13-01', '2024-02-30']
userInputs.forEach((input) => {
  const isValid = isValidDate(input)
  const formatted = isValid ? formatDate(input) : 'Invalid input'
  console.log(`Input: "${input}" -> Valid: ${isValid}, Formatted: ${formatted}`)
})

// Console Output:
// Input: "" -> Valid: false, Formatted: Invalid input
// Input: "invalid" -> Valid: false, Formatted: Invalid input
// Input: "2024-13-01" -> Valid: false, Formatted: Invalid input
// Input: "2024-02-30" -> Valid: false, Formatted: Invalid input

🔇 Production-Ready Logging

The package includes intelligent logging that automatically adapts to your environment:

Automatic Environment Detection

import { initializeApp } from 'date-core'

// Automatically detects environment
// Development: Helpful debugging information
// Production: Clean, no console spam
initializeApp({ locale: 'en' })

Custom Logging (Optional)

import { configureLogger, initializeApp } from 'date-core'

// Optional: Configure logging behavior
configureLogger({
  enabled: process.env.NODE_ENV !== 'production',
  level: 'warn',
})

initializeApp({ locale: 'en' })

// Scenario 3: Database date handling
const dbDates = [null, '2024-12-25', 'invalid-date', '2024-02-29']
dbDates.forEach((dbDate) => {
  const validation = getDateValidationInfo(dbDate)
  console.log(`DB Date: ${JSON.stringify(dbDate)}`)
  console.log(`  Valid: ${validation.isValid}`)
  console.log(`  Error: ${validation.error || 'None'}`)
  console.log(`  Safe Format: ${formatDate(dbDate)}`)
})

// Console Output:
// DB Date: null
//   Valid: false
//   Error: Date cannot be null
//   Safe Format: 15 January 2024
// DB Date: "2024-12-25"
//   Valid: true
//   Error: None
//   Safe Format: 25 December 2024
// DB Date: "invalid-date"
//   Valid: false
//   Error: Date results in NaN
//   Safe Format: 15 January 2024
// DB Date: "2024-02-29"
//   Valid: false
//   Error: Invalid date (February 29, 2024 is not a leap year)
//   Safe Format: 15 January 2024

🌍 Multi-Locale Support

Built-in Locales

The package comes with 5 built-in locales:

  • English (en) - Default locale
  • Arabic (ar) - Full RTL support with Arabic numerals
  • French (fr) - French date and time formatting
  • Spanish (es) - Spanish date and time formatting
  • German (de) - German date and time formatting

Dynamic Locale Registration

import { registerLocale, setLocale } from 'date-core'
import { fr, es, de } from 'date-core'

// Register additional locales
registerLocale('fr', fr)
registerLocale('es', es)
registerLocale('de', de)

// Switch to any registered locale
setLocale('fr')

// Text view examples with different locales
const date = new Date()

// English
<p>Date: {formatDateLocalized(date, { locale: 'en' })}</p>
// Output: Date: 15 January 2024

// Arabic
<p>Date: {formatDateLocalized(date, { locale: 'ar' })}</p>
// Output: Date: ١٥ يناير ٢٠٢٤

// French
<p>Date: {formatDateLocalized(date, { locale: 'fr' })}</p>
// Output: Date: 15 janvier 2024

// Spanish
<Text>Date: {formatDateLocalized(date, { locale: 'es' })}</Text>
// Output: Date: 15 de enero de 2024

// German
<Text>Date: {formatDateLocalized(date, { locale: 'de' })}</Text>
// Output: Date: 15. Januar 2024

Custom Locale Files

You can create and register your own locale files:

import {registerCustomLocale} from 'date-core';

// Your custom locale configuration
const myCustomLocale = {
  months: ['January', 'February', 'March', ...],
  monthsShort: ['Jan', 'Feb', 'Mar', ...],
  weekdays: ['Sunday', 'Monday', 'Tuesday', ...],
  weekdaysShort: ['Sun', 'Mon', 'Tue', ...],
  weekdaysMin: ['Su', 'Mo', 'Tu', ...],
  relativeTime: {
    future: 'in %s',
    past: '%s ago',
    s: 'a few seconds',
    // ... more translations
  },
  calendar: {
    sameDay: 'today at LT',
    nextDay: 'tomorrow at LT',
    // ... more calendar formats
  },
  numberMap: {}, // For custom numeral systems
  symbolMap: {}, // For custom numeral systems
};

// Register your custom locale
registerCustomLocale('my-locale', myCustomLocale);

// Use your custom locale
setLocale('my-locale');

Locale Management Functions

import {
  getAvailableLocales,
  getCustomLocales,
  getBuiltInLocales,
  getLocaleInfo,
  removeCustomLocale,
  resetToDefaults,
} from 'date-core'

// Get all available locales
const allLocales = getAvailableLocales() // ['en', 'ar', 'fr', 'es', 'de', 'my-locale']

// Get custom locales only
const customLocales = getCustomLocales() // ['my-locale']

// Get built-in locales only
const builtInLocales = getBuiltInLocales() // ['en', 'ar', 'fr', 'es', 'de']

// Get locale information
const info = getLocaleInfo('ar')
// {
//   code: 'ar',
//   isCustom: false,
//   isBuiltIn: true,
//   hasArabicNumerals: true,
//   sampleDate: 'يناير',
//   sampleDay: 'الأحد'
// }

// Remove a custom locale
removeCustomLocale('my-locale')

// Reset to defaults
resetToDefaults()

📋 Available Functions

Core Functions

  • Basic Formatting: 5 functions
  • Localized Formatting: 6 functions
  • Relative Time: 3 functions
  • Day/Month Names: 2 functions
  • Date Checking: 6 functions
  • Date Manipulation: 4 functions
  • Date Ranges: 6 functions
  • Date Differences: 3 functions
  • Parsing/Validation: 4 functions
  • Locale Management: 15+ functions
  • Error Handling: 4 functions
  • App Initialization: 3 functions

Demo Functions (30+ total)

  • Basic Usage: 8 functions
  • Advanced Usage: 6 functions
  • Multi-Locale: 8 functions
  • Error Handling: 8 functions
  • App Initialization: 13 functions

💡 Usage Examples

Basic Usage (Uses App Locale)

import {
  formatDateLocalized,
  getRelativeTimeLocalized,
  getDayName,
} from 'date-core'

const date = formatDateLocalized(new Date()) // Uses app locale
const relative = getRelativeTimeLocalized(someDate) // Uses app locale
const dayName = getDayName(new Date(), { format: 'short' }) // Uses app locale

Force Specific Locale

const arabicDate = formatDateLocalized(new Date(), { locale: 'ar' }) // Force Arabic
const englishDate = formatDateLocalized(new Date(), { locale: 'en' }) // Force English
const frenchDay = getDayName(new Date(), { locale: 'fr', format: 'short' }) // French short day

React Native Component

import React from 'react'
import { View, Text } from 'react-native'
import { formatDateSmart, formatTimeLocalized, getDayName } from 'date-core'

const DateDisplay = ({ date }) => (
  <View>
    <Text>Date: {formatDateSmart(date)}</Text>
    <Text>Time: {formatTimeLocalized(date)}</Text>
    <Text>Day: {getDayName(date, { format: 'short' })}</Text>
  </View>
)

Multi-Locale Component

import React from 'react'
import { View, Text } from 'react-native'
import { formatDateLocalized, setLocale } from 'date-core'

const MultiLocaleDisplay = ({ date, locale }) => {
  // Switch to specified locale
  setLocale(locale)

  return (
    <View>
      <Text>Date: {formatDateLocalized(date)}</Text>
      <Text>Locale: {locale}</Text>
    </View>
  )
}

📖 API Reference

Core Functions

Function Description Parameters Returns
formatDate(date) Format date as ISO string date: Date|string string
formatDateLocalized(date, options) Format date with locale support date: Date|string, options: {locale?, format?} string
formatLongDate(date, options) Format date in long format date: Date|string, options: {locale?, format?} string
getRelativeTimeLocalized(date) Get relative time (e.g., "2 hours ago") date: Date|string string
getDayName(date, options) Get day name date: Date|string, options: {locale?, format?} string
getMonthName(date, options) Get month name date: Date|string, options: {locale?, format?} string
isToday(date) Check if date is today date: Date|string boolean
isYesterday(date) Check if date is yesterday date: Date|string boolean
addDays(date, days) Add days to date date: Date|string, days: number Date
subtractDays(date, days) Subtract days from date date: Date|string, days: number Date
startOfDay(date) Get start of day date: Date|string Date
endOfDay(date) Get end of day date: Date|string Date
isValidDate(date) Validate date date: any boolean

Locale Management

Function Description Parameters Returns
setLocale(locale) Set current locale locale: string void
getLocale() Get current locale - string
registerLocale(code, config) Register new locale code: string, config: object void
getAvailableLocales() Get all available locales - string[]

App Configuration

Function Description Parameters Returns
initializeApp(config) Initialize app with configuration config: object object
configureErrorHandling(config) Configure error handling config: object void

🎨 Advanced Features

Complete Function Reference

Date-Core Function Output Example Description
formatDate(date) "2024-01-15" ISO date format
formatDateDDMMYYYY(date) "15/01/2024" European format
formatTime(date) "14:30" 24-hour time
formatLongDate(date, {format: 'LL'}) "15 January 2024" Long date
formatLongDate(date, {format: 'LLLL'}) "Monday, 15 January 2024 14:30" Full long date
getRelativeTimeLocalized(date) "2 hours ago" Relative time
formatCalendar(date) "Today at 2:30 PM" Calendar context
getDayName(date) "Monday" Day name
getDayName(date, {format: 'short'}) "Mon" Short day name
getMonthName(date) "January" Month name
getMonthName(date, {format: 'short'}) "Jan" Short month name
isToday(date) true Check if today
isYesterday(date) true Check if yesterday
addDays(date, 1) Date object Add days
subtractDays(date, 1) Date object Subtract days
startOfDay(date) Date object Start of day
endOfDay(date) Date object End of day
getDaysDifference(date1, date2) 5 Days difference
isValidDate(date) true Date validation

Arabic Numeral Support

// Automatic Arabic numeral conversion
formatDateLocalized(new Date(), { locale: 'ar' }) // "١٥ يناير ٢٠٢٤"
formatTimeLocalized(new Date(), { locale: 'ar' }) // "١٤:٣٠"
getDayName(new Date(), { locale: 'ar', format: 'short' }) // "إث"

Smart Date Formatting

formatDateSmart(date) // "اليوم" (if today)
formatDateSmart(yesterday) // "أمس" (if yesterday)
formatDateSmart(lastWeek) // "الإثنين" (if this week)

Long Date Formats

formatLongDate(date, { locale: 'ar', format: 'LL' }) // "١٥ يناير ٢٠٢٤"
formatLongDate(date, { locale: 'ar', format: 'LLLL' }) // "الإثنين ١٥ يناير ٢٠٢٤ ١٤:٣٠"

Calendar Context

formatCalendar(date, { locale: 'ar' }) // "اليوم على الساعة ١٤:٣٠"

Multiple Format Options

// Day name formats
getDayName(date, { format: 'long' }) // "الإثنين"
getDayName(date, { format: 'short' }) // "إث"
getDayName(date, { format: 'min' }) // "إ"

// Date formats
formatDateLocalized(date, { format: 'short' }) // "15 Jan 2024"
formatDateLocalized(date, { format: 'long' }) // "15 January 2024"
formatDateLocalized(date, { format: 'weekday' }) // "Monday, 15 January 2024"

📊 Performance Benefits

  • Bundle Size: Compact library with tree-shaking support
  • Execution Speed: Optimized for React Native and web performance
  • Memory Usage: Efficient memory footprint
  • Tree Shaking: Only import what you need
  • Error Handling: Minimal overhead for valid dates

🧪 Testing

Using Demos

import {
  TestLocaleManager,
  runMultiLocaleDemos,
  runErrorHandlingDemos,
  runAppInitializationDemos,
} from 'date-core/demos'

// Run basic tests
TestLocaleManager()

// Run comprehensive multi-locale tests
runMultiLocaleDemos()

// Run error handling tests
runErrorHandlingDemos()

// Run app initialization tests
runAppInitializationDemos()

Manual Testing

import {
  initializeApp,
  setLocale,
  testSpecificLocale,
  testErrorScenario,
  testAppInitialization,
} from 'date-core/demos'

// Test app initialization
const result = testAppInitialization({
  locale: 'ar',
  logErrors: true,
})

// Test specific locale
testSpecificLocale('fr')

// Test error scenarios
testErrorScenario('invalid-date', 'formatDate')
testErrorScenario(null, 'formatDateLocalized')

// Test locale switching
setLocale('en')
console.log('Switched to English')

📚 Additional Resources

  • Demos: See demos/ folder for comprehensive usage examples
  • Multi-Locale Demo: See demos/multi-locale-demo.js for dynamic locale registration
  • Error Handling Demo: See demos/error-handling-demo.js for invalid date handling
  • App Initialization Demo: See demos/app-initialization-demo.js for configuration examples
  • Locale Configs: See lib/locales/ folder for locale configurations
  • Custom Locales: Create your own locale files following the same format

🤝 Contributing

We welcome contributions! Please visit our GitHub repository for contribution guidelines.

📄 License

This project is licensed under the MIT License - see the LICENSE file for details.

🙏 Acknowledgments

  • Built with modern JavaScript (ES6+) best practices
  • Inspired by the need for compact, performant date utilities
  • Special thanks to the React Native community for feedback and testing

About

Modern, compact date utilities library for React Native and web applications

Resources

License

Contributing

Stars

Watchers

Forks

Packages

No packages published