bitwarden_importers/importers/onepassword/convert/
value.rs1use chrono::{DateTime, TimeDelta};
4
5pub(super) fn render_value(kind: Option<&str>, value: &serde_json::Value) -> Option<String> {
8 match (kind, value) {
9 (_, serde_json::Value::Null) => None,
10 (_, serde_json::Value::String(text)) => non_blank(text).map(str::to_string),
11 (Some("date"), serde_json::Value::Number(seconds)) => seconds
12 .as_i64()
13 .map(render_date)
14 .or(Some(value.to_string())),
15 (Some("monthYear"), serde_json::Value::Number(number)) => Some(
16 number
17 .as_i64()
18 .and_then(month_year)
19 .map(|(year, month)| format!("{year:04}-{month:02}"))
20 .unwrap_or_else(|| value.to_string()),
21 ),
22 (_, other) => Some(other.to_string()),
23 }
24}
25
26fn render_date(seconds: i64) -> String {
31 DateTime::from_timestamp(seconds, 0)
32 .and_then(|date| date.checked_add_signed(TimeDelta::hours(12)))
33 .map(|date| date.format("%Y-%m-%d").to_string())
34 .unwrap_or_else(|| seconds.to_string())
35}
36
37pub(super) fn month_year(value: i64) -> Option<(i64, i64)> {
39 let (year, month) = (value / 100, value % 100);
40 (1..=12).contains(&month).then_some((year, month))
41}
42
43pub(super) fn non_blank(value: &str) -> Option<&str> {
44 (!value.trim().is_empty()).then_some(value)
45}