Compare commits

..

2 commits
v1.0.0 ... main

Author SHA1 Message Date
Aric Camarata
7895dc7ee6 chore: polish README for P1 E6 2026-05-30 18:39:39 -04:00
Aric Camarata
cf07c69613 fix: remove invalid publisher field from pubspec
The publisher field is not recognized by pub and caused dart pub publish
--dry-run to exit 65. Publisher is configured on pub.dev, not in pubspec.
2026-05-29 15:53:38 -04:00
2 changed files with 20 additions and 111 deletions

126
README.md
View file

@ -3,8 +3,11 @@
[![pub package](https://img.shields.io/pub/v/moon_sighting.svg)](https://pub.dev/packages/moon_sighting) [![pub package](https://img.shields.io/pub/v/moon_sighting.svg)](https://pub.dev/packages/moon_sighting)
[![CI](https://github.com/acamarata/moon-sighting-dart/actions/workflows/ci.yml/badge.svg)](https://github.com/acamarata/moon-sighting-dart/actions/workflows/ci.yml) [![CI](https://github.com/acamarata/moon-sighting-dart/actions/workflows/ci.yml/badge.svg)](https://github.com/acamarata/moon-sighting-dart/actions/workflows/ci.yml)
[![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE) [![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)
[![Wiki](https://img.shields.io/badge/docs-wiki-blue)](https://github.com/acamarata/moon-sighting-dart/wiki)
Lunar crescent visibility for Dart and Flutter. Computes moon phase, topocentric position, illumination, and Yallop/Odeh crescent visibility criteria using Meeus algorithms. Zero dependencies. Lunar crescent visibility for Dart and Flutter. Moon phase, topocentric position, illumination, and Yallop/Odeh crescent criteria using Meeus algorithms. Zero dependencies.
Uses Meeus lite algorithms (~0.3 degree accuracy). The companion TypeScript package (`moon-sighting` on npm) uses JPL DE442S ephemeris for sub-arcminute precision.
## Installation ## Installation
@ -22,18 +25,16 @@ import 'package:moon_sighting/moon_sighting.dart';
final phase = getMoonPhase(); final phase = getMoonPhase();
print('${phase.phaseName} ${phase.phaseSymbol}'); print('${phase.phaseName} ${phase.phaseSymbol}');
print('Illumination: ${phase.illumination.toStringAsFixed(1)}%'); print('Illumination: ${phase.illumination.toStringAsFixed(1)}%');
print('Age: ${phase.age.toStringAsFixed(1)} hours');
// Moon position for an observer // Moon position for an observer
final pos = getMoonPosition(DateTime.now(), 51.5074, -0.1278, elevation: 10); final pos = getMoonPosition(DateTime.now(), 51.5074, -0.1278, elevation: 10);
print('Azimuth: ${pos.azimuth.toStringAsFixed(1)}'); print('Azimuth: ${pos.azimuth.toStringAsFixed(1)}');
print('Altitude: ${pos.altitude.toStringAsFixed(1)}'); print('Altitude: ${pos.altitude.toStringAsFixed(1)}');
print('Distance: ${pos.distance.toStringAsFixed(0)} km');
// Crescent visibility estimate (pass a post-sunset time) // Crescent visibility estimate (pass a post-sunset time)
final vis = getMoonVisibilityEstimate( final vis = getMoonVisibilityEstimate(
DateTime.utc(2025, 3, 31, 18, 30), DateTime.utc(2025, 3, 31, 18, 30),
21.4225, 39.8262, // Mecca 21.4225, 39.8262, // Makkah
); );
print('Zone: ${vis.zone.label}'); // A through D print('Zone: ${vis.zone.label}'); // A through D
print('Visible naked eye: ${vis.isVisibleNakedEye}'); print('Visible naked eye: ${vis.isVisibleNakedEye}');
@ -41,124 +42,33 @@ print('Visible naked eye: ${vis.isVisibleNakedEye}');
## API ## API
### getMoonPhase([DateTime? date]) Five public functions. See the [API Reference](https://github.com/acamarata/moon-sighting-dart/wiki/API-Reference) for full field tables.
Returns `MoonPhaseResult` with: | Function | Returns | Description |
| Field | Type | Description |
| --- | --- | --- | | --- | --- | --- |
| `phase` | `MoonPhaseName` | Enum: newMoon, waxingCrescent, firstQuarter, etc. | | `getMoonPhase([DateTime?])` | `MoonPhaseResult` | Phase name, illumination, age, next events |
| `phaseName` | `String` | Human-readable name | | `getMoonPosition(DateTime?, lat, lon)` | `MoonPosition` | Topocentric az/alt, distance |
| `phaseSymbol` | `String` | Moon emoji | | `getMoonIllumination([DateTime?])` | `MoonIlluminationResult` | Fraction, phase cycle, bright limb angle |
| `illumination` | `double` | Percent illuminated (0-100) | | `getMoonVisibilityEstimate(DateTime?, lat, lon)` | `MoonVisibilityEstimate` | Odeh V parameter, visibility zone A-D |
| `age` | `double` | Hours since last new moon | | `getMoon(DateTime?, lat, lon)` | `MoonSnapshot` | All four results combined |
| `elongationDeg` | `double` | Moon-Sun elongation in degrees |
| `isWaxing` | `bool` | True when illumination is increasing |
| `nextNewMoon` | `DateTime` | Next new moon (UTC) |
| `nextFullMoon` | `DateTime` | Next full moon (UTC) |
| `prevNewMoon` | `DateTime` | Previous new moon (UTC) |
### getMoonPosition(DateTime? date, double lat, double lon, {double elevation = 0})
Returns `MoonPosition` with:
| Field | Type | Description |
| --- | --- | --- |
| `azimuth` | `double` | Degrees from North, clockwise |
| `altitude` | `double` | Degrees above horizon (refraction applied) |
| `distance` | `double` | Earth-Moon distance in km |
| `parallacticAngle` | `double` | Parallactic angle in radians |
### getMoonIllumination([DateTime? date])
Returns `MoonIlluminationResult` with:
| Field | Type | Description |
| --- | --- | --- |
| `fraction` | `double` | Illuminated fraction (0-1) |
| `phase` | `double` | Phase cycle (0=new, 0.25=Q1, 0.5=full, 0.75=Q3) |
| `angle` | `double` | Bright limb position angle (radians) |
| `isWaxing` | `bool` | True when waxing |
### getMoonVisibilityEstimate(DateTime? date, double lat, double lon, {double elevation = 0})
Returns `MoonVisibilityEstimate` with:
| Field | Type | Description |
| --- | --- | --- |
| `v` | `double` | Odeh V parameter |
| `zone` | `OdehZone` | Visibility zone (a through d) |
| `description` | `String` | Zone description |
| `isVisibleNakedEye` | `bool` | True for zone A |
| `isVisibleWithOpticalAid` | `bool` | True for zones A and B |
| `arcl` | `double` | Sun-Moon elongation (degrees) |
| `arcv` | `double` | Arc of vision (degrees) |
| `w` | `double` | Crescent width (arc minutes) |
| `moonAboveHorizon` | `bool` | Moon above horizon at given time |
### getMoon(DateTime? date, double lat, double lon, {double elevation = 0})
Returns `MoonSnapshot` combining all four results: `phase`, `position`, `illumination`, `visibility`.
## Visibility Criteria
The Odeh criterion (2006) classifies crescent visibility into four zones:
| Zone | V threshold | Meaning |
| --- | --- | --- |
| A | V >= 5.65 | Visible with naked eye |
| B | V >= 2.00 | Visible with optical aid, may be seen naked eye |
| C | V >= -0.96 | Visible with optical aid only |
| D | V < -0.96 | Not visible even with optical aid |
The Yallop q-test (1997) uses six categories A through F with different threshold semantics. Both criteria use the same underlying polynomial for the minimum arc of vision as a function of crescent width.
## Accuracy ## Accuracy
All positions use Meeus (1998) approximations: All positions use Meeus (1998) approximations: Moon longitude < 0.3 deg, latitude < 0.2 deg, distance ~300 km. New/full moon times are within ~2 hours.
- **Sun:** < 0.01 deg ecliptic longitude error
- **Moon:** < 0.3 deg longitude, < 0.2 deg latitude
- **Distance:** ~300 km error (~0.08%)
- **New/full moon times:** within ~2 hours
The GCRS-to-topocentric conversion uses a simplified Earth rotation (ERA only, no nutation/precession), adding ~1 deg systematic error. This is acceptable for phase displays, illumination calculations, and approximate visibility estimates.
For high-precision crescent sighting reports with DE442S ephemeris accuracy, see the TypeScript [moon-sighting](https://github.com/acamarata/moon-sighting) package.
## Lite Mode vs Full Mode
This Dart package implements lite mode only. It covers moon phase, position, illumination, and quick visibility estimates using analytical Meeus algorithms with no external data files.
The full-mode features (DE442S JPL ephemeris, sub-arcsecond accuracy, rise/set event finding, best-time optimization, full sighting reports) are available in the TypeScript package.
## Architecture
Two-mode design: lite mode uses Jean Meeus Chapters 47 and 48 for moon phase, position, and illumination: zero dependencies, no file I/O, works in any Dart environment. The GCRS-to-topocentric conversion applies ERA-only Earth rotation (no full nutation/precession), which introduces a ~1 degree systematic error acceptable for display and quick-estimate use cases.
Full-mode features (DE442S ephemeris, sub-arcsecond accuracy, rise/set event finding) are in the TypeScript [moon-sighting](https://github.com/acamarata/moon-sighting) package.
## Compatibility
- Dart SDK >= 3.7.0
- Works in Flutter, Dart CLI, and server-side Dart
- Zero runtime dependencies
## Related ## Related
- [moon-sighting](https://github.com/acamarata/moon-sighting) (TypeScript) - Full-accuracy lunar crescent visibility with DE442S ephemeris - [moon-sighting](https://github.com/acamarata/moon-sighting) (TypeScript) - Full accuracy with DE442S ephemeris
- [nrel-spa](https://github.com/acamarata/nrel-spa) (TypeScript) - Pure JS NREL Solar Position Algorithm - [nrel-spa](https://github.com/acamarata/nrel-spa) (TypeScript) - NREL Solar Position Algorithm
- [pray-calc](https://github.com/acamarata/pray-calc) (JavaScript) - Islamic prayer time calculation - [pray-calc](https://github.com/acamarata/pray-calc) (TypeScript) - Islamic prayer times
- [luxon-hijri](https://github.com/acamarata/luxon-hijri) (TypeScript) - Hijri/Gregorian calendar conversion
## Acknowledgments ## Acknowledgments
Crescent visibility criteria implemented from: Crescent visibility criteria from:
- B.D. Yallop, "A Method for Predicting the First Sighting of the New Crescent Moon," NAO Technical Note No. 69, 1997. - B.D. Yallop, "A Method for Predicting the First Sighting of the New Crescent Moon," NAO Technical Note No. 69, 1997.
- M.Sh. Odeh, "New Criterion for Lunar Crescent Visibility," Experimental Astronomy 18(1), 39-64, 2006. - M.Sh. Odeh, "New Criterion for Lunar Crescent Visibility," Experimental Astronomy 18(1), 39-64, 2006.
- Jean Meeus, "Astronomical Algorithms," 2nd ed., Chapters 47 and 48.
Meeus positions from: Jean Meeus, "Astronomical Algorithms," 2nd ed., Chapters 47 and 48.
## License ## License

View file

@ -7,7 +7,6 @@ version: 1.0.0
homepage: https://github.com/acamarata/moon-sighting-dart homepage: https://github.com/acamarata/moon-sighting-dart
repository: https://github.com/acamarata/moon-sighting-dart repository: https://github.com/acamarata/moon-sighting-dart
issue_tracker: https://github.com/acamarata/moon-sighting-dart/issues issue_tracker: https://github.com/acamarata/moon-sighting-dart/issues
publisher: ariccamarata.com
topics: topics:
- moon - moon
- lunar - lunar