๐Ÿ”ฅ Streak Calculator

License: MIT Pub Version Pub Likes Pub Monthly Downloads Github Stars Github Open Isssues Github Pull Request Github Last Commit X (formerly Twitter) Follow

A powerful and flexible Dart package for calculating activity streaks with support for daily, weekly, and monthly patterns.

Perfect for habit tracking apps, fitness applications, productivity tools, and any app that needs to measure user engagement consistency.

โœจ Features

  • ๐Ÿ”ฅ Current & Best Streaks: Track both ongoing streaks and historical records

  • ๐Ÿ—“๏ธ Multiple Streak Types: Daily, weekly, and monthly streak calculations

  • ๐ŸŽฏ Configurable Targets: Set custom goals for weekly (1-7 days) and monthly (1-28 days) streaks

  • ๐Ÿ“… Flexible Week Start: Configure any day of the week as your week start (Monday-Sunday)

  • ๐Ÿงน Smart Data Processing: Automatic duplicate removal, sorting, and time normalization

  • โšก High Performance: Optimized algorithms with O(1) lookups for large datasets

  • โœ… Null Safety: Full null safety support

๐Ÿš€ Quick Start

Add this to your package's pubspec.yaml file:

dependencies:
  streak_calculator: ^0.2.1

Then run:

dart pub get

๐Ÿ“‹ Basic Usage

Daily Streaks (Current + Best)

Perfect for tracking daily habits like meditation, exercise, or reading:

import 'package:streak_calculator/streak_calculator.dart';

void main() {
  // Track daily meditation sessions
  final meditationDates = [
    DateTime(2025, 9, 15),
    DateTime(2025, 9, 16),
    DateTime(2025, 9, 17),
    DateTime(2025, 9, 18),
    DateTime(2025, 9, 19), // Today
  ];
  final streakCalc = StreakCalculator(
    dates: meditationDates,
    streakType: StreakType.daily,
  );

  print('Current meditation streak: ${streakCalc.currentStreak} days');
  print('Best meditation streak: ${streakCalc.bestStreak} days');
}

Weekly Streaks (Current + Best)

Great for fitness goals like "workout at least 3 times per week":

import 'package:streak_calculator/streak_calculator.dart';

void main() {
  // Track workout sessions with goal of 3 workouts per week
  final workoutDates = [
    DateTime(2025, 9, 1),  // Week 1: Mon
    DateTime(2025, 9, 3),  // Week 1: Wed  
    DateTime(2025, 9, 5),  // Week 1: Fri (3 days - goal met!)
    DateTime(2025, 9, 9),  // Week 2: Mon
    DateTime(2025, 9, 11), // Week 2: Wed
    DateTime(2025, 9, 12), // Week 2: Thu (3 days - goal met!)
    DateTime(2025, 9, 16), // Week 3: Mon
    DateTime(2025, 9, 18), // Week 3: Wed (only 2 days - streak broken)
  ];

  final weeklyStreak = StreakCalculator(
    dates: workoutDates,
    streakType: StreakType.weekly,
    streakTarget: 3, // Need at least 3 workouts per week
    weekStartDay: DateTime.monday,
  );

  print('Weekly workout streak: ${weeklyStreak.currentStreak} weeks');
  print('Best weekly streak: ${weeklyStreak.bestStreak} weeks');
}

Monthly Streaks (Current + Best)

Ideal for broader goals like "read at least 10 days per month":

import 'package:streak_calculator/streak_calculator.dart';

void main() {
  // Track reading sessions with monthly target
  final readingDates = [
    // January 2025 - 12 reading days (goal met!)
    DateTime(2025, 1, 1), DateTime(2025, 1, 3), DateTime(2025, 1, 5),
    DateTime(2025, 1, 7), DateTime(2025, 1, 9), DateTime(2025, 1, 11),
    DateTime(2025, 1, 13), DateTime(2025, 1, 15), DateTime(2025, 1, 17),
    DateTime(2025, 1, 19), DateTime(2025, 1, 21), DateTime(2025, 1, 23),
    
    // February 2025 - 15 reading days (goal met!)
    DateTime(2025, 2, 2), DateTime(2025, 2, 4), DateTime(2025, 2, 6),
    DateTime(2025, 2, 8), DateTime(2025, 2, 10), DateTime(2025, 2, 12),
    DateTime(2025, 2, 14), DateTime(2025, 2, 16), DateTime(2025, 2, 18),
    DateTime(2025, 2, 20), DateTime(2025, 2, 22), DateTime(2025, 2, 24),
    DateTime(2025, 2, 26), DateTime(2025, 2, 27), DateTime(2025, 2, 28),
  ];

  final monthlyStreak = StreakCalculator(
    dates: readingDates,
    streakType: StreakType.monthly,
    streakTarget: 10, // Need at least 10 reading days per month
  );

  print('Monthly reading streak: ${monthlyStreak.currentStreak} months');
  print('Best monthly streak: ${monthlyStreak.bestStreak} months');
}

โš™๏ธ Configuration Options

Parameter Type Default Description
dates List<DateTime> Required List of activity dates
streakType StreakType Required daily, weekly, or monthly
streakTarget int 1 Days required per week (1-7) or month (1-28)
weekStartDay int DateTime.monday First day of week (1=Monday, 7=Sunday)

๐Ÿงฎ Streak Calculation Logic

  • Daily: Each consecutive day counts as +1 to streak
  • Weekly: Consecutive weeks with โ‰ฅ streakTarget days count as +1 to streak
  • Monthly: Consecutive months with โ‰ฅ streakTarget days count as +1 to streak

๐Ÿ”ง Advanced Configuration

Custom Week Start Days

// Start weeks on Sunday (perfect for US-based apps)
final sundayWeekStreak = StreakCalculator(
  dates: dates,
  streakType: StreakType.weekly,
  streakTarget: 2,
  weekStartDay: DateTime.sunday,
);

// Start weeks on Wednesday (custom business cycle)
final midWeekStreak = StreakCalculator(
  dates: dates,
  streakType: StreakType.weekly,
  streakTarget: 4,
  weekStartDay: DateTime.wednesday,
);

๐Ÿ› ๏ธ Data Handling

The package automatically handles messy real-world data:

void main() {
  // Messy data with duplicates, unsorted dates, and time components
  final messyData = [
    DateTime(2025, 9, 17, 14, 30), // Afternoon
    DateTime(2025, 9, 15, 9, 15),  // Morning (out of order)
    DateTime(2025, 9, 16, 23, 45), // Night
    DateTime(2025, 9, 17, 8, 0),   // Duplicate date (different time)
    DateTime(2025, 9, 18, 12, 0),  // Noon
  ];

  // The package automatically:
  // 1. Removes duplicate dates (keeps unique days only)
  // 2. Sorts dates chronologically
  // 3. Normalizes times to midnight
  // 4. Validates input parameters

  final calculator = StreakCalculator(
    dates: messyData,
    streakType: StreakType.daily,
  );

  print('Clean streak calculation: ${calculator.currentStreak}'); // 4 days
}

๐Ÿ“Š Performance & Benchmarks

Time Complexity

  • Initial Processing: O(n log n) for sorting and normalization
  • Streak Calculation: O(n) linear pass through sorted data
  • Memory Usage: O(n) for date storage with duplicate removal

Benchmark Results

Tested on MacMini M2 (2023), 16GB RAM, Dart 3.0+

Dataset Size Performance (Daily Streaks)

   100 dates:     0.45 ms
 1,000 dates:     1.23 ms
10,000 dates:     8.91 ms
50,000 dates:    33.92 ms
100,000 dates:   62.08 ms

Streak Type Performance (10,000 dates)

Daily  :  6.85 ms
Weekly :  6.96 ms
Monthly:  4.81 ms

Real-World Data Handling

Messy data processing:    4.47 ms
(10,000 dates with duplicates, random times, unsorted)

Want to test performance on your own hardware? See BenchMark Guide

๐Ÿ“ Contributing

Feel free to contribute! Check out the guides for more information.

โค๏ธโ€๐Ÿ”ฅ Enjoying this package?

Here are a few ways you can show support:

  • โญ๏ธ Star it on GitHub โ€“ stars help others discover it!
  • If this package helped you, please give it a โญ on pub.dev!
  • ๐Ÿ‘‰ Try my TypeFast app, a fun way to sharpen your touch typing skills with games.
  • ๐Ÿ‘‰ Explore more of my work!

Libraries

streak_calculator
A comprehensive streak calculation library for Dart applications.