Skip to content

react-native-date

The fastest date library for React Native. Powered by C++ and Nitro Modules with zero-config localization.

Is this library for you?

Perfect for

  • Apps that render many dates (calendars, timelines, feeds, chat apps)
  • Apps targeting low-end devices where JS performance matters
  • Apps requiring multiple locales without bundle size bloat
  • Apps that need timezone conversions at scale

Maybe not needed

If your app only formats a few dates occasionally, date-fns or Day.js work fine. This library shines when performance and localization are critical - rendering hundreds of dates, supporting many languages, or running smoothly on budget devices.

Why react-native-date?

Zero-Config Localization

No locale plugins. No imports. No bundles. The library reads locales directly from the operating system.

LibraryLocale Support
date-fnsImport each locale separately (~3KB per locale)
Day.jsInstall locale plugin + import each locale
Moment.jsImport locales or full bundle (~300KB)
react-native-dateBuilt-in. Reads from device OS. Zero config.
typescript
import { format, setLocale } from '@bernagl/react-native-date';

// Works immediately - uses device's language
format(Date.now(), 'MMMM'); // "November" (or user's language)

// Or set explicitly - no imports needed
setLocale('ja');
format(Date.now(), 'MMMM'); // "11月"

setLocale('ar');
format(Date.now(), 'MMMM'); // "نوفمبر"

All 150+ locales supported by iOS/Android work out of the box.

Native Performance

Built with C++ and Nitro Modules for synchronous, near-native speed.

iPhone 14 Pro (ops/sec - higher is better)

OperationNativeDatedate-fnsDay.jsLuxon
now()445K 3.2x278K214K139K
parse()2.0M 71x94K329K28K
format()771K 25x31K103K34K
addDays()1.7M 65x612K68K26K
addMonths()279K400K 1.4x32K26K
diffInDays()1.6M 200x74K104K8K
startOfDay()1.8M 31x727K136K58K
endOfDay()1.8M 164x727K136K11K
isWeekend()2.1M 16x711K383K134K
isLeapYear()1.8M 8.9x693K400K202K
getComponents()673K 4.6x147K296K180K
addHours()1.7M 65x414K158K26K
addMinutes()1.7M 65x642K158K26K
addSeconds()1.7M 65x456K159K26K
formatUTC()805K 45x18K80K29K
formatInTZ()400K 27x19K15K23K

Low-End Android Device (ops/sec - higher is better)

OperationNativeDatedate-fnsDay.jsLuxon
now()530K 17x162K76K32K
parse()465K 116x13K46K4K
format()270K 54x5K16K5K
addDays()378K 95x107K10K4K
addMonths()80K 20x69K5K4K
diffInDays()351K 351x13K15K1K
startOfDay()392K 49x130K20K8K
endOfDay()396K 198x129K20K2K
isWeekend()445K 23x128K59K19K
isLeapYear()419K 14x125K70K29K
getComponents()141K 5.6x25K47K27K
addHours()367K 92x75K24K4K
addMinutes()377K 94x113K23K4K
addSeconds()376K 94x81K23K4K
formatUTC()292K 146x2K12K4K
formatInTZ()38K 225x2K169973

Performance Summary

react-native-date wins 15/16 on iOS and 16/16 on Android. Only addMonths() loses to date-fns on iOS - we're actively working on optimizing this.

Low-End Device Impact

The performance gap widens significantly on budget devices:

  • format(): 25x faster on iOS → 54x faster on Android
  • formatUTC(): 45x faster on iOS → 146x faster on Android

The native C++ implementation shines on low-end devices where JavaScript performance is constrained. Essential for apps targeting emerging markets.

Benchmark Methodology

Results obtained from the example app using the Benchmark tab. Each operation runs 1,000 iterations to calculate ops/sec. Run the example app on your own device to verify results.

Familiar API

Works like date-fns or Day.js - pick your style:

typescript
// Functional (date-fns style)
import { format, addDays, startOfMonth } from '@bernagl/react-native-date';
format(addDays(Date.now(), 7), 'yyyy-MM-dd');

// Chainable (Day.js style)
import { nativeDate } from '@bernagl/react-native-date';
nativeDate().addDays(7).format('yyyy-MM-dd');

Tree-Shakeable

The library is fully tree-shakeable. Only import what you need:

typescript
// Only these functions are included in your bundle
import { format, addDays } from '@bernagl/react-native-date';

For optimal bundle size, the chainable API can be imported separately:

typescript
// Functional API only (smaller bundle)
import { format, addDays } from '@bernagl/react-native-date';

// Chainable API (explicit import)
import { nativeDate } from '@bernagl/react-native-date/chain';

Features

  • Fast - C++ core, no bridge overhead, synchronous calls
  • Zero-config locales - Reads from OS, no plugins or imports
  • 150+ locales - Every locale supported by iOS/Android
  • Timezone support - Full IANA timezone database from the OS
  • Timezone-aware predicates - Check "is today in Tokyo?" etc.
  • Expo compatible - Works with Expo Dev Client (SDK 54+)
  • Tiny footprint - No locale bundles, minimal JS
  • Tree-shakeable - Only bundle what you use
  • Type-safe - Full TypeScript support
  • Two API styles - Functional or chainable

Requirements

PlatformMinimum Version
iOS13.0+
AndroidAPI 24+ (Android 7.0)
React Native0.76+ (New Architecture)

Installation

bash
npm install @bernagl/react-native-date react-native-nitro-modules

React Native CLI

bash
cd ios && pod install

Expo

Requires Expo Dev Client (not Expo Go):

bash
npx expo prebuild
npx expo run:ios

No additional setup. No locale configuration. Just install and use.


Quick Start

typescript
import {
  now,
  format,
  addDays,
  diffInDays,
  isToday,
  setLocale,
  getTimezone
} from '@bernagl/react-native-date';

// Current timestamp
const timestamp = now();

// Format (uses device locale automatically)
format(timestamp, 'EEEE, MMMM d, yyyy');
// "Sunday, November 30, 2025" (or localized)

// Date math
const nextWeek = addDays(timestamp, 7);
diffInDays(nextWeek, timestamp); // 7

// Predicates
isToday(timestamp); // true

// Timezone (from device)
getTimezone(); // "America/New_York"

// Change locale (optional - defaults to device language)
setLocale('es');
format(timestamp, 'EEEE, d MMMM'); // "domingo, 30 noviembre"

How Locales Work

The library uses native OS APIs - no JavaScript locale data needed:

PlatformNative Classes
iOSNSLocale, NSDateFormatter
Androidjava.util.Locale, DateFormatSymbols

Default behavior: If you never call setLocale(), the library automatically uses the device's language setting. Month names, day names, and formatting respect the user's preferences with zero configuration.

typescript
// User's device is set to French
format(Date.now(), 'EEEE d MMMM yyyy');
// "dimanche 30 novembre 2025" - automatic!

Next Steps