# Data Utilities — `data.rs`

## 6.1 Numbers — `data/numbers.rs`

```rust
/// Format with thousand separators: 1_234_567.89 → "1,234,567.89"
pub fn format_number(n: f64, decimals: usize, sep: char) -> String

/// Format as currency: format_currency(1234.5, "USD") → "$1,234.50"
pub fn format_currency(amount: f64, currency: &str) -> String

/// Format as percentage: 0.1234 → "12.34%"
pub fn format_percentage(ratio: f64, decimals: usize) -> String

pub fn round(n: f64, decimals: u32) -> f64
pub fn ceil(n: f64, decimals: u32) -> f64
pub fn floor(n: f64, decimals: u32) -> f64
pub fn clamp(n: f64, min: f64, max: f64) -> f64
pub fn lerp(a: f64, b: f64, t: f64) -> f64
```

## 6.2 Dates — `data/dates.rs` _(feature = "dates")_

```rust
use chrono::{DateTime, Utc, NaiveDate, Duration};

pub fn now() -> DateTime<Utc>
pub fn today() -> NaiveDate
pub fn yesterday() -> NaiveDate
pub fn tomorrow() -> NaiveDate

/// Format date: format_date(now(), "%Y-%m-%d") → "2025-01-15"
pub fn format_date(dt: &DateTime<Utc>, fmt: &str) -> String

/// Parse from string: parse_date("2025-01-15", "%Y-%m-%d")
pub fn parse_date(s: &str, fmt: &str) -> Result<DateTime<Utc>, RokError>

/// Diff in days between two dates
pub fn diff_days(a: &NaiveDate, b: &NaiveDate) -> i64

/// Human-readable relative time: "3 days ago", "in 5 minutes"
pub fn human_diff(dt: &DateTime<Utc>) -> String

/// Add duration
pub fn add_days(dt: &NaiveDate, days: i64) -> NaiveDate
pub fn add_hours(dt: &DateTime<Utc>, hours: i64) -> DateTime<Utc>
```

## 6.3 IDs — `data/ids.rs` _(feature = "ids")_

```rust
/// UUID v4 (random) — Laravel: Str::uuid()
pub fn uuid_v4() -> String

/// UUID v7 (time-ordered) — Laravel: Str::uuid7() / Str::orderedUuid()
pub fn uuid_v7() -> String

/// ULID — Laravel: Str::ulid()
pub fn ulid() -> String

/// Validate UUID string — Laravel: Str::isUuid()
pub fn is_uuid(s: &str) -> bool

/// Validate ULID string — Laravel: Str::isUlid()
pub fn is_ulid(s: &str) -> bool
```

## 6.4 Hashing — `data/hashing.rs` _(feature = "crypto")_

```rust
/// SHA-256 hex digest
pub fn hash_sha256(input: &str) -> String

/// Verify SHA-256 hash
pub fn verify_sha256(input: &str, expected: &str) -> bool

/// Generate a secure opaque token (URL-safe base64 of random bytes)
/// Like AdonisJS opaque tokens
pub fn generate_token(bytes: usize) -> String

/// Constant-time comparison to prevent timing attacks
pub fn secure_compare(a: &str, b: &str) -> bool
```