Skip to content

Commit 90a0fb6

Browse files
authored
fix Forge metadata timestamp handling (#7767)
* fix Forge metadata timestamp handling * fmt
1 parent 54713c8 commit 90a0fb6

1 file changed

Lines changed: 64 additions & 2 deletions

File tree

‎packages/daedalus/src/modded.rs‎

Lines changed: 64 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -93,9 +93,19 @@ fn deserialize_date<'de, D>(deserializer: D) -> Result<DateTime<Utc>, D::Error>
9393
where
9494
D: Deserializer<'de>,
9595
{
96-
let s = String::deserialize(deserializer)?;
96+
let mut s = String::deserialize(deserializer)?;
9797

98-
serde_json::from_str::<DateTime<Utc>>(&format!("\"{s}\""))
98+
if let Some((_, offset)) = s.rsplit_once(['+', '-'])
99+
&& matches!(
100+
offset.as_bytes(),
101+
[b'0'..=b'9', b':', b'0'..=b'9', b'0'..=b'9']
102+
)
103+
{
104+
s.insert(s.len() - offset.len(), '0');
105+
}
106+
107+
DateTime::parse_from_rfc3339(&s)
108+
.map(|date| date.with_timezone(&Utc))
99109
.or_else(|_| {
100110
NaiveDateTime::parse_from_str(&s, "%Y-%m-%dT%H:%M:%S%.f")
101111
.map(|date| date.and_utc())
@@ -291,3 +301,55 @@ pub struct LoaderVersion {
291301
/// Whether the loader is stable or not
292302
pub stable: bool,
293303
}
304+
305+
#[cfg(test)]
306+
mod tests {
307+
use super::PartialVersionInfo;
308+
use chrono::{DateTime, Utc};
309+
use serde_json::json;
310+
311+
fn deserialize_version(
312+
date: &str,
313+
) -> serde_json::Result<PartialVersionInfo> {
314+
serde_json::from_value(json!({
315+
"id": "1.21.11-forge-61.1.7",
316+
"inheritsFrom": "1.21.11",
317+
"time": date,
318+
"releaseTime": date,
319+
"libraries": [],
320+
"type": "release"
321+
}))
322+
}
323+
324+
#[test]
325+
fn deserialize_loader_timestamps() {
326+
for (input, expected) in [
327+
("2026-05-27T14:13:59+0:00", "2026-05-27T14:13:59Z"),
328+
("2026-05-27T14:13:59+5:30", "2026-05-27T08:43:59Z"),
329+
("2026-05-27T14:13:59-5:30", "2026-05-27T19:43:59Z"),
330+
("2026-05-27T14:13:59.123+0:00", "2026-05-27T14:13:59.123Z"),
331+
("2026-05-27T14:13:59+00:00", "2026-05-27T14:13:59Z"),
332+
("2026-05-27T14:13:59+05:30", "2026-05-27T08:43:59Z"),
333+
("2026-05-27T14:13:59Z", "2026-05-27T14:13:59Z"),
334+
("2026-05-27T14:13:59", "2026-05-27T14:13:59Z"),
335+
("2026-05-27T14:13:59.123", "2026-05-27T14:13:59.123Z"),
336+
] {
337+
let version = deserialize_version(input).unwrap();
338+
let expected = expected.parse::<DateTime<Utc>>().unwrap();
339+
assert_eq!(version.time, expected, "{input}");
340+
assert_eq!(version.release_time, expected, "{input}");
341+
}
342+
}
343+
344+
#[test]
345+
fn reject_invalid_loader_timestamps() {
346+
for input in [
347+
"not a date",
348+
"2026-05-27T14:13:59+0:60",
349+
"2026-05-27T14:13:59+0:00junk",
350+
"2026-05-27T14:13:59\"",
351+
] {
352+
assert!(deserialize_version(input).is_err(), "{input}");
353+
}
354+
}
355+
}

0 commit comments

Comments
 (0)