MCPcopy Create free account
hub / github.com/ScriptedAlchemy/tracedecay / parse_cursor_human_timestamp

Function parse_cursor_human_timestamp

src/timeutil.rs:181–238  ·  view source on GitHub ↗

Parses the human-readable timestamp Cursor injects into user prompts as ` … ` (e.g. `Wednesday, Jun 10, 2026, 9:11 AM (UTC+2)`) into Unix epoch seconds. Cursor transcript JSONL carries no structured per-message timestamps, so this tag is the only per-message time signal available to ingest. The parser is tolerant: the weekday is optional, the clock accepts 12-hour (`AM`/`PM`)

(value: &str)

Source from the content-addressed store, hash-verified

179/// (`AM`/`PM`) or 24-hour form, and the offset accepts `(UTC)`, `(UTC±H)`,
180/// and `(UTC±H:MM)`.
181pub fn parse_cursor_human_timestamp(value: &str) -> Option<i64> {
182 let parts: Vec<&str> = value.split(',').map(str::trim).collect();
183 // [weekday,] "Jun 10", "2026", "9:11 AM (UTC+2)"
184 let (month_day, year_part, time_part) = match parts.as_slice() {
185 [_, month_day, year, time] | [month_day, year, time] => (*month_day, *year, *time),
186 _ => return None,
187 };
188
189 let mut md = month_day.split_whitespace();
190 let month = month_number(md.next()?)?;
191 let day: u32 = md.next()?.parse().ok()?;
192 if md.next().is_some() {
193 return None;
194 }
195 let year: i32 = year_part.parse().ok()?;
196 if day == 0 || day > days_in_month(year, month) {
197 return None;
198 }
199
200 let mut clock = time_part.split_whitespace();
201 let hour_minute = clock.next()?;
202 let (hour_text, minute_text) = hour_minute.split_once(':')?;
203 let mut hour: u32 = hour_text.parse().ok()?;
204 let minute: u32 = minute_text.parse().ok()?;
205 let mut rest = clock.next();
206 match rest.map(str::to_ascii_uppercase).as_deref() {
207 Some("AM") => {
208 if !(1..=12).contains(&hour) {
209 return None;
210 }
211 hour %= 12;
212 rest = clock.next();
213 }
214 Some("PM") => {
215 if !(1..=12).contains(&hour) {
216 return None;
217 }
218 hour = hour % 12 + 12;
219 rest = clock.next();
220 }
221 _ => {}
222 }
223 if hour > 23 || minute > 59 {
224 return None;
225 }
226 let offset_seconds = match rest {
227 Some(zone) => parse_utc_offset(zone)?,
228 None => 0,
229 };
230 if clock.next().is_some() {
231 return None;
232 }
233
234 let days = days_from_civil(year, month, day);
235 let local_seconds = days * 86_400 + i64::from(hour) * 3_600 + i64::from(minute) * 60;
236 let timestamp = local_seconds - offset_seconds;
237 (timestamp >= 0).then_some(timestamp)
238}

Callers 1

timestamp_tag_from_textFunction · 0.85

Calls 7

month_numberFunction · 0.85
days_in_monthFunction · 0.85
parse_utc_offsetFunction · 0.85
days_from_civilFunction · 0.85
collectMethod · 0.80
parseMethod · 0.45
containsMethod · 0.45

Tested by

no test coverage detected