Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ marstime.marsTime(new Date(), { longitude: 137.44 });
// { msd, mtc, ls, marsYear, eot, lmst, ltst, subsolarLongitude, solarDeclination, heliocentricDistance, meanAnomaly, sol }

marstime.interimmTime(new Date(), { zone: 5 });
// { year: 31, month: 1, day: 3, weekday: 'Tuesday', monthName: { zh: '春分', en: 'Chunfen' }, clock: '06:19:12', hours, ... }
// { iso: '31-01-03', year: 31, month: 1, day: 3, weekday: 'Tuesday', monthName: { zh: '春分', en: 'Chunfen' }, clock: '06:19:12', hours, ... }
```

Runs in browsers, Node 18+, Deno and Bun. Every function is pure and takes a `Date` or milliseconds since 1970.
Expand All @@ -31,6 +31,7 @@ Runs in browsers, Node 18+, Deno and Bun. Every function is pure and takes a `Da
| `missionTime(date, 'curiosity')` | `{ sol, lmst, ltst }` for a lander or rover in `MISSIONS`, or for `{ landed, longitude }`. |
| `interimmTime(date, { zone })` | InterImm calendar date and clock in one of the 25 zones. |
| `dateFromInterimm({ year, month, day, hours, zone })` | The Earth instant of an InterImm date and time. |
| `formatInterimmDate(d)` / `parseInterimmDate('31-01-03')` | InterImm dates as `31-01-03`: the year as is, two-digit month and day. |
| `interimmZone(longitude)` / `interimmZoneOffset(zone)` | Zone for a longitude, and its offset from zone 0 in Earth hours. |
| `taiMinusUtc(date)`, `julianDates(date)` | Earth time scales used underneath. |
| `formatHms(hours)`, `formatInterimmClock(hours)` | `"hh:mm:ss"` and the InterImm `"hh:mm:ss"` / `"+mm:ss"` reading. |
Expand Down
2 changes: 1 addition & 1 deletion api/v1/daily/2000.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion api/v1/daily/2001.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion api/v1/daily/2002.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion api/v1/daily/2003.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion api/v1/daily/2004.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion api/v1/daily/2005.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion api/v1/daily/2006.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion api/v1/daily/2007.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion api/v1/daily/2008.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion api/v1/daily/2009.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion api/v1/daily/2010.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion api/v1/daily/2011.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion api/v1/daily/2012.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion api/v1/daily/2013.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion api/v1/daily/2014.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion api/v1/daily/2015.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion api/v1/daily/2016.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion api/v1/daily/2017.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion api/v1/daily/2018.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion api/v1/daily/2019.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion api/v1/daily/2020.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion api/v1/daily/2021.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion api/v1/daily/2022.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion api/v1/daily/2023.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion api/v1/daily/2024.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion api/v1/daily/2025.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion api/v1/daily/2026.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion api/v1/daily/2027.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion api/v1/daily/2028.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion api/v1/daily/2029.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion api/v1/daily/2030.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion api/v1/daily/2031.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion api/v1/daily/2032.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion api/v1/daily/2033.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion api/v1/daily/2034.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion api/v1/daily/2035.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion api/v1/daily/2036.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion api/v1/daily/2037.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion api/v1/daily/2038.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion api/v1/daily/2039.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion api/v1/daily/2040.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion api/v1/daily/2041.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion api/v1/daily/2042.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion api/v1/daily/2043.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion api/v1/daily/2044.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion api/v1/daily/2045.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion api/v1/daily/2046.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion api/v1/daily/2047.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion api/v1/daily/2048.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion api/v1/daily/2049.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion api/v1/daily/2050.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion api/v1/openapi.json
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"openapi":"3.1.0","info":{"title":"InterImm Mars time API","version":"1.0.0","description":"Static, precomputed Mars time tables (GET only, no key, CORS open). For an arbitrary instant use the JavaScript library (https://cdn.jsdelivr.net/gh/InterImm/mars-clock@gh-pages/lib/marstime.js) or the MCP server (npx -y github:InterImm/mars-clock#gh-pages). Guide for language models: https://interimm.org/mars-clock/llms.txt","license":{"name":"MIT","identifier":"MIT"}},"servers":[{"url":"https://interimm.org/mars-clock/api/v1"}],"paths":{"/daily/{year}.json":{"get":{"operationId":"getDailyTable","summary":"Mars time at 00:00 UTC on every day of an Earth year (2000-2050)","parameters":[{"name":"year","in":"path","required":true,"schema":{"type":"integer","minimum":2000,"maximum":2050}}],"responses":{"200":{"description":"Rows are arrays in the order of `columns`.","content":{"application/json":{"schema":{"type":"object","properties":{"about":{"type":"string"},"columns":{"type":"array","items":{"type":"string"},"example":["utc","msd","mtc","ls","marsYear","interimmDate","interimmClock","curiositySol","perseveranceSol"]},"rows":{"type":"array","items":{"type":"array","prefixItems":[{"type":"string","description":"UTC date"},{"type":"number","description":"Mars Sol Date"},{"type":"string","description":"Coordinated Mars Time hh:mm:ss"},{"type":"number","description":"Solar longitude Ls, degrees"},{"type":"integer","description":"Mars Year (Clancy)"},{"type":"string","description":"InterImm date year-month-day, zone 0"},{"type":"string","description":"InterImm clock, zone 0"},{"type":["integer","null"],"description":"Curiosity sol"},{"type":["integer","null"],"description":"Perseverance sol"}]}}}}}}}}}},"/mars-years.json":{"get":{"operationId":"getMarsYears","summary":"Start of Mars Years 1-80 and their Ls 90/180/270 dates","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"about":{"type":"string"},"years":{"type":"array","items":{"type":"object","properties":{"marsYear":{"type":"integer"},"start":{"type":"string"},"ls90":{"type":"string"},"ls180":{"type":"string"},"ls270":{"type":"string"}}}}}}}}}}}},"/interimm-years.json":{"get":{"operationId":"getInterimmYears","summary":"Start and length of InterImm calendar years 1-80, and month names","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"about":{"type":"string"},"months":{"type":"array","items":{"type":"object","properties":{"month":{"type":"integer"},"zh":{"type":"string"},"en":{"type":"string"}}}},"years":{"type":"array","items":{"type":"object","properties":{"year":{"type":"integer"},"start":{"type":"string"},"sols":{"type":"integer"}}}}}}}}}}}},"/missions.json":{"get":{"operationId":"getMissions","summary":"Landers and rovers: landing time (UTC) and longitude (degrees east)","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}}}}},"/leap-seconds.json":{"get":{"operationId":"getLeapSeconds","summary":"TAI-UTC table used for the conversion","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}}}}}}}
{"openapi":"3.1.0","info":{"title":"InterImm Mars time API","version":"1.0.0","description":"Static, precomputed Mars time tables (GET only, no key, CORS open). For an arbitrary instant use the JavaScript library (https://cdn.jsdelivr.net/gh/InterImm/mars-clock@gh-pages/lib/marstime.js) or the MCP server (npx -y github:InterImm/mars-clock#gh-pages). Guide for language models: https://interimm.org/mars-clock/llms.txt","license":{"name":"MIT","identifier":"MIT"}},"servers":[{"url":"https://interimm.org/mars-clock/api/v1"}],"paths":{"/daily/{year}.json":{"get":{"operationId":"getDailyTable","summary":"Mars time at 00:00 UTC on every day of an Earth year (2000-2050)","parameters":[{"name":"year","in":"path","required":true,"schema":{"type":"integer","minimum":2000,"maximum":2050}}],"responses":{"200":{"description":"Rows are arrays in the order of `columns`.","content":{"application/json":{"schema":{"type":"object","properties":{"about":{"type":"string"},"columns":{"type":"array","items":{"type":"string"},"example":["utc","msd","mtc","ls","marsYear","interimmDate","interimmClock","curiositySol","perseveranceSol"]},"rows":{"type":"array","items":{"type":"array","prefixItems":[{"type":"string","description":"UTC date"},{"type":"number","description":"Mars Sol Date"},{"type":"string","description":"Coordinated Mars Time hh:mm:ss"},{"type":"number","description":"Solar longitude Ls, degrees"},{"type":"integer","description":"Mars Year (Clancy)"},{"type":"string","description":"InterImm date year-MM-DD, zone 0"},{"type":"string","description":"InterImm clock, zone 0"},{"type":["integer","null"],"description":"Curiosity sol"},{"type":["integer","null"],"description":"Perseverance sol"}]}}}}}}}}}},"/mars-years.json":{"get":{"operationId":"getMarsYears","summary":"Start of Mars Years 1-80 and their Ls 90/180/270 dates","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"about":{"type":"string"},"years":{"type":"array","items":{"type":"object","properties":{"marsYear":{"type":"integer"},"start":{"type":"string"},"ls90":{"type":"string"},"ls180":{"type":"string"},"ls270":{"type":"string"}}}}}}}}}}}},"/interimm-years.json":{"get":{"operationId":"getInterimmYears","summary":"Start and length of InterImm calendar years 1-80, and month names","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"about":{"type":"string"},"months":{"type":"array","items":{"type":"object","properties":{"month":{"type":"integer"},"zh":{"type":"string"},"en":{"type":"string"}}}},"years":{"type":"array","items":{"type":"object","properties":{"year":{"type":"integer"},"start":{"type":"string"},"sols":{"type":"integer"}}}}}}}}}}}},"/missions.json":{"get":{"operationId":"getMissions","summary":"Landers and rovers: landing time (UTC) and longitude (degrees east)","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}}}}},"/leap-seconds.json":{"get":{"operationId":"getLeapSeconds","summary":"TAI-UTC table used for the conversion","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}}}}}}}
8 changes: 3 additions & 5 deletions app/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,7 @@ const T = {
season: (s) => `Northern ${s.north}, southern ${s.south}`,
weekdays: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'],
weekShort: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
date: (i) => `Year ${i.year}, month ${i.month} (${i.monthName.en}), day ${i.day}`,
dateShort: (i) => `${i.year}-${i.month}-${i.day}`,
date: (i) => `${i.iso} · ${i.monthName.en}`,
zone: (z) => `Zone ${z}`,
sol: (n) => `Sol ${n.toLocaleString('en')}`,
my: (n) => `Mars Year ${n}`,
Expand All @@ -24,8 +23,7 @@ const T = {
season: (s) => `北半球${s.north}季,南半球${s.south}季`,
weekdays: ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六'],
weekShort: ['日', '一', '二', '三', '四', '五', '六'],
date: (i) => `${i.year}年${i.month}月(${i.monthName.zh})${i.day}日`,
dateShort: (i) => `${i.year}年${i.month}月${i.day}日`,
date: (i) => `${i.iso} · ${i.monthName.zh}`,
zone: (z) => `${z} 区`,
sol: (n) => `火星日 ${n}`,
my: (n) => `火星年 MY ${n}`,
Expand Down Expand Up @@ -149,7 +147,7 @@ function tick(force = false) {

function renderMonth(today) {
const { year, month } = today;
set('cal-title', lang === 'zh' ? `${year}年${month}月 · ${today.monthName.zh}` : `Year ${year}, month ${month} · ${today.monthName.en}`);
set('cal-title', `${today.iso.slice(0, -3)} · ${lang === 'zh' ? today.monthName.zh : today.monthName.en}`);
set('cal-leap', T.leap(today.leapYear));
const days = mt.interimmMonthLength(year, month);
const grid = $('cal-grid');
Expand Down
4 changes: 2 additions & 2 deletions lib/mars-clock-card.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ const TEXT = {
en: {
zone: (z) => `InterImm zone ${z}`,
local: (p) => `Local mean solar time${p ? ` · ${p}` : ''}`,
date: (i) => `Year ${i.year} · ${i.monthName.en} (month ${i.month}) · day ${i.day}`,
date: (i) => `${i.iso} · ${i.monthName.en} · ${i.weekday}`,
mtc: 'Mars time (MTC)', ls: 'Season', my: 'Mars Year', sol: 'Sol',
season: (s) => `${s.north} (N)`,
seasons: { spring: 'spring', summer: 'summer', autumn: 'autumn', winter: 'winter' },
Expand All @@ -32,7 +32,7 @@ const TEXT = {
zh: {
zone: (z) => `星际移民中心时间 · ${z} 区`,
local: (p) => `地方平太阳时${p ? ` · ${p}` : ''}`,
date: (i) => `${i.year}年${i.month}月(${i.monthName.zh})${i.day}日`,
date: (i) => `${i.iso} · ${i.monthName.zh} · ${['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六'][(i.day - 1) % 7]}`,
mtc: '协调火星时', ls: '季节', my: '火星年', sol: '火星日',
season: (s) => `北半球${s.north}季`,
seasons: { spring: '春', summer: '夏', autumn: '秋', winter: '冬' },
Expand Down
4 changes: 2 additions & 2 deletions lib/mars-clock-element.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
// <mars-clock show="lmst" longitude="137.44"></mars-clock> local mean solar time at Gale crater
// <mars-clock show="sol" mission="perseverance"></mars-clock> Perseverance's sol number
// <mars-clock show="ls"></mars-clock> solar longitude (season), e.g. 1.5°
// <mars-clock show="date"></mars-clock> InterImm date, e.g. 31-1-3
// <mars-clock show="date"></mars-clock> InterImm date, e.g. 31-01-03
//
// It renders plain text with no styles of its own, so it takes the font and colour of where it sits.
import { marsTime, interimmTime, missionTime, formatHms } from './marstime.js';
Expand All @@ -30,7 +30,7 @@ class MarsClock extends HTMLElement {
let text;
if (show === 'interimm' || show === 'date') {
const t = interimmTime(now, { zone: Number(this.getAttribute('zone') || 0) });
text = show === 'date' ? `${t.year}-${t.month}-${t.day}` : t.clock;
text = show === 'date' ? t.iso : t.clock;
} else if (show === 'sol') {
text = String(missionTime(now, this.getAttribute('mission') || 'curiosity').sol);
} else {
Expand Down
16 changes: 14 additions & 2 deletions lib/marstime.js
Original file line number Diff line number Diff line change
Expand Up @@ -258,9 +258,21 @@ export function formatInterimmClock(hours) {
return `+${String(Math.floor(extra / 60)).padStart(2, '0')}:${String(extra % 60).padStart(2, '0')}`;
}

/** InterImm date as "31-01-03": the year as is, two-digit month and day ("-2-12-07" before Year 0). */
export function formatInterimmDate({ year, month, day }) {
return `${year}-${String(month).padStart(2, '0')}-${String(day).padStart(2, '0')}`;
}

/** Read "31-01-03" (or "31-1-3", "0031-01-03") back into { year, month, day }. */
export function parseInterimmDate(text) {
const m = /^\s*(-?\d{1,6})-(\d{1,2})-(\d{1,2})\s*$/.exec(String(text));
if (!m) throw new RangeError(`marstime: expected an InterImm date like 31-01-03, got "${text}"`);
return { year: Number(m[1]), month: Number(m[2]), day: Number(m[3]) };
}

/**
* InterImm date and clock time at an instant, in an InterImm timezone (0-24).
* @returns {{year:number, month:number, day:number, dayOfYear:number, weekday:string, monthName:{zh:string,en:string},
* @returns {{iso:string, year:number, month:number, day:number, dayOfYear:number, weekday:string, monthName:{zh:string,en:string},
* hours:number, clock:string, zone:number, solCount:number, leapYear:boolean}}
* hours: Earth hours since the start of the sol (0 to 24.6598); clock: formatted reading;
* solCount: sols since the start of Year 1 in that zone, as a decimal.
Expand All @@ -272,7 +284,7 @@ export function interimmTime(date, { zone = 0 } = {}) {
const hours = mod(solCount, 1) * HOURS_PER_SOL;
const { zh, en } = INTERIMM_MONTHS[cal.month - 1];
return {
...cal, weekday: WEEKDAYS[(cal.day - 1) % 7], monthName: { zh, en }, hours, clock: formatInterimmClock(hours),
iso: formatInterimmDate(cal), ...cal, weekday: WEEKDAYS[(cal.day - 1) % 7], monthName: { zh, en }, hours, clock: formatInterimmClock(hours),
zone, solCount, leapYear: isInterimmLeapYear(cal.year),
};
}
Expand Down
12 changes: 12 additions & 0 deletions lib/marstime.test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,18 @@ test('InterImm date round-trips', () => {
}
});

test('InterImm date format', () => {
assert.equal(mt.formatInterimmDate({ year: 31, month: 1, day: 3 }), '31-01-03');
assert.equal(mt.formatInterimmDate({ year: 1234, month: 24, day: 28 }), '1234-24-28');
assert.equal(mt.formatInterimmDate({ year: -2, month: 12, day: 7 }), '-2-12-07');
assert.deepEqual(mt.parseInterimmDate('31-01-03'), { year: 31, month: 1, day: 3 });
assert.deepEqual(mt.parseInterimmDate('0031-01-03'), { year: 31, month: 1, day: 3 });
assert.deepEqual(mt.parseInterimmDate('31-1-3'), { year: 31, month: 1, day: 3 });
assert.deepEqual(mt.parseInterimmDate('-0002-12-07'), { year: -2, month: 12, day: 7 });
assert.throws(() => mt.parseInterimmDate('31/1/3'), RangeError);
assert.equal(mt.interimmTime(Date.UTC(2026, 9, 3, 10), { zone: 5 }).iso, '31-01-03');
});

test('InterImm clock format', () => {
assert.equal(mt.formatInterimmClock(0), '00:00:00');
assert.equal(mt.formatInterimmClock(23.999), '23:59:56');
Expand Down
17 changes: 15 additions & 2 deletions llms-full.txt
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ Recent starts: MY 36 2021-02-07, MY 37 2022-12-26, MY 38 2024-11-12, MY 39 2026-
- Year Y has 668 sols, or 669 when Y + 1 is "leap": n is leap if n is odd or divisible by 10, except multiples of 100 are not, multiples of 1000 are, multiples of 3000 are not.
- 24 months: months 6, 12, 18, 24 have 27 sols, others 28; in a 669-sol year month 24 has 28. Every month starts on a Sunday (7-sol weeks restart each month).
- Month names (solar terms): 1 春分 Chunfen, 2 清明 Qingming, 3 谷雨 Guyu, 4 立夏 Lixia, 5 小满 Xiaoman, 6 芒种 Mangzhong, 7 夏至 Xiazhi, 8 小暑 Xiaoshu, 9 大暑 Dashu, 10 立秋 Liqiu, 11 处暑 Chushu, 12 白露 Bailu, 13 秋分 Qiufen, 14 寒露 Hanlu, 15 霜降 Shuangjiang, 16 立冬 Lidong, 17 小雪 Xiaoxue, 18 大雪 Daxue, 19 冬至 Dongzhi, 20 小寒 Xiaohan, 21 大寒 Dahan, 22 立春 Lichun, 23 雨水 Yushui, 24 惊蛰 Jingzhe.
- Dates are written Y-MM-DD, with two-digit month and day and the year unpadded: 31-01-03 is Year 31, month 1, day 3.
- Clock: Earth-length hours. hours = frac(S + offset/24.6598) × 24.6598, shown as hh:mm:ss below 24 h and +mm:ss after (up to +39:35).
- Timezones 0-24, each 14.5987° wide eastward from Airy-0; zone k is k hours ahead of zone 0, except zone 24 which is 39 min 35 s behind (24 h ahead modulo the 24.6598 h sol).

Expand Down Expand Up @@ -308,9 +309,21 @@ export function formatInterimmClock(hours) {
return `+${String(Math.floor(extra / 60)).padStart(2, '0')}:${String(extra % 60).padStart(2, '0')}`;
}

/** InterImm date as "31-01-03": the year as is, two-digit month and day ("-2-12-07" before Year 0). */
export function formatInterimmDate({ year, month, day }) {
return `${year}-${String(month).padStart(2, '0')}-${String(day).padStart(2, '0')}`;
}

/** Read "31-01-03" (or "31-1-3", "0031-01-03") back into { year, month, day }. */
export function parseInterimmDate(text) {
const m = /^\s*(-?\d{1,6})-(\d{1,2})-(\d{1,2})\s*$/.exec(String(text));
if (!m) throw new RangeError(`marstime: expected an InterImm date like 31-01-03, got "${text}"`);
return { year: Number(m[1]), month: Number(m[2]), day: Number(m[3]) };
}

/**
* InterImm date and clock time at an instant, in an InterImm timezone (0-24).
* @returns {{year:number, month:number, day:number, dayOfYear:number, weekday:string, monthName:{zh:string,en:string},
* @returns {{iso:string, year:number, month:number, day:number, dayOfYear:number, weekday:string, monthName:{zh:string,en:string},
* hours:number, clock:string, zone:number, solCount:number, leapYear:boolean}}
* hours: Earth hours since the start of the sol (0 to 24.6598); clock: formatted reading;
* solCount: sols since the start of Year 1 in that zone, as a decimal.
Expand All @@ -322,7 +335,7 @@ export function interimmTime(date, { zone = 0 } = {}) {
const hours = mod(solCount, 1) * HOURS_PER_SOL;
const { zh, en } = INTERIMM_MONTHS[cal.month - 1];
return {
...cal, weekday: WEEKDAYS[(cal.day - 1) % 7], monthName: { zh, en }, hours, clock: formatInterimmClock(hours),
iso: formatInterimmDate(cal), ...cal, weekday: WEEKDAYS[(cal.day - 1) % 7], monthName: { zh, en }, hours, clock: formatInterimmClock(hours),
zone, solCount, leapYear: isInterimmLeapYear(cal.year),
};
}
Expand Down
2 changes: 1 addition & 1 deletion llms.txt
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ How to get Mars time, best option first:
3. If you can run JavaScript: `import { marsTime, interimmTime } from 'https://cdn.jsdelivr.net/gh/InterImm/mars-clock@gh-pages/lib/marstime.js'`.
4. If you can only fetch URLs: read the precomputed daily table for the year and interpolate (MSD grows by 0.973244 sol per Earth day; MTC by 24 Mars hours per sol). Or compute it yourself from the formulas in llms-full.txt.

Conventions: longitudes are degrees EAST of Airy-0 (west longitudes are negative or 360 minus). MTC, LMST and LTST are in Mars hours (1/24 sol). The InterImm clock uses Earth-length hours, so a sol reads 00:00:00 to 23:59:59 then +00:00 to +39:35. InterImm Year 1 began 1970-04-28. Mars Years use Clancy numbering (MY 1 began 1955-04-11; MY 39 began 2026-09-30).
Conventions: longitudes are degrees EAST of Airy-0 (west longitudes are negative or 360 minus). MTC, LMST and LTST are in Mars hours (1/24 sol). The InterImm clock uses Earth-length hours, so a sol reads 00:00:00 to 23:59:59 then +00:00 to +39:35. InterImm dates are written year-MM-DD with two-digit month and day (31-01-03); Year 1 began 1970-04-28. Mars Years use Clancy numbering (MY 1 began 1955-04-11; MY 39 began 2026-09-30).

## Docs

Expand Down
Loading
Loading