ocs 0.1.5

A session picker for OpenCode
#[derive(Debug, Default, PartialEq)]
pub(crate) struct Time {
  pub(crate) created: u64,
  pub(crate) updated: u64,
}

impl Time {
  pub(crate) fn relative_updated(&self, now: u64) -> String {
    let seconds = now.saturating_sub(self.updated.max(self.created)) / 1_000;

    let (value, unit) = match seconds {
      0..60 => return "now".into(),
      60..3_600 => (seconds / 60, "m"),
      3_600..86_400 => (seconds / 3_600, "h"),
      86_400..604_800 => (seconds / 86_400, "d"),
      604_800..2_629_800 => (seconds / 604_800, "w"),
      2_629_800..31_557_600 => (seconds / 2_629_800, "mo"),
      _ => (seconds / 31_557_600, "y"),
    };

    format!("{value}{unit}")
  }
}

#[cfg(test)]
mod tests {
  use super::*;

  #[test]
  fn formats_relative_updated_time() {
    #[track_caller]
    fn case(elapsed: u64, expected: &str) {
      assert_eq!(
        Time {
          created: 0,
          updated: 1_000,
        }
        .relative_updated(1_000 + elapsed),
        expected,
      );
    }

    case(0, "now");
    case(59_000, "now");
    case(60_000, "1m");
    case(7_200_000, "2h");
    case(172_800_000, "2d");
    case(1_209_600_000, "2w");
    case(5_259_600_000, "2mo");
    case(63_115_200_000, "2y");
  }
}