1use super::*;
4
5pub(crate) fn civil_from_days(z: i64) -> (i64, u32, u32) {
10 let z = z + 719468;
11 let era = (if z >= 0 { z } else { z - 146096 }) / 146097;
12 let doe = z - era * 146097;
13 let yoe = (doe - doe / 1460 + doe / 36524 - doe / 146096) / 365;
14 let y = yoe + era * 400;
15 let doy = doe - (365 * yoe + yoe / 4 - yoe / 100);
16 let mp = (5 * doy + 2) / 153;
17 let d = (doy - (153 * mp + 2) / 5 + 1) as u32;
18 let m = (if mp < 10 { mp + 3 } else { mp - 9 }) as u32;
19 (if m <= 2 { y + 1 } else { y }, m, d)
20}
21pub(crate) fn days_from_civil(y: i64, m: u32, d: u32) -> i64 {
23 let y = if m <= 2 { y - 1 } else { y };
24 let era = (if y >= 0 { y } else { y - 399 }) / 400;
25 let yoe = y - era * 400;
26 let mp = (m as i64 + 9) % 12;
27 let doy = (153 * mp + 2) / 5 + d as i64 - 1;
28 let doe = yoe * 365 + yoe / 4 - yoe / 100 + doy;
29 era * 146097 + doe - 719468
30}
31pub(crate) fn decompose_ms(ms: f64) -> (i64, u32, u32, u32, u32, u32, u32, u32) {
33 let total_ms = libm::floor(ms) as i64;
34 let days = total_ms.div_euclid(86_400_000);
35 let ms_of_day = total_ms.rem_euclid(86_400_000);
36 let (y, mo, d) = civil_from_days(days);
37 let hh = (ms_of_day / 3_600_000) as u32;
38 let mm = ((ms_of_day / 60_000) % 60) as u32;
39 let ss = ((ms_of_day / 1000) % 60) as u32;
40 let mms = (ms_of_day % 1000) as u32;
41 let dow = ((days.rem_euclid(7)) + 4).rem_euclid(7) as u32;
43 (y, mo, d, hh, mm, ss, mms, dow)
44}
45pub(crate) fn epoch_ms_now() -> f64 {
46 match crate::kernel::timer::get_unix_time() {
47 Some(secs) => (secs as f64) * 1000.0,
48 None => 0.0,
51 }
52}
53pub(crate) fn parse_hh_mm(s: &str) -> Option<(i64, i64)> {
59 let mut it = s.splitn(2, ':');
60 let h: i64 = it.next()?.parse().ok()?;
61 let m: i64 = it.next().unwrap_or("0").parse().ok()?;
62 Some((h, m))
63}
64pub(crate) fn parse_tz_offset_hhmm(s: &str) -> Option<(i64, i64)> {
70 if s.contains(':') {
71 return parse_hh_mm(s);
72 }
73 match s.len() {
74 4 => {
75 let h: i64 = s.get(0..2)?.parse().ok()?;
76 let m: i64 = s.get(2..4)?.parse().ok()?;
77 Some((h, m))
78 }
79 2 => {
80 let h: i64 = s.parse().ok()?;
81 Some((h, 0))
82 }
83 _ => parse_hh_mm(s),
84 }
85}
86pub(crate) fn parse_iso_date(s: &str) -> Option<f64> {
87 let s = s.trim();
88 if s.is_empty() {
89 return None;
90 }
91 let (main, tz_offset_min): (&str, i64) = if let Some(rest) = s.strip_suffix('Z') {
94 (rest, 0)
95 } else if let Some(t_pos) = s.find('T') {
96 let time_part = s.get(t_pos..).unwrap_or("");
97 if let Some(sign_pos_rel) = time_part.rfind(['+', '-']) {
98 let sign_pos = t_pos + sign_pos_rel;
99 let sign = if s.as_bytes()[sign_pos] == b'-' { -1i64 } else { 1i64 };
100 let (th, tm) = parse_tz_offset_hhmm(s.get(sign_pos + 1..).unwrap_or(""))?;
101 (s.get(..sign_pos).unwrap_or(""), sign * (th * 60 + tm))
102 } else {
103 (s, 0)
104 }
105 } else {
106 (s, 0)
107 };
108 let (date_part, time_part) = match main.find('T') {
109 Some(p) => (
110 main.get(..p).unwrap_or(""),
111 Some(main.get(p + 1..).unwrap_or("")),
112 ),
113 None => (main, None),
114 };
115 let mut date_it = date_part.split('-');
116 let y: i64 = date_it.next()?.parse().ok()?;
117 let mo: u32 = match date_it.next() {
118 Some(x) => x.parse().ok()?,
119 None => 1,
120 };
121 let d: u32 = match date_it.next() {
122 Some(x) => x.parse().ok()?,
123 None => 1,
124 };
125 if !(1..=12).contains(&mo) || !(1..=31).contains(&d) {
126 return None;
127 }
128 let days = days_from_civil(y, mo, d);
129 let mut ms_of_day: i64 = 0;
130 if let Some(tp) = time_part {
131 let mut parts = tp.splitn(2, ':');
132 let hh: i64 = parts.next()?.parse().ok()?;
133 let rest = parts.next()?;
134 let mut parts2 = rest.splitn(2, ':');
135 let mi: i64 = parts2.next()?.parse().ok()?;
136 let (ss, mms) = match parts2.next() {
137 Some(sec_part) => {
138 if let Some((s_, f_)) = sec_part.split_once('.') {
139 let ss: i64 = s_.parse().ok()?;
140 let mut f = String::from(f_);
141 while f.len() < 3 {
142 f.push('0');
143 }
144 f.truncate(3);
145 let mms: i64 = f.parse().ok()?;
146 (ss, mms)
147 } else {
148 (sec_part.parse().ok()?, 0)
149 }
150 }
151 None => (0, 0),
152 };
153 ms_of_day = hh * 3_600_000 + mi * 60_000 + ss * 1000 + mms;
154 }
155 let ms = days * 86_400_000 + ms_of_day - tz_offset_min * 60_000;
156 Some(ms as f64)
157}
158pub(crate) const MONTH_ABBREVS: [&str; 12] = [
159 "jan", "feb", "mar", "apr", "may", "jun", "jul", "aug", "sep", "oct", "nov", "dec",
160];
161
162pub(crate) fn parse_rfc2822_date(s: &str) -> Option<f64> {
169 let s = s.trim();
170 let s = match s.find(',') {
172 Some(pos) => s.get(pos + 1..)?.trim(),
173 None => s,
174 };
175 let mut tokens = s.split_whitespace();
176 let day: u32 = tokens.next()?.parse().ok()?;
177 let mon_str = tokens.next()?.to_lowercase();
178 let mon = MONTH_ABBREVS
179 .iter()
180 .position(|m| mon_str.starts_with(m))? as u32
181 + 1;
182 let year: i64 = tokens.next()?.parse().ok()?;
183 let time_tok = tokens.next()?;
184 let mut tp = time_tok.splitn(3, ':');
185 let hh: i64 = tp.next()?.parse().ok()?;
186 let mi: i64 = tp.next()?.parse().ok()?;
187 let ss: i64 = tp.next().unwrap_or("0").parse().unwrap_or(0);
188 let tz_offset_min: i64 = match tokens.next() {
189 Some(tz) if tz.eq_ignore_ascii_case("gmt") || tz.eq_ignore_ascii_case("ut") || tz == "Z" => {
190 0
191 }
192 Some(tz) if tz.len() == 5 && (tz.starts_with('+') || tz.starts_with('-')) => {
193 let sign = if tz.starts_with('-') { -1 } else { 1 };
194 let hh_off: i64 = tz.get(1..3)?.parse().ok()?;
195 let mm_off: i64 = tz.get(3..5)?.parse().ok()?;
196 sign * (hh_off * 60 + mm_off)
197 }
198 _ => 0,
199 };
200 if !(1..=12).contains(&mon) || !(1..=31).contains(&day) {
201 return None;
202 }
203 let days = days_from_civil(year, mon, day);
204 let ms_of_day = hh * 3_600_000 + mi * 60_000 + ss * 1000;
205 let ms = days * 86_400_000 + ms_of_day - tz_offset_min * 60_000;
206 Some(ms as f64)
207}
208
209pub(crate) fn parse_date_string(s: &str) -> Option<f64> {
213 parse_iso_date(s).or_else(|| parse_rfc2822_date(s))
214}
215
216pub(crate) fn date_parse_static(_it: &mut Interp, _t: Value, a: &[Value]) -> Result<Value, Value> {
217 Ok(Value::Number(
218 parse_date_string(&arg(a, 0).to_js_string()).unwrap_or(f64::NAN),
219 ))
220}
221pub(crate) fn date_ctor(_it: &mut Interp, _t: Value, a: &[Value]) -> Result<Value, Value> {
226 let ms = if a.is_empty() {
227 epoch_ms_now()
228 } else if a.len() == 1 {
229 let v0 = arg(a, 0);
230 match &v0 {
231 Value::Str(s) => parse_date_string(s).unwrap_or(f64::NAN),
232 _ => v0.to_number(),
233 }
234 } else {
235 let y = arg(a, 0).to_number() as i64;
236 let mo0 = arg(a, 1).to_number() as i64; let d = if a.len() > 2 { arg(a, 2).to_number() as i64 } else { 1 };
238 let hh = if a.len() > 3 { arg(a, 3).to_number() as i64 } else { 0 };
239 let mi = if a.len() > 4 { arg(a, 4).to_number() as i64 } else { 0 };
240 let ss = if a.len() > 5 { arg(a, 5).to_number() as i64 } else { 0 };
241 let mms = if a.len() > 6 { arg(a, 6).to_number() as i64 } else { 0 };
242 let y_adj = y + mo0.div_euclid(12);
244 let m_adj = (mo0.rem_euclid(12) + 1) as u32;
245 let days = days_from_civil(y_adj, m_adj, 1) + (d - 1);
246 (days * 86_400_000 + hh * 3_600_000 + mi * 60_000 + ss * 1000 + mms) as f64
247 };
248 Ok(Value::Object(Obj::date_obj(ms)))
249}
250pub(crate) fn date_now_static(_: &mut Interp, _t: Value, _a: &[Value]) -> Result<Value, Value> {
251 Ok(Value::Number(epoch_ms_now()))
252}
253pub(crate) fn date_utc_static(_: &mut Interp, _t: Value, a: &[Value]) -> Result<Value, Value> {
259 let y = arg(a, 0).to_number() as i64;
260 let mo0 = if a.len() > 1 { arg(a, 1).to_number() as i64 } else { 0 };
261 let d = if a.len() > 2 { arg(a, 2).to_number() as i64 } else { 1 };
262 let hh = if a.len() > 3 { arg(a, 3).to_number() as i64 } else { 0 };
263 let mi = if a.len() > 4 { arg(a, 4).to_number() as i64 } else { 0 };
264 let ss = if a.len() > 5 { arg(a, 5).to_number() as i64 } else { 0 };
265 let mms = if a.len() > 6 { arg(a, 6).to_number() as i64 } else { 0 };
266 Ok(Value::Number(compose_civil_ms(y, mo0, d, hh, mi, ss, mms)))
267}
268pub(crate) fn date_ms(t: &Value) -> f64 {
269 match t {
270 Value::Object(o) => match &o.borrow().kind {
271 ObjKind::DateObj(ms) => *ms,
272 _ => f64::NAN,
273 },
274 _ => f64::NAN,
275 }
276}
277pub(crate) fn input_value_as_date_ms(type_attr: &str, value: &str) -> Option<f64> {
284 if !matches!(type_attr, "date" | "month" | "datetime-local") {
289 return None;
290 }
291 parse_iso_date(value)
292}
293pub(crate) fn input_date_ms_to_value(type_attr: &str, ms: f64) -> Option<String> {
296 if (type_attr != "date" && type_attr != "month") || ms.is_nan() {
297 return None;
298 }
299 let (y, mo, d, ..) = decompose_ms(ms);
300 if type_attr == "month" {
301 Some(alloc::format!("{y:04}-{mo:02}"))
302 } else {
303 Some(alloc::format!("{y:04}-{mo:02}-{d:02}"))
304 }
305}
306pub(crate) fn date_value_ms(v: &Value) -> f64 {
309 date_ms(v)
310}
311pub(crate) fn date_get_time(_: &mut Interp, t: Value, _a: &[Value]) -> Result<Value, Value> {
312 Ok(Value::Number(date_ms(&t)))
313}
314pub(crate) fn date_get_full_year(_: &mut Interp, t: Value, _a: &[Value]) -> Result<Value, Value> {
315 Ok(Value::Number(decompose_ms(date_ms(&t)).0 as f64))
316}
317pub(crate) fn date_get_month(_: &mut Interp, t: Value, _a: &[Value]) -> Result<Value, Value> {
318 Ok(Value::Number((decompose_ms(date_ms(&t)).1 - 1) as f64))
319}
320pub(crate) fn date_get_date(_: &mut Interp, t: Value, _a: &[Value]) -> Result<Value, Value> {
321 Ok(Value::Number(decompose_ms(date_ms(&t)).2 as f64))
322}
323pub(crate) fn date_get_hours(_: &mut Interp, t: Value, _a: &[Value]) -> Result<Value, Value> {
324 Ok(Value::Number(decompose_ms(date_ms(&t)).3 as f64))
325}
326pub(crate) fn date_get_minutes(_: &mut Interp, t: Value, _a: &[Value]) -> Result<Value, Value> {
327 Ok(Value::Number(decompose_ms(date_ms(&t)).4 as f64))
328}
329pub(crate) fn date_get_seconds(_: &mut Interp, t: Value, _a: &[Value]) -> Result<Value, Value> {
330 Ok(Value::Number(decompose_ms(date_ms(&t)).5 as f64))
331}
332pub(crate) fn date_get_milliseconds(_: &mut Interp, t: Value, _a: &[Value]) -> Result<Value, Value> {
333 Ok(Value::Number(decompose_ms(date_ms(&t)).6 as f64))
334}
335pub(crate) fn date_get_day(_: &mut Interp, t: Value, _a: &[Value]) -> Result<Value, Value> {
336 Ok(Value::Number(decompose_ms(date_ms(&t)).7 as f64))
337}
338pub(crate) fn format_iso(ms: f64) -> String {
339 let (y, mo, d, hh, mm, ss, mms, _) = decompose_ms(ms);
340 format!(
341 "{:04}-{:02}-{:02}T{:02}:{:02}:{:02}.{:03}Z",
342 y, mo, d, hh, mm, ss, mms
343 )
344}
345pub(crate) fn date_to_iso_string(_: &mut Interp, t: Value, _a: &[Value]) -> Result<Value, Value> {
346 Ok(Value::str(format_iso(date_ms(&t))))
347}
348pub(crate) fn date_to_string(it: &mut Interp, t: Value, a: &[Value]) -> Result<Value, Value> {
349 date_to_iso_string(it, t, a)
352}
353pub(crate) fn date_to_date_string(_: &mut Interp, t: Value, _a: &[Value]) -> Result<Value, Value> {
357 let (y, mo, d, ..) = decompose_ms(date_ms(&t));
358 Ok(Value::str(format!("{:04}-{:02}-{:02}", y, mo, d)))
359}
360pub(crate) fn date_to_time_string(_: &mut Interp, t: Value, _a: &[Value]) -> Result<Value, Value> {
362 let (_, _, _, hh, mm, ss, ..) = decompose_ms(date_ms(&t));
363 Ok(Value::str(format!("{:02}:{:02}:{:02}", hh, mm, ss)))
364}
365pub(crate) fn compose_civil_ms(y: i64, mo0: i64, d: i64, hh: i64, mi: i64, ss: i64, mms: i64) -> f64 {
372 let y_adj = y + mo0.div_euclid(12);
373 let m_adj = (mo0.rem_euclid(12) + 1) as u32;
374 let days = days_from_civil(y_adj, m_adj, 1) + (d - 1);
375 (days * 86_400_000 + hh * 3_600_000 + mi * 60_000 + ss * 1000 + mms) as f64
376}
377pub(crate) fn date_write_ms(t: &Value, ms: f64) {
378 if let Value::Object(o) = t {
379 if let ObjKind::DateObj(slot) = &mut o.borrow_mut().kind {
380 *slot = ms;
381 }
382 }
383}
384pub(crate) fn date_set_time(_: &mut Interp, t: Value, a: &[Value]) -> Result<Value, Value> {
385 let ms = arg(a, 0).to_number();
386 date_write_ms(&t, ms);
387 Ok(Value::Number(ms))
388}
389pub(crate) fn date_get_year(_: &mut Interp, t: Value, _a: &[Value]) -> Result<Value, Value> {
393 Ok(Value::Number(decompose_ms(date_ms(&t)).0 as f64 - 1900.0))
394}
395pub(crate) fn date_set_year(_: &mut Interp, t: Value, a: &[Value]) -> Result<Value, Value> {
399 let (_, mo1, d0, hh, mi, ss, mms, _) = decompose_ms(date_ms(&t));
400 let y_arg = arg(a, 0).to_number();
401 let y = if (0.0..=99.0).contains(&y_arg) { 1900.0 + y_arg } else { y_arg } as i64;
402 let ms = compose_civil_ms(y, mo1 as i64 - 1, d0 as i64, hh as i64, mi as i64, ss as i64, mms as i64);
403 date_write_ms(&t, ms);
404 Ok(Value::Number(ms))
405}
406pub(crate) fn date_set_full_year(_: &mut Interp, t: Value, a: &[Value]) -> Result<Value, Value> {
407 let (_, mo1, d0, hh, mi, ss, mms, _) = decompose_ms(date_ms(&t));
408 let y = arg(a, 0).to_number() as i64;
409 let mo0 = if a.len() > 1 { arg(a, 1).to_number() as i64 } else { mo1 as i64 - 1 };
410 let d = if a.len() > 2 { arg(a, 2).to_number() as i64 } else { d0 as i64 };
411 let ms = compose_civil_ms(y, mo0, d, hh as i64, mi as i64, ss as i64, mms as i64);
412 date_write_ms(&t, ms);
413 Ok(Value::Number(ms))
414}
415pub(crate) fn date_set_month(_: &mut Interp, t: Value, a: &[Value]) -> Result<Value, Value> {
416 let (y, _, d0, hh, mi, ss, mms, _) = decompose_ms(date_ms(&t));
417 let mo0 = arg(a, 0).to_number() as i64;
418 let d = if a.len() > 1 { arg(a, 1).to_number() as i64 } else { d0 as i64 };
419 let ms = compose_civil_ms(y, mo0, d, hh as i64, mi as i64, ss as i64, mms as i64);
420 date_write_ms(&t, ms);
421 Ok(Value::Number(ms))
422}
423pub(crate) fn date_set_date(_: &mut Interp, t: Value, a: &[Value]) -> Result<Value, Value> {
424 let (y, mo1, _, hh, mi, ss, mms, _) = decompose_ms(date_ms(&t));
425 let d = arg(a, 0).to_number() as i64;
426 let ms = compose_civil_ms(y, mo1 as i64 - 1, d, hh as i64, mi as i64, ss as i64, mms as i64);
427 date_write_ms(&t, ms);
428 Ok(Value::Number(ms))
429}
430pub(crate) fn date_set_hours(_: &mut Interp, t: Value, a: &[Value]) -> Result<Value, Value> {
431 let (y, mo1, d, _, mi0, ss0, mms0, _) = decompose_ms(date_ms(&t));
432 let hh = arg(a, 0).to_number() as i64;
433 let mi = if a.len() > 1 { arg(a, 1).to_number() as i64 } else { mi0 as i64 };
434 let ss = if a.len() > 2 { arg(a, 2).to_number() as i64 } else { ss0 as i64 };
435 let mms = if a.len() > 3 { arg(a, 3).to_number() as i64 } else { mms0 as i64 };
436 let ms = compose_civil_ms(y, mo1 as i64 - 1, d as i64, hh, mi, ss, mms);
437 date_write_ms(&t, ms);
438 Ok(Value::Number(ms))
439}
440pub(crate) fn date_set_minutes(_: &mut Interp, t: Value, a: &[Value]) -> Result<Value, Value> {
441 let (y, mo1, d, hh, _, ss0, mms0, _) = decompose_ms(date_ms(&t));
442 let mi = arg(a, 0).to_number() as i64;
443 let ss = if a.len() > 1 { arg(a, 1).to_number() as i64 } else { ss0 as i64 };
444 let mms = if a.len() > 2 { arg(a, 2).to_number() as i64 } else { mms0 as i64 };
445 let ms = compose_civil_ms(y, mo1 as i64 - 1, d as i64, hh as i64, mi, ss, mms);
446 date_write_ms(&t, ms);
447 Ok(Value::Number(ms))
448}
449pub(crate) fn date_set_seconds(_: &mut Interp, t: Value, a: &[Value]) -> Result<Value, Value> {
450 let (y, mo1, d, hh, mi, _, mms0, _) = decompose_ms(date_ms(&t));
451 let ss = arg(a, 0).to_number() as i64;
452 let mms = if a.len() > 1 { arg(a, 1).to_number() as i64 } else { mms0 as i64 };
453 let ms = compose_civil_ms(y, mo1 as i64 - 1, d as i64, hh as i64, mi as i64, ss, mms);
454 date_write_ms(&t, ms);
455 Ok(Value::Number(ms))
456}
457pub(crate) fn date_set_milliseconds(_: &mut Interp, t: Value, a: &[Value]) -> Result<Value, Value> {
458 let (y, mo1, d, hh, mi, ss, _, _) = decompose_ms(date_ms(&t));
459 let mms = arg(a, 0).to_number() as i64;
460 let ms = compose_civil_ms(y, mo1 as i64 - 1, d as i64, hh as i64, mi as i64, ss as i64, mms);
461 date_write_ms(&t, ms);
462 Ok(Value::Number(ms))
463}
464pub fn date_get(key: &str) -> Value {
465 match key {
466 "getTime" | "valueOf" => nv("getTime", date_get_time),
467 "getFullYear" | "getUTCFullYear" => nv("getFullYear", date_get_full_year),
468 "getMonth" | "getUTCMonth" => nv("getMonth", date_get_month),
469 "getDate" | "getUTCDate" => nv("getDate", date_get_date),
470 "getHours" | "getUTCHours" => nv("getHours", date_get_hours),
471 "getMinutes" | "getUTCMinutes" => nv("getMinutes", date_get_minutes),
472 "getSeconds" | "getUTCSeconds" => nv("getSeconds", date_get_seconds),
473 "getMilliseconds" | "getUTCMilliseconds" => nv("getMilliseconds", date_get_milliseconds),
474 "getDay" | "getUTCDay" => nv("getDay", date_get_day),
475 "getYear" => nv("getYear", date_get_year),
478 "setYear" => nv("setYear", date_set_year),
479 "setTime" => nv("setTime", date_set_time),
480 "setFullYear" | "setUTCFullYear" => nv("setFullYear", date_set_full_year),
481 "setMonth" | "setUTCMonth" => nv("setMonth", date_set_month),
482 "setDate" | "setUTCDate" => nv("setDate", date_set_date),
483 "setHours" | "setUTCHours" => nv("setHours", date_set_hours),
484 "setMinutes" | "setUTCMinutes" => nv("setMinutes", date_set_minutes),
485 "setSeconds" | "setUTCSeconds" => nv("setSeconds", date_set_seconds),
486 "setMilliseconds" | "setUTCMilliseconds" => nv("setMilliseconds", date_set_milliseconds),
487 "toISOString" | "toJSON" => nv("toISOString", date_to_iso_string),
488 "toString" => nv("toString", date_to_string),
489 "toLocaleString" => nv("toLocaleString", date_to_locale_string),
490 "toDateString" => nv("toDateString", date_to_date_string),
491 "toLocaleDateString" => nv("toLocaleDateString", date_to_locale_date_string),
492 "toTimeString" => nv("toTimeString", date_to_time_string),
493 "toLocaleTimeString" => nv("toLocaleTimeString", date_to_locale_time_string),
494 "getTimezoneOffset" => nv("getTimezoneOffset", date_get_timezone_offset),
499 _ => Value::Undefined,
500 }
501}
502pub(crate) fn date_get_timezone_offset(_it: &mut Interp, _t: Value, _a: &[Value]) -> Result<Value, Value> {
503 Ok(Value::Number(0.0))
504}
505
506fn format_locale_date(ms: f64) -> String {
517 let (y, mo, d, ..) = decompose_ms(ms);
518 format!("{:04}-{:02}-{:02}", y, mo, d)
519}
520fn format_locale_time(ms: f64) -> String {
521 let (_, _, _, hh, mm, ss, ..) = decompose_ms(ms);
522 format!("{:02}:{:02}:{:02}", hh, mm, ss)
523}
524pub(crate) fn date_to_locale_string(_it: &mut Interp, t: Value, _a: &[Value]) -> Result<Value, Value> {
525 let ms = date_ms(&t);
526 Ok(Value::str(format!("{} {}", format_locale_date(ms), format_locale_time(ms))))
527}
528
529pub(crate) fn date_to_locale_date_string(_it: &mut Interp, t: Value, _a: &[Value]) -> Result<Value, Value> {
530 Ok(Value::str(format_locale_date(date_ms(&t))))
531}
532
533pub(crate) fn date_to_locale_time_string(_it: &mut Interp, t: Value, _a: &[Value]) -> Result<Value, Value> {
534 Ok(Value::str(format_locale_time(date_ms(&t))))
535}
536