natural-time-js 1.1.1 → 2.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,96 +1,68 @@
1
1
  /**
2
- * @module context
3
- * @description Provides astronomical calculations and events for natural time, including sun and moon positions
2
+ * @module natural-time-js/celestial
3
+ * @description The cosmic heartbeat of natural time - precise astronomical calculations that connect us to the rhythms of sun and moon.
4
+ *
5
+ * While artificial time ignores the sky, natural time is anchored to celestial reality.
6
+ * This module provides the astronomical foundation that makes natural time truly natural:
7
+ * - Exact solar positions throughout the day
8
+ * - Precise lunar phases and cycles
9
+ * - Solstice and equinox calculations
10
+ * - Location-aware sunrise, sunset, moonrise and moonset times
4
11
  */
5
-
6
- import { NaturalDate } from './index.js';
12
+ import { NaturalDate } from '../core/NaturalDate';
7
13
  import { Body, Observer, SearchHourAngle, SearchRiseSet, SearchAltitude, MoonPhase, Equator, Horizon, Seasons } from 'astronomy-engine';
8
- import {
9
- isValidLatitude,
10
- isValidLongitude,
11
- isValidNaturalDate,
12
- throwValidationError
13
- } from './utils/validators.js';
14
-
14
+ import { isValidLatitude, isValidNaturalDate, throwValidationError } from '../utils/validators';
15
15
  /**
16
- * Hemisphere identifiers for geographical calculations
17
- * @constant
18
- * @enum {string}
19
- * @readonly
16
+ * Hemisphere identifiers for geographical calculations.
20
17
  */
21
- export const HEMISPHERES = {
22
- NORTH: 'NORTH',
23
- SOUTH: 'SOUTH'
24
- };
25
-
18
+ export var HEMISPHERES;
19
+ (function (HEMISPHERES) {
20
+ /** Northern hemisphere (latitude >= 0) */
21
+ HEMISPHERES["NORTH"] = "NORTH";
22
+ /** Southern hemisphere (latitude < 0) */
23
+ HEMISPHERES["SOUTH"] = "SOUTH";
24
+ })(HEMISPHERES || (HEMISPHERES = {}));
26
25
  /**
27
- * Day numbers marking the start and end of summer season
28
- * Day 1 represents January 1st
29
- * @constant
30
- * @enum {number}
31
- * @readonly
26
+ * Day numbers marking the start and end of summer season.
32
27
  */
33
28
  export const SEASONS = {
34
- /** Day 91 (typically April 1st) */
29
+ /** Day 91 (typically April 1st) - Start of summer in Northern hemisphere */
35
30
  SUMMER_START_DAY: 91,
36
- /** Day 273 (typically September 30th) */
31
+ /** Day 273 (typically September 30th) - End of summer in Northern hemisphere */
37
32
  SUMMER_END_DAY: 273
38
33
  };
39
-
40
34
  /**
41
- * Solar altitude thresholds in degrees for different daylight conditions
42
- * @constant
43
- * @enum {number}
44
- * @readonly
35
+ * Solar altitude thresholds in degrees for different daylight conditions.
45
36
  */
46
37
  export const ANGLES = {
38
+ /** Altitude below which astronomical night begins (-12°) */
47
39
  NIGHT_ALTITUDE: -12,
40
+ /** Altitude below which golden hour lighting occurs (6°) */
48
41
  GOLDEN_HOUR_ALTITUDE: 6
49
42
  };
50
-
51
- // Move cache to its own module for better separation of concerns
43
+ /**
44
+ * Cache for astronomical calculations to improve performance.
45
+ */
52
46
  const astroCache = new Map();
53
-
54
47
  /**
55
- * Determines the hemisphere based on latitude
56
- * @param {number} latitude - Latitude in degrees (-90 to 90)
57
- * @returns {string} HEMISPHERES.NORTH or HEMISPHERES.SOUTH
58
- * @private
48
+ * Determines the hemisphere based on latitude.
59
49
  */
60
50
  const getHemisphere = (latitude) => latitude >= 0 ? HEMISPHERES.NORTH : HEMISPHERES.SOUTH;
61
-
62
51
  /**
63
- * Determines if the given day is in summer season for the specified latitude
64
- * @param {number} dayOfYear - Day of the year (1-366)
65
- * @param {number} latitude - Latitude in degrees (-90 to 90)
66
- * @returns {boolean} True if the day is in summer season
67
- * @private
52
+ * Determines if the current day is in the summer season based on hemisphere.
68
53
  */
69
54
  const isSummerSeason = (dayOfYear, latitude) => {
70
55
  const hemisphere = getHemisphere(latitude);
71
- return hemisphere === HEMISPHERES.NORTH
56
+ return hemisphere === HEMISPHERES.NORTH
72
57
  ? (dayOfYear >= SEASONS.SUMMER_START_DAY && dayOfYear <= SEASONS.SUMMER_END_DAY)
73
58
  : (dayOfYear <= SEASONS.SUMMER_START_DAY || dayOfYear >= SEASONS.SUMMER_END_DAY);
74
- }
75
-
59
+ };
76
60
  /**
77
- * Creates an astronomical observer at the specified coordinates
78
- * @param {number} latitude - Latitude in degrees (-90 to 90)
79
- * @param {number} longitude - Longitude in degrees (-180 to 180)
80
- * @returns {Observer} Astronomy-engine observer instance
81
- * @private
61
+ * Creates an observer object for astronomical calculations.
82
62
  */
83
63
  const createObserver = (latitude, longitude) => new Observer(latitude, longitude, 0);
84
-
85
64
  /**
86
- * Calculates sun altitude data for a given natural date and latitude
87
- * @param {NaturalDate} naturalDate - Natural date instance
88
- * @param {number} latitude - Latitude in degrees (-90 to 90)
89
- * @returns {{
90
- * altitude: number,
91
- * highestAltitude: number
92
- * }} Sun altitude data
93
- * @throws {Error} If inputs are invalid or calculation fails
65
+ * Calculates the sun's altitude at a specific natural time and location.
94
66
  */
95
67
  export function NaturalSunAltitude(naturalDate, latitude) {
96
68
  // Validate inputs
@@ -100,35 +72,22 @@ export function NaturalSunAltitude(naturalDate, latitude) {
100
72
  if (!isValidLatitude(latitude)) {
101
73
  throwValidationError('latitude', latitude, 'number between -90 and 90');
102
74
  }
103
-
104
75
  try {
105
76
  const observer = createObserver(latitude, naturalDate.longitude);
106
77
  const date = new Date(naturalDate.unixTime);
107
78
  const sun = Equator(Body.Sun, date, observer, true, false);
108
-
109
79
  return {
110
80
  altitude: Math.max(Horizon(date, observer, sun.ra, sun.dec).altitude, 0),
111
81
  highestAltitude: SearchHourAngle(Body.Sun, observer, 0, new Date(naturalDate.nadir)).hor.altitude
112
- }
113
- } catch (error) {
82
+ };
83
+ }
84
+ catch (error) {
114
85
  console.error('Error in NaturalSunAltitude:', error);
115
86
  throw error;
116
87
  }
117
88
  }
118
-
119
89
  /**
120
- * Calculates sun-related events for a given natural date and latitude
121
- * @param {NaturalDate} naturalDate - Natural date instance
122
- * @param {number} latitude - Latitude in degrees (-90 to 90)
123
- * @returns {{
124
- * sunrise: number,
125
- * sunset: number,
126
- * nightStart: number,
127
- * nightEnd: number,
128
- * morningGoldenHour: number,
129
- * eveningGoldenHour: number
130
- * }} Sun events in natural degrees (0-360)
131
- * @throws {Error} If inputs are invalid or calculation fails
90
+ * Calculates sun events for a specific natural date and location.
132
91
  */
133
92
  export function NaturalSunEvents(naturalDate, latitude) {
134
93
  // Validate inputs
@@ -138,29 +97,22 @@ export function NaturalSunEvents(naturalDate, latitude) {
138
97
  if (!isValidLatitude(latitude)) {
139
98
  throwValidationError('latitude', latitude, 'number between -90 and 90');
140
99
  }
141
-
142
100
  const cacheKey = `SUN_${naturalDate.toDateString()}_${latitude}_${naturalDate.longitude}`;
143
-
144
101
  try {
145
- if (astroCache.has(cacheKey)) {
146
- const cachedResult = astroCache.get(cacheKey);
147
- if (cachedResult && typeof cachedResult === 'object') {
148
- return cachedResult;
149
- }
102
+ const cachedResult = astroCache.get(cacheKey);
103
+ if (cachedResult && 'sunrise' in cachedResult) {
104
+ return cachedResult;
150
105
  }
151
-
152
106
  const observer = createObserver(latitude, naturalDate.longitude);
153
107
  const nadir = new Date(naturalDate.nadir);
154
108
  const isSummer = isSummerSeason(naturalDate.dayOfYear, latitude);
155
-
156
109
  // Helper function to handle edge cases
157
110
  const getEventTime = (searchResult, isSummerDefault) => {
158
111
  if (!searchResult) {
159
112
  return isSummer ? (isSummerDefault ? 360 : 0) : 180;
160
113
  }
161
- return naturalDate.getTimeOfEvent(searchResult);
114
+ return naturalDate.getTimeOfEvent(searchResult.date) || 0;
162
115
  };
163
-
164
116
  const events = {
165
117
  sunrise: getEventTime(SearchRiseSet(Body.Sun, observer, +1, nadir, 1), false),
166
118
  sunset: getEventTime(SearchRiseSet(Body.Sun, observer, -1, nadir, 1), true),
@@ -169,24 +121,16 @@ export function NaturalSunEvents(naturalDate, latitude) {
169
121
  morningGoldenHour: getEventTime(SearchAltitude(Body.Sun, observer, +1, nadir, 2, ANGLES.GOLDEN_HOUR_ALTITUDE), false),
170
122
  eveningGoldenHour: getEventTime(SearchAltitude(Body.Sun, observer, -1, nadir, 2, ANGLES.GOLDEN_HOUR_ALTITUDE), true)
171
123
  };
172
-
173
124
  astroCache.set(cacheKey, events);
174
125
  return events;
175
- } catch (error) {
126
+ }
127
+ catch (error) {
176
128
  console.error('Error in NaturalSunEvents:', error);
177
129
  throw error;
178
130
  }
179
131
  }
180
-
181
132
  /**
182
- * Calculates moon position and phase data for a given natural date and latitude
183
- * @param {NaturalDate} naturalDate - Natural date instance
184
- * @param {number} latitude - Latitude in degrees (-90 to 90)
185
- * @returns {{
186
- * phase: number,
187
- * altitude: number,
188
- * highestAltitude: number
189
- * }} Moon position and phase data
133
+ * Calculates the moon's position and phase.
190
134
  */
191
135
  export function NaturalMoonPosition(naturalDate, latitude) {
192
136
  // Validate inputs
@@ -196,107 +140,85 @@ export function NaturalMoonPosition(naturalDate, latitude) {
196
140
  if (!isValidLatitude(latitude)) {
197
141
  throwValidationError('latitude', latitude, 'number between -90 and 90');
198
142
  }
199
-
200
143
  try {
201
144
  const observer = createObserver(latitude, naturalDate.longitude);
202
145
  const date = new Date(naturalDate.unixTime);
203
146
  const moon = Equator(Body.Moon, date, observer, true, false);
204
-
205
147
  return {
206
- phase: MoonPhase(date),
207
148
  altitude: Math.max(Horizon(date, observer, moon.ra, moon.dec).altitude, 0),
208
- highestAltitude: SearchHourAngle(Body.Moon, observer, 0, new Date(naturalDate.nadir)).hor.altitude
209
- }
210
- } catch (error) {
149
+ phase: MoonPhase(date),
150
+ illumination: Math.cos(MoonPhase(date) * Math.PI / 180)
151
+ };
152
+ }
153
+ catch (error) {
211
154
  console.error('Error in NaturalMoonPosition:', error);
212
- return {
213
- phase: 0,
214
- altitude: 0,
215
- highestAltitude: 0
216
- }
155
+ throw error;
217
156
  }
218
157
  }
219
-
220
158
  /**
221
- * Calculates moon rise and set events for a given natural date and latitude
222
- * @param {NaturalDate} naturalDate - Natural date instance
223
- * @param {number} latitude - Latitude in degrees (-90 to 90)
224
- * @returns {{
225
- * moonrise: number|null,
226
- * moonset: number|null
227
- * }} Moon events in natural degrees (0-360)
159
+ * Calculates moon events for a specific natural date and location.
228
160
  */
229
161
  export function NaturalMoonEvents(naturalDate, latitude) {
162
+ // Validate inputs
163
+ if (!isValidNaturalDate(naturalDate)) {
164
+ throwValidationError('naturalDate', naturalDate, 'NaturalDate instance');
165
+ }
166
+ if (!isValidLatitude(latitude)) {
167
+ throwValidationError('latitude', latitude, 'number between -90 and 90');
168
+ }
230
169
  const cacheKey = `MOON_${naturalDate.toDateString()}_${latitude}_${naturalDate.longitude}`;
231
-
232
170
  try {
233
- if (astroCache.has(cacheKey)) {
234
- return astroCache.get(cacheKey);
171
+ const cachedResult = astroCache.get(cacheKey);
172
+ if (cachedResult && 'moonrise' in cachedResult) {
173
+ return cachedResult;
235
174
  }
236
-
237
175
  const observer = createObserver(latitude, naturalDate.longitude);
238
176
  const nadir = new Date(naturalDate.nadir);
239
-
240
- const moonrise = SearchRiseSet(Body.Moon, observer, +1, nadir, 1);
241
- const moonset = SearchRiseSet(Body.Moon, observer, -1, nadir, 1);
242
-
177
+ // Helper function to handle edge cases
178
+ const getEventTime = (searchResult) => {
179
+ if (!searchResult)
180
+ return 0;
181
+ return naturalDate.getTimeOfEvent(searchResult.date) || 0;
182
+ };
243
183
  const events = {
244
- moonrise: naturalDate.getTimeOfEvent(moonrise),
245
- moonset: naturalDate.getTimeOfEvent(moonset)
184
+ moonrise: getEventTime(SearchRiseSet(Body.Moon, observer, +1, nadir, 1)),
185
+ moonset: getEventTime(SearchRiseSet(Body.Moon, observer, -1, nadir, 1)),
186
+ highestAltitude: SearchHourAngle(Body.Moon, observer, 0, nadir).hor.altitude
246
187
  };
247
-
248
188
  astroCache.set(cacheKey, events);
249
189
  return events;
250
- } catch (error) {
251
- console.error('Error calculating moon events:', error);
252
- return {
253
- moonrise: null,
254
- moonset: null
255
- }
190
+ }
191
+ catch (error) {
192
+ console.error('Error in NaturalMoonEvents:', error);
193
+ throw error;
256
194
  }
257
195
  }
258
-
259
196
  /**
260
197
  * Calculates the range of sun positions between winter and summer solstices (average mustaches angle)
261
- * @param {NaturalDate} naturalDate - Natural date instance
262
- * @param {number} latitude - Latitude in degrees (-90 to 90)
263
- * @returns {{
264
- * winterSunrise: number,
265
- * winterSunset: number,
266
- * summerSunrise: number,
267
- * summerSunset: number,
268
- * averageMustacheAngle: number
269
- * }} Solstice sun positions and mustache angle
270
198
  */
271
199
  export function MustachesRange(naturalDate, latitude) {
272
- const cacheKey = `MUSTACHES_${naturalDate.year}_${latitude}`;
273
-
200
+ // Validate inputs
201
+ if (!isValidNaturalDate(naturalDate)) {
202
+ throwValidationError('naturalDate', naturalDate, 'NaturalDate instance');
203
+ }
204
+ if (!isValidLatitude(latitude)) {
205
+ throwValidationError('latitude', latitude, 'number between -90 and 90');
206
+ }
207
+ const currentYear = new Date(naturalDate.unixTime).getFullYear();
208
+ const cacheKey = `MUSTACHES_${currentYear}_${latitude}`;
274
209
  try {
275
- if (astroCache.has(cacheKey)) {
276
- return astroCache.get(cacheKey);
210
+ const cachedResult = astroCache.get(cacheKey);
211
+ if (cachedResult && 'winterSunrise' in cachedResult) {
212
+ return cachedResult;
277
213
  }
278
-
279
- const currentYear = new Date(naturalDate.unixTime).getFullYear();
280
214
  const currentSeasons = Seasons(currentYear);
281
-
282
- const winterSolsticeSunEvents = NaturalSunEvents(
283
- new NaturalDate(currentSeasons.dec_solstice.date, 0),
284
- latitude
285
- );
286
- const summerSolsticeSunEvents = NaturalSunEvents(
287
- new NaturalDate(currentSeasons.jun_solstice.date, 0),
288
- latitude
289
- );
290
-
291
- const averageMustacheAngle = Math.min(Math.max(
292
- latitude >= 0
293
- ? (winterSolsticeSunEvents.sunrise - summerSolsticeSunEvents.sunrise +
294
- summerSolsticeSunEvents.sunset - winterSolsticeSunEvents.sunset) / 4
295
- : (summerSolsticeSunEvents.sunrise - winterSolsticeSunEvents.sunrise +
296
- winterSolsticeSunEvents.sunset - summerSolsticeSunEvents.sunset) / 4,
297
- 0
298
- ), 90);
299
-
215
+ const winterSolsticeSunEvents = NaturalSunEvents(new NaturalDate(currentSeasons.dec_solstice.date, 0), latitude);
216
+ const summerSolsticeSunEvents = NaturalSunEvents(new NaturalDate(currentSeasons.jun_solstice.date, 0), latitude);
217
+ const averageMustacheAngle = Math.min(Math.max(latitude >= 0
218
+ ? (winterSolsticeSunEvents.sunrise - summerSolsticeSunEvents.sunrise +
219
+ summerSolsticeSunEvents.sunset - winterSolsticeSunEvents.sunset) / 4
220
+ : (summerSolsticeSunEvents.sunrise - winterSolsticeSunEvents.sunrise +
221
+ winterSolsticeSunEvents.sunset - summerSolsticeSunEvents.sunset) / 4, 0), 90);
300
222
  const result = {
301
223
  winterSunrise: winterSolsticeSunEvents.sunrise,
302
224
  winterSunset: winterSolsticeSunEvents.sunset,
@@ -304,10 +226,10 @@ export function MustachesRange(naturalDate, latitude) {
304
226
  summerSunset: summerSolsticeSunEvents.sunset,
305
227
  averageMustacheAngle
306
228
  };
307
-
308
229
  astroCache.set(cacheKey, result);
309
230
  return result;
310
- } catch (error) {
231
+ }
232
+ catch (error) {
311
233
  console.error('Error calculating mustaches range:', error);
312
234
  return {
313
235
  winterSunrise: 0,
@@ -315,6 +237,7 @@ export function MustachesRange(naturalDate, latitude) {
315
237
  summerSunrise: 0,
316
238
  summerSunset: 0,
317
239
  averageMustacheAngle: 0
318
- }
240
+ };
319
241
  }
320
- }
242
+ }
243
+ //# sourceMappingURL=celestial.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"celestial.js","sourceRoot":"","sources":["../../src/astronomy/celestial.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,164 @@
1
+ /**
2
+ * @module natural-time-js/core
3
+ * @description This module provides the core NaturalDate class that bridges between artificial Gregorian time and Natural Time.
4
+ */
5
+ /**
6
+ * Year context interface for natural date calculations
7
+ */
8
+ interface YearContext {
9
+ start: number;
10
+ duration: number;
11
+ }
12
+ /**
13
+ * Cache for year context calculations to improve performance
14
+ * @private
15
+ */
16
+ declare const yearContextCache: Map<string, YearContext>;
17
+ /**
18
+ * Natural date class for converting artificial (Gregorian) dates to natural time.
19
+ *
20
+ * The NaturalDate class provides a complete implementation of the natural time system,
21
+ * which is based on natural cycles:
22
+ * - Years begin at the winter solstice
23
+ * - Each year has 13 moons (months) of 28 days each, plus 1-2 "rainbow days"
24
+ * - Weeks are 7 days
25
+ * - Time is measured in 360 degrees for a full day cycle
26
+ *
27
+ * This class handles the conversion between Gregorian calendar dates and natural time,
28
+ * accounting for longitude adjustments to provide location-specific natural time.
29
+ */
30
+ export declare class NaturalDate {
31
+ /**
32
+ * Number of milliseconds in a day
33
+ */
34
+ static readonly MILLISECONDS_PER_DAY: number;
35
+ /**
36
+ * End date of the artificial time era (December 21, 2012 12:00 UTC)
37
+ * This is the reference point for natural time calculations
38
+ */
39
+ static readonly END_OF_ARTIFICIAL_TIME: number;
40
+ /** Artificial gregorian date (UNIX timestamp) */
41
+ readonly unixTime: number;
42
+ /** Longitude in degrees (-180° to +180°) */
43
+ readonly longitude: number;
44
+ /** Current natural year (year 001: winter solstice 2012 > winter solstice 2013) */
45
+ readonly year: number;
46
+ /** Current moon (month) in the natural year (1-14) */
47
+ readonly moon: number;
48
+ /** Current week of the natural year (1-53) */
49
+ readonly week: number;
50
+ /** Current week within the current moon (1-4) */
51
+ readonly weekOfMoon: number;
52
+ /** Number of days passed since END_OF_ARTIFICIAL_TIME */
53
+ readonly day: number;
54
+ /** Current day of the natural year (1-366) */
55
+ readonly dayOfYear: number;
56
+ /** Current day of the moon (1-28) */
57
+ readonly dayOfMoon: number;
58
+ /** Current day of the week (1-7) */
59
+ readonly dayOfWeek: number;
60
+ /** True if current day is a rainbow day (day beyond the 13 moons) */
61
+ readonly isRainbowDay: boolean;
62
+ /** Current time in natural degrees (0-360°) */
63
+ readonly time: number;
64
+ /** Beginning of the natural year at the current longitude (UNIX timestamp) */
65
+ readonly yearStart: number;
66
+ /** Number of days in the current natural year (365 or 366) */
67
+ readonly yearDuration: number;
68
+ /** Beginning of the current natural day at the current longitude (UNIX timestamp) */
69
+ readonly nadir: number;
70
+ /**
71
+ * Creates a new natural date instance.
72
+ *
73
+ * Converts a Gregorian date to natural time based on the specified longitude.
74
+ * The longitude is used to adjust the natural time for the local position on Earth.
75
+ *
76
+ * @param date - JavaScript Date object, Unix timestamp, or date string
77
+ * @param longitude - Longitude in degrees (-180 to 180)
78
+ * @throws {Error} If inputs are invalid
79
+ *
80
+ * @example
81
+ * // Create a natural date for the current time in Paris (longitude 2.3522)
82
+ * const parisNaturalDate = new NaturalDate(new Date(), 2.3522);
83
+ *
84
+ * @example
85
+ * // Create a natural date for a specific time in Tokyo (longitude 139.6503)
86
+ * const tokyoNaturalDate = new NaturalDate('2023-06-21T12:00:00', 139.6503);
87
+ */
88
+ constructor(date: Date | number | string | null | undefined, longitude?: number);
89
+ /**
90
+ * Gets the time of an astronomical event in natural degrees.
91
+ *
92
+ * Converts an event timestamp to natural degrees (0-360°) within the current natural day.
93
+ * Returns false if the event occurs outside the current natural day.
94
+ *
95
+ * This is useful for calculating the position of celestial events like sunrise, sunset,
96
+ * moonrise, or moonset within the natural time system.
97
+ *
98
+ * @param event - Event timestamp (Date object, Unix timestamp, or date string)
99
+ * @returns Event time in natural degrees (0-360°) or false if out of range
100
+ *
101
+ * @example
102
+ * // Calculate sunrise time in natural degrees
103
+ * const naturalDate = new NaturalDate(new Date(), 0);
104
+ * const sunrise = '2023-01-01T06:00:00'; // Example sunrise at 6:00 AM
105
+ * const sunriseInDegrees = naturalDate.getTimeOfEvent(sunrise);
106
+ * console.log(`Sunrise occurs at ${sunriseInDegrees}°`);
107
+ */
108
+ getTimeOfEvent(event: Date | number | string): number | false;
109
+ /**
110
+ * Exports current date as a full ISO formatted string.
111
+ *
112
+ * The format is: "YYY)MM)DD TTT°DD NT±LLL.L"
113
+ * - YYY: Natural year (padded to 3 digits)
114
+ * - MM: Moon number (padded to 2 digits)
115
+ * - DD: Day of moon (padded to 2 digits)
116
+ * - TTT: Time in degrees (padded to 3 digits)
117
+ * - DD: Decimal degrees (2 digits)
118
+ * - ±LLL.L: Longitude with sign and 1 decimal
119
+ *
120
+ * @returns {string} Formatted natural date string
121
+ */
122
+ toString(): string;
123
+ /**
124
+ * Exports the date part of the natural date.
125
+ *
126
+ * @param separator - Separator character between components (default: ')')
127
+ * @returns Formatted date string
128
+ */
129
+ toDateString(separator?: string): string;
130
+ /**
131
+ * Exports the time part of the natural date.
132
+ *
133
+ * @param decimals - Number of decimal places for time (default: 2)
134
+ * @param rounding - Rounding increment for time (default: 1)
135
+ * @returns Formatted time string
136
+ */
137
+ toTimeString(decimals?: number, rounding?: number): string;
138
+ /**
139
+ * Exports the longitude part of the natural date.
140
+ *
141
+ * @param decimals - Number of decimal places for longitude (default: 1)
142
+ * @returns Formatted longitude string
143
+ */
144
+ toLongitudeString(decimals?: number): string;
145
+ /**
146
+ * Exports the year part of the natural date.
147
+ *
148
+ * @returns Formatted year string
149
+ */
150
+ toYearString(): string;
151
+ /**
152
+ * Exports the moon part of the natural date.
153
+ *
154
+ * @returns Formatted moon string
155
+ */
156
+ toMoonString(): string;
157
+ /**
158
+ * Exports the day of moon part of the natural date.
159
+ *
160
+ * @returns Formatted day of moon string
161
+ */
162
+ toDayOfMoonString(): string;
163
+ }
164
+ export { yearContextCache };