From Gregorian (ParsiDateTime) - parsicore/parsidate GitHub Wiki

Static Function ParsiDateTime::from_gregorian

Converts a Gregorian chrono::NaiveDateTime to its equivalent ParsiDateTime.

Description

This function takes a chrono::NaiveDateTime instance, which represents a specific date and time in the Gregorian calendar (without timezone information), and converts it into the corresponding ParsiDateTime in the Persian (Hejri-Shamsi) calendar.

The conversion process involves these steps:

  1. Extracts the date component (chrono::NaiveDate) from the input gregorian_dt.
  2. Converts this NaiveDate into a ParsiDate using the logic provided by ParsiDate::from_gregorian. This handles the core calendar conversion logic.
  3. Extracts the time components (hour, minute, second) directly from the input gregorian_dt. Note: Nanoseconds present in the input NaiveDateTime are ignored and not preserved in the resulting ParsiDateTime.
  4. Combines the successfully converted ParsiDate and the extracted time components (hour, minute, second) to create the final ParsiDateTime instance.

Arguments

  • gregorian_dt: The chrono::NaiveDateTime instance to convert.

Returns

  • Ok(ParsiDateTime): If the conversion of the date part is successful, returns the resulting ParsiDateTime instance wrapped in Ok.
  • Err(DateError::GregorianConversionError): If the conversion of the date part fails. This error is propagated from the underlying call to ParsiDate::from_gregorian.

Error Conditions

The primary reason for failure is an error during the conversion of the date component:

  • DateError::GregorianConversionError: This typically occurs if the date part of the input gregorian_dt represents a Gregorian date that:
    • Falls before the start of the Persian calendar epoch (approximately March 21st, 622 CE).
    • Results in a Persian date outside the year range supported by ParsiDate (e.g., year 0 or year 10000+).

Examples (Rust)

use chrono::{NaiveDate, NaiveTime, NaiveDateTime};
use parsidate::{ParsiDateTime, ParsiDate, DateError}; // Assuming these types exist

// --- Example 1: Standard Conversion ---
// Define a Gregorian NaiveDateTime
let g_date = NaiveDate::from_ymd_opt(2024, 7, 23).unwrap();
let g_time = NaiveTime::from_hms_opt(15, 30, 45).unwrap();
let g_dt = NaiveDateTime::new(g_date, g_time); // Gregorian: 2024-07-23 15:30:45

// Convert to ParsiDateTime
let pd_dt_result = ParsiDateTime::from_gregorian(g_dt);
assert!(pd_dt_result.is_ok());
let pd_dt = pd_dt_result.unwrap();

// Verify the Persian date and time components
// Expected Persian date: 1403-05-02 (Mordad 2nd, 1403)
assert_eq!(pd_dt.date(), ParsiDate::new(1403, 5, 2).unwrap());
assert_eq!(pd_dt.hour(), 15);
assert_eq!(pd_dt.minute(), 30);
assert_eq!(pd_dt.second(), 45);


// --- Example 2: Nanosecond Truncation ---
// Gregorian datetime with nanoseconds: March 21, 2023, 00:00:01.123456789
// This corresponds to the start of the Persian year 1402.
let g_dt_nano = NaiveDate::from_ymd_opt(2023, 3, 21).unwrap()
                 .and_hms_nano_opt(0, 0, 1, 123_456_789).unwrap();

// Convert to ParsiDateTime
let pd_dt_nano_result = ParsiDateTime::from_gregorian(g_dt_nano);
assert!(pd_dt_nano_result.is_ok());
let pd_dt_nano = pd_dt_nano_result.unwrap();

// Verify the components - nanoseconds should be lost
assert_eq!(pd_dt_nano.date(), ParsiDate::new(1402, 1, 1).unwrap()); // Farvardin 1st, 1402
assert_eq!(pd_dt_nano.hour(), 0);
assert_eq!(pd_dt_nano.minute(), 0);
assert_eq!(pd_dt_nano.second(), 1); // Seconds are kept, nanoseconds are truncated


// --- Example 3: Date Before Persian Epoch (Error Case) ---
// Define a Gregorian date well before the Persian epoch (~622 CE)
let g_dt_early = NaiveDate::from_ymd_opt(600, 1, 1).unwrap()
                  .and_hms_opt(0, 0, 0).unwrap(); // January 1st, 600 CE

// Attempt conversion
let result_early = ParsiDateTime::from_gregorian(g_dt_early);

// Expect an error because the date is out of the convertible range
assert!(result_early.is_err());
assert_eq!(result_early, Err(DateError::GregorianConversionError));