使用データ
計算用パラメータを求めるためのデータは、理科年表プレミアムの グリニッジ恒星時 1960 〜 2025 年(66年分)を修正して使用しています。
計算式
計算式は、一次式とサイン関数4つの和です。サイン関数の周期は、理科年表に記載されている
| 周期 | 日 |
|---|---|
| 半年 | 365.24219 ÷ 2 |
| 1年 | 365.24219 |
| 月:対恒星交点順行周期 | 3232.605 |
| 月:対恒星交点逆行周期 | 6793.477 |
を用いています。パラメータは Python の numpy と scipy.optimize.curve_fit で求めました。
Python
# import math が必要
# T は 2000/1/1 からの経過日数で、結果は秒[0,86400)が得られる
(sum([
(+23992.21618202308309264481067657470703125
if T < -5478 else
+23992.27275168397682136856019496917724609375),
+236.55536717968294624370173551142215728759765625 * T,
*(v * math.sin((T + p) * r) for v, p, r in (
(+0.079137171399709826946633484112680889666080474853515625,
+14619.81569701491753221489489078521728515625,
+0.03440558335924766286684217675428953953087329864501953125),
(+0.00777027586037625818404794841853799880482256412506103515625,
+14601.25901597426491207443177700042724609375,
+0.017202791679623831433421088377144769765436649322509765625),
(-0.01008260911585116999245048674538338673301041126251220703125,
+14050.13595880462889908812940120697021484375,
+0.00194369101921811862805633541739780412171967327594757080078125),
(-1.0558999819068641823349707919987849891185760498046875,
+14628.993680660876634647138416767120361328125,
+0.000924885048875500183178377522352775486069731414318084716796875)))
]) % 86400)
JavaScript
// T は 2000/1/1 からの経過日数で、結果は秒(-86400,86400)が得られる
((((T < -5478)
? 23992.21618202308309264481067657470703125
: 23992.27275168397682136856019496917724609375)
+ 236.55536717968294624370173551142215728759765625 * T
+ [[0.079137171399709826946633484112680889666080474853515625,
14619.81569701491753221489489078521728515625,
0.03440558335924766286684217675428953953087329864501953125],
[0.00777027586037625818404794841853799880482256412506103515625,
14601.25901597426491207443177700042724609375,
0.017202791679623831433421088377144769765436649322509765625],
[-0.01008260911585116999245048674538338673301041126251220703125,
14050.13595880462889908812940120697021484375,
0.00194369101921811862805633541739780412171967327594757080078125],
[-1.0558999819068641823349707919987849891185760498046875,
14628.993680660876634647138416767120361328125,
0.000924885048875500183178377522352775486069731414318084716796875]
].reduce((a, d) => a + d[0] * Math.sin((T + d[1]) * d[2]), 0)) % 86400)
誤差は±0.1秒以内に収まりましたが、数値表現では理科年表と違うものが出てきます。
グリニッジ恒星時 世界時 0時の表
sample.html
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<title>グリニッジ恒星時 世界時 各日0時</title>
<style>
table {
border: solid 1px lightgray;
border-collaspe: collaspe;
border-spacing: 0;
}
th, td {
border: solid 1px lightgray;
padding: 4px;
}
</style>
</head>
<body>
<script>
const start_year = 1950;
const end_year = 2050;
const num_years = end_year - start_year + 1;
const table = [...Array(num_years)].map(() => [...Array(12)].map(() => []));
function initialize() {
const edt = Date.UTC(end_year + 1);
var cdt = Date.UTC(start_year);
for (var p = 0; cdt < edt; p += 1, cdt += 86400_000) {
const dt = new Date(cdt);
const year = dt.getUTCFullYear();
const month = dt.getUTCMonth();
const ytab = table[year - start_year];
const mtab = ytab[month];
mtab.push(new Date(cdt - (9*3600_000)));
}
const year = Math.max(start_year, Math.min(new Date().getFullYear(), end_year));
document.body.innerHTML = [
'<table style="margin-bottom: 2px;">',
'<tr>',
'<td>グリニッジ恒星時 世界時 各日0時</td>',
'<td>',
'<input',
/**/ ' id="tagYear" name="tagYear" type="number"',
/**/ ` min="${start_year}" max="${end_year}" value="${year}"`,
/**/ ' onchange="setYear()">',
'<label for="tagYear">年</label>',
`<span>(${start_year}〜${end_year})</span>`,
'</td>',
'</table>',
'<table id="tagTable"></table>',
].join('');
setYear();
}
function getGST(T) {
return ((((T < -5478)
? 23992.21618202308309264481067657470703125
: 23992.27275168397682136856019496917724609375)
+ 236.55536717968294624370173551142215728759765625 * T
+ [[0.079137171399709826946633484112680889666080474853515625,
14619.81569701491753221489489078521728515625,
0.03440558335924766286684217675428953953087329864501953125],
[0.00777027586037625818404794841853799880482256412506103515625,
14601.25901597426491207443177700042724609375,
0.017202791679623831433421088377144769765436649322509765625],
[-0.01008260911585116999245048674538338673301041126251220703125,
14050.13595880462889908812940120697021484375,
0.00194369101921811862805633541739780412171967327594757080078125],
[-1.0558999819068641823349707919987849891185760498046875,
14628.993680660876634647138416767120361328125,
0.000924885048875500183178377522352775486069731414318084716796875]
].reduce((a, d) => a + d[0] * Math.sin((T + d[1]) * d[2]), 0)) % 86400);
}
function setYear() {
const dty2000 = new Date(Date.UTC(2000, 1-1, 1) - (9*3600_000));
const month = [
"1", "2", "3", "4", "5", "6",
"7", "8", "9", "10", "11", "12",
];
const year = Math.max(start_year, Math.min(tagYear.value, end_year));
if (tagYear.value != year)
tagYear.value = year;
const ytab = table[year - start_year];
const fmt02 = ((n) => {
const s = `0${n}`;
return s.substring(s.length-2);
});
const fmt02_1f = ((n) => `${fmt02((n/10)|0)}.${n%10}`);
const fmt02_2f = ((n) => `${fmt02((n/100)|0)}.${fmt02(n%100)}`);
const hms = ((msec) => {
if (msec < 0) msec = (msec % 86400_000) + 86400_000;
const h = Math.trunc(msec / 3600_000); msec -= h * 3600_000;
const m = Math.trunc(msec / 60_000); msec -= m * 60_000;
return `${fmt02(h)}:${fmt02(m)}:${fmt02_1f((msec/100)|0)}`;
// return `${fmt02(h)}:${fmt02(m)}:${fmt02_2f((msec/10)|0)}`;
});
const getData = ((mon, day) => {
const mtab = ytab[mon];
return (day >= mtab.length) ? ' ' :
hms(getGST((mtab[day] - dty2000) / 86400_000) * 1000);
});
const html = [
'<tr>',
'<th>日\月</th>',
[...Array(12)].map((_, n) => `<th>${month[n]}</th>`),
[...Array(31)].map((_, day) => [
'<tr>',
`<th>${day+1}</th>`,
[...Array(12)].map((_, mon) => [
'<td>', getData(mon, day), '</td>',
].join('')),
'</tr>',
].flat().join('')),
].flat().join('');
tagTable.innerHTML = html;
}
window.onload = initialize;
</script>
</body>
</html>
Comments
そもそもjavascriptの数値(Number)型に何十桁もの精度はありませんから誤差も出るでしょう。
Let's comment your feelings that are more than good