Skip to content

arnaldo-tomo/momento-rn

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

2 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

πŸ•°οΈ Momento

A powerful and intuitive date library for React Native and Expo, inspired by PHP's Carbon

npm version License: MIT TypeScript React Native

πŸš€ Installation

npm install momento-rn
# or
yarn add momento-rn

✨ Features

  • 🌍 Full Localization - Native support for Portuguese, English, and more
  • ⏰ Fluent API - Intuitive date manipulation like PHP's Carbon
  • πŸ“± React Native First - Optimized specifically for RN/Expo
  • πŸ”„ Immutable - All operations return new instances
  • 🎯 TypeScript - Complete typing and IntelliSense
  • πŸ“… Advanced Comparisons - Rich methods for date comparison
  • 🌐 Timezone Support - Complete timezone handling
  • 🎨 Flexible Formatting - Custom formatting in any language
  • ⚑ Performance - Optimized for mobile applications
  • πŸ§ͺ Tested - Comprehensive test coverage

🎯 Why Momento?

If you've used Carbon in PHP, you'll feel at home! Momento brings all the elegance and power of Carbon to the React Native world, with some mobile-specific improvements.

import Momento from 'momento-rn';

// Intuitive creation
const now = Momento.now();
const tomorrow = Momento.tomorrow();
const birthday = Momento.create(1995, 8, 15);

// Fluent manipulation
const future = now
  .addYears(1)
  .addMonths(6)
  .addDays(15)
  .startOfDay();

// Natural comparisons
if (birthday.isToday()) {
  console.log('Happy birthday! πŸŽ‰');
}

// Localized formatting
console.log(now.locale('pt').format('DDDD, D [de] MMMM [de] YYYY'));
// "Monday, 15 de July de 2024"

// Humanized differences
console.log(tomorrow.diffForHumans()); // "in 1 day"

πŸ“– Quick Documentation

Creating Instances

// Various ways to create dates
const now = Momento.now();
const today = Momento.today();
const tomorrow = Momento.tomorrow();
const yesterday = Momento.yesterday();

// Specific date
const date = Momento.create(2024, 12, 25, 14, 30, 0);

// From string
const parsed = Momento.parse('2024-12-25');

// From timestamp
const fromTimestamp = Momento.createFromTimestamp(1640995200);

Manipulation

const date = Momento.create(2024, 1, 15);

// Addition
const future = date
  .addYears(1)
  .addMonths(2)
  .addWeeks(3)
  .addDays(4)
  .addHours(5);

// Subtraction
const past = date
  .subYears(1)
  .subMonths(1)
  .subDays(10);

// Start/end of periods
const startOfYear = date.startOfYear();
const endOfMonth = date.endOfMonth();
const startOfWeek = date.startOfWeek();

Comparisons

const date1 = Momento.create(2024, 6, 15);
const date2 = Momento.create(2024, 6, 20);

// Basic comparisons
date1.isBefore(date2);  // true
date1.isAfter(date2);   // false
date1.equals(date2);    // false

// Type checks
date1.isToday();        // false
date1.isFuture();       // true/false depending on when executed
date1.isWeekend();      // true if Saturday/Sunday
date1.isLeapYear();     // true if leap year

// Same period
date1.isSameDay(date2);    // false
date1.isSameMonth(date2);  // true
date1.isSameYear(date2);   // true

Formatting

const date = Momento.create(2024, 3, 15, 14, 30, 45);

// Standard formats
date.toDateString();      // "2024-03-15"
date.toTimeString();      // "14:30:45"
date.toDateTimeString();  // "2024-03-15 14:30:45"
date.toISOString();       // ISO 8601

// Custom formatting
date.format('DD/MM/YYYY HH:mm');           // "15/03/2024 14:30"
date.format('MMMM D, YYYY [at] h:mm A');   // "March 15, 2024 at 2:30 PM"
date.format('DDDD [the] D[th] [of] MMMM'); // "Friday the 15th of March"

// With localization
date.locale('pt').format('MMMM');  // "MarΓ§o"
date.locale('en').format('MMMM');  // "March"

Differences

const start = Momento.create(2024, 1, 1);
const end = Momento.create(2024, 12, 31);

// Numeric differences
start.diffInDays(end);     // 365
start.diffInMonths(end);   // 11
start.diffInHours(end);    // 8760

// Humanized differences
end.diffForHumans();        // "in 5 months" (depending on current date)
start.diffForHumans(end);   // "11 months before"

// With precision
start.diffInHours(end, { float: true }); // 8760.0

Localization

// Global configuration
Momento.setLocale('pt');

// Per instance
const datePortuguese = Momento.now().locale('pt');
const dateEnglish = Momento.now().locale('en');

console.log(datePortuguese.format('DDDD, MMMM'));
// "Segunda-feira, Julho"

console.log(dateEnglish.format('DDDD, MMMM'));
// "Monday, July"

πŸ”§ Usage with React Native

Live Clock

import React, { useState, useEffect } from 'react';
import { Text, View } from 'react-native';
import Momento from 'momento-rn';

const LiveClock = () => {
  const [time, setTime] = useState(Momento.now());

  useEffect(() => {
    const interval = setInterval(() => {
      setTime(Momento.now());
    }, 1000);

    return () => clearInterval(interval);
  }, []);

  return (
    <View>
      <Text style={{ fontSize: 24, fontWeight: 'bold' }}>
        {time.format('HH:mm:ss')}
      </Text>
      <Text>
        {time.locale('en').format('DDDD, MMMM D')}
      </Text>
    </View>
  );
};

Birthday Countdown

const BirthdayCountdown = ({ birthDate, name }) => {
  const birth = Momento.parse(birthDate);
  const now = Momento.now();
  
  const nextBirthday = birth.setYear(now.year);
  if (nextBirthday.isBefore(now)) {
    nextBirthday.addYears(1);
  }
  
  const daysUntil = now.diffInDays(nextBirthday, { absolute: true });
  const age = birth.age;

  return (
    <View>
      <Text>{name}</Text>
      <Text>Age: {age} years</Text>
      <Text>
        {daysUntil === 0 
          ? 'Happy Birthday! πŸŽ‰' 
          : `${daysUntil} days until birthday`
        }
      </Text>
    </View>
  );
};

Notification Time Formatting

const formatNotificationTime = (date: Momento): string => {
  const now = Momento.now();
  const diffInMinutes = now.diffInMinutes(date, { absolute: true });
  
  if (diffInMinutes < 1) {
    return 'now';
  } else if (diffInMinutes < 60) {
    return `${diffInMinutes}m`;
  } else if (diffInMinutes < 1440) {
    return `${Math.floor(diffInMinutes / 60)}h`;
  } else {
    return date.format('MM/DD');
  }
};

// Usage
console.log(formatNotificationTime(Momento.now().subMinutes(30))); // "30m"
console.log(formatNotificationTime(Momento.now().subHours(2)));   // "2h"
console.log(formatNotificationTime(Momento.now().subDays(2)));    // "07/13"

🌍 Supported Locales

  • en - English
  • pt - Portuguese (Brazil/Portugal/Mozambique)
  • More locales in development...

πŸ› οΈ Utility Functions

// Business days
const addBusinessDays = (date: Momento, days: number): Momento => {
  let result = date.clone();
  let addedDays = 0;
  
  while (addedDays < days) {
    result = result.addDays(1);
    if (result.isWeekday()) {
      addedDays++;
    }
  }
  
  return result;
};

// Calculate vacation days
const getVacationDays = (start: Momento, end: Momento, holidays: Momento[] = []): number => {
  let totalDays = 0;
  let current = start.clone();
  
  while (current.isSameOrBefore(end)) {
    const isHoliday = holidays.some(holiday => current.isSameDay(holiday));
    if (current.isWeekday() && !isHoliday) {
      totalDays++;
    }
    current = current.addDays(1);
  }
  
  return totalDays;
};

// Month calendar
const getMonthCalendar = (date: Momento): Momento[][] => {
  const startOfMonth = date.startOfMonth();
  const endOfMonth = date.endOfMonth();
  const startOfCalendar = startOfMonth.startOfWeek();
  const endOfCalendar = endOfMonth.endOfWeek();
  
  const weeks: Momento[][] = [];
  let current = startOfCalendar;
  
  while (current.isSameOrBefore(endOfCalendar)) {
    const week: Momento[] = [];
    for (let i = 0; i < 7; i++) {
      week.push(current.clone());
      current = current.addDays(1);
    }
    weeks.push(week);
  }
  
  return weeks;
};

πŸ“š Complete API

Static Constructors

  • Momento.now(timezone?)
  • Momento.today(timezone?)
  • Momento.tomorrow(timezone?)
  • Momento.yesterday(timezone?)
  • Momento.create(year?, month?, day?, hour?, minute?, second?, timezone?)
  • Momento.parse(dateString, timezone?)
  • Momento.createFromTimestamp(timestamp, timezone?)
  • Momento.createFromTimestampMs(timestamp, timezone?)

Getters

  • year, month, day, hour, minute, second, millisecond
  • dayOfWeek, dayOfYear, weekOfYear, quarter, age

Manipulation

  • addYears(), addMonths(), addWeeks(), addDays(), addHours(), addMinutes(), addSeconds()
  • subYears(), subMonths(), subWeeks(), subDays(), subHours(), subMinutes(), subSeconds()
  • setYear(), setMonth(), setDay(), setHour(), setMinute(), setSecond()

Start/End of Periods

  • startOfYear(), endOfYear()
  • startOfMonth(), endOfMonth()
  • startOfWeek(), endOfWeek()
  • startOfDay(), endOfDay()
  • startOfHour(), endOfHour()
  • startOfMinute(), endOfMinute()

Comparisons

  • equals(), isBefore(), isAfter(), isSameOrBefore(), isSameOrAfter()
  • isBetween(), isToday(), isTomorrow(), isYesterday()
  • isFuture(), isPast(), isWeekday(), isWeekend(), isLeapYear()
  • isSameYear(), isSameMonth(), isSameDay(), isSameHour(), isSameMinute()

Differences

  • diff(), diffInYears(), diffInMonths(), diffInWeeks(), diffInDays()
  • diffInHours(), diffInMinutes(), diffInSeconds(), diffForHumans()

Formatting

  • format(), toDateString(), toTimeString(), toDateTimeString()
  • toISOString(), toJSON(), toString()

Utilities

  • clone(), copy(), locale(), timezone()
  • getDate(), getTimestamp(), getTimestampMs()
  • Momento.min(), Momento.max(), Momento.isValidDate()

πŸ”§ Advanced Configuration

Global Timezone

// Set default timezone
Momento.setTimezone('America/Sao_Paulo');

// Get current timezone
const tz = Momento.getTimezone();

Week Start

// Configure week start (0 = Sunday, 1 = Monday)
Momento.setWeekStartsAt(1); // Monday
Momento.setWeekEndsAt(0);   // Sunday

πŸ§ͺ Testing

# Run tests
npm test

# Tests with coverage
npm run test:coverage

# Tests in watch mode
npm run test:watch

🀝 Contributing

Contributions are very welcome! To contribute:

  1. Fork the project
  2. Create your feature branch (git checkout -b feature/AmazingFeature)
  3. Commit your changes (git commit -m 'Add some AmazingFeature')
  4. Push to the branch (git push origin feature/AmazingFeature)
  5. Open a Pull Request

Local Development

# Clone the repository
git clone https://github.com/arnaldotomo/momento-rn.git
cd momento-rn

# Install dependencies
npm install

# Run tests
npm test

# Build the library
npm run build

πŸ“‹ Roadmap

  • More localizations (es, fr, de, it)
  • Alternative calendar support
  • Plugin system for extensions
  • Integration with react-native-date-picker
  • More advanced periods and intervals support
  • Humanized duration formatting
  • Natural language date parsing

πŸ™ Inspirations

  • Carbon (PHP) - The main inspiration for this library
  • Moment.js - For popularizing fluent date manipulation in JS
  • Day.js - For the lightweight and modern approach
  • Date-fns - For well-thought utility functions

πŸ“„ License

MIT Β© Arnaldo Tomo


Made with ❀️ in Mozambique by Arnaldo Tomo

"Because dealing with dates shouldn't be complicated" - Arnaldo Tomo

πŸ“ž Support

🌟 If you like it, leave a star!

If this project helped you, consider leaving a ⭐ on GitHub. It motivates me to keep developing!

πŸ”— Useful Links

About

A powerful date library for React Native, inspired by PHP's Carbon

Resources

License

Stars

Watchers

Forks

Packages

No packages published