-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathdst.html
More file actions
143 lines (135 loc) · 4.8 KB
/
Copy pathdst.html
File metadata and controls
143 lines (135 loc) · 4.8 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
<!doctype html>
<html lang="en">
<!-- sponsored by ChatGPT o3 -->
<!-- thanks for billiard26 for helping me understand this -->
<head>
<meta charset="utf-8">
<title>Dolphin Serial → Timestamp (Legacy & Current)</title>
<style>
body{font-family:sans-serif;max-width:760px;margin:2rem auto;padding:0 1rem;line-height:1.5}
h1{font-size:1.9rem;margin-bottom:0.4rem}
h2{font-size:1.2rem;margin:1.2rem 0 0.3rem}
input,button{font-size:1rem}
input{padding:0.46rem 0.6rem;margin-right:0.4rem}
button{padding:0.5rem 0.9rem;cursor:pointer}
.inline{display:inline-block;margin-right:0.8rem}
.output{margin-top:1rem}
ul{padding-left:1.3rem;margin-top:0.4rem}
li{margin-bottom:0.3rem}
small{color:#555}
</style>
</head>
<body>
<h1>Dolphin Serial ⇒ Candidate Timestamps</h1>
<p>This tool enumerates possible timestamps for <strong>both</strong> Dolphin serial
generators:</p>
<ul>
<li><strong>Legacy:</strong> <code>fmt::format("{%j%H%M%S}", localtime(t))</code> → day‑of‑year + HHMMSS (9 digits)</li>
<li><strong>Current:</strong> <code>fmt::format("{:09}", t % 1 000 000 000)</code> → last 9 digits of Unix time (wraps every ≈31 years 8 months)</li>
</ul>
<div class="inline">
<label>Serial<br>
<input id="serial" type="text" pattern="\d{1,9}" placeholder="162155104" style="width:11rem">
</label>
</div>
<div class="inline">
<label>Years ⤵︎<br>
<input id="yearFrom" type="number" value="2017" style="width:5rem"> –
<input id="yearTo" type="number" style="width:5rem">
</label>
</div>
<button id="decode">Decode</button>
<div id="output" class="output"></div>
<script>
const BILLION = 1_000_000_000;
const currentYear = new Date().getFullYear();
document.getElementById('yearTo').value = currentYear;
/* ---------- Legacy decoder (%j%H%M%S) ---------- */
function parseLegacy(serial){
if(!/^[0-9]{8,9}$/.test(serial)) return null;
const s = serial.padStart(9,'0');
const doy = parseInt(s.slice(0,3),10);
const hour = parseInt(s.slice(3,5),10);
const min = parseInt(s.slice(5,7),10);
const sec = parseInt(s.slice(7,9),10);
if(doy<1||doy>366||hour>23||min>59||sec>59) return null;
return {doy,hour,min,sec};
}
function buildLegacyDate(year,p){
const d=new Date(year,0,1,p.hour,p.min,p.sec);
d.setDate(d.getDate()+p.doy-1);
return d.getFullYear()===year?d:null; // reject overflow on non‑leap years
}
function enumerateLegacy(serial,yFrom,yTo){
const parts=parseLegacy(serial);
if(!parts) return [];
const list=[];
for(let y=yFrom;y<=yTo;y++){
const dt=buildLegacyDate(y,parts);
if(dt) list.push(dt);
}
return list;
}
/* ---------- Current decoder (tail‑of‑Unix‑time) ---------- */
function enumerateCurrent(serial,yFrom,yTo){
const n=Number(serial.replace(/^0+/,''));
if(!Number.isFinite(n)||n>=BILLION) return [];
const startTs=Date.UTC(yFrom,0,1)/1000;
const endTs=Date.UTC(yTo+1,0,1)/1000-1;
const kMin=Math.ceil((startTs-n)/BILLION);
const kMax=Math.floor((endTs-n)/BILLION);
const list=[];
for(let k=kMin;k<=kMax;k++){
const ts=n+k*BILLION;
list.push(new Date(ts*1000));
}
return list;
}
/* ---------- UI ---------- */
function renderList(title,dates){
const frag=document.createDocumentFragment();
const h2=document.createElement('h2');
h2.textContent=title;
frag.appendChild(h2);
if(dates.length===0){
const p=document.createElement('p');
p.textContent='— none in range —';
frag.appendChild(p);
return frag;
}
const ul=document.createElement('ul');
dates.forEach(d=>{
const li=document.createElement('li');
li.textContent=`${d.toLocaleString()} (local) • ${d.toUTCString()} (UTC)`;
ul.appendChild(li);
});
frag.appendChild(ul);
if(dates.length>1){
const note=document.createElement('small');
note.textContent='Pick the one matching your install year.';
frag.appendChild(note);
}
return frag;
}
function decode(){
const raw=document.getElementById('serial').value.trim();
const yFrom=parseInt(document.getElementById('yearFrom').value,10);
const yTo=parseInt(document.getElementById('yearTo').value,10);
const out=document.getElementById('output');
out.innerHTML='';
if(!/^\d{1,9}$/.test(raw)||yFrom>yTo){
out.textContent='✖️ Invalid input.';
return;
}
const legacyDates=enumerateLegacy(raw,yFrom,yTo);
const currentDates=enumerateCurrent(raw,yFrom,yTo);
out.appendChild(renderList('Legacy (%j%H%M%S)',legacyDates));
out.appendChild(renderList('Current (tail‑of‑Unix‑time)',currentDates));
}
document.getElementById('decode').addEventListener('click',decode);
document.getElementById('serial').addEventListener('keydown',e=>{
if(e.key==='Enter') decode();
});
</script>
</body>
</html>