Skip to content

Commit

Permalink
refactor: Move Date and Time Formatter checker to parser package
Browse files Browse the repository at this point in the history
  • Loading branch information
AmrDeveloper committed May 25, 2024
1 parent 7910b2f commit 231d59f
Show file tree
Hide file tree
Showing 4 changed files with 84 additions and 84 deletions.
81 changes: 0 additions & 81 deletions crates/gitql-ast/src/date_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -191,84 +191,3 @@ pub fn time_stamp_from_year_and_day(year: i32, day_of_year: u32) -> i64 {
let datetime = date.and_hms_opt(0, 0, 0).unwrap();
Utc.from_utc_datetime(&datetime).timestamp()
}

/// Check if String literal is matching SQL time format: HH:MM:SS or HH:MM:SS.SSS
pub fn is_valid_time_format(time_str: &str) -> bool {
// Check length of the string
if !(8..=12).contains(&time_str.len()) {
return false;
}

// Split the string into hours, minutes, seconds, and optional milliseconds
let parts: Vec<&str> = time_str.split(':').collect();
if parts.len() < 3 || parts.len() > 4 {
return false;
}

// Extract hours, minutes, seconds, and optionally milliseconds
let hours = parts[0].parse::<u32>().ok();
let minutes = parts[1].parse::<u32>().ok();
let seconds_parts: Vec<&str> = parts[2].split('.').collect();
let seconds = seconds_parts[0].parse::<u32>().ok();
let milliseconds = if seconds_parts.len() == 2 {
seconds_parts[1].parse::<u32>().ok()
} else {
Some(0)
};

// Validate the parsed values
hours.is_some()
&& minutes.is_some()
&& seconds.is_some()
&& milliseconds.is_some()
&& hours.unwrap() < 24
&& minutes.unwrap() < 60
&& seconds.unwrap() < 60
&& milliseconds.unwrap() < 1000
}

/// Check if String literal is matching SQL Date format: YYYY-MM-DD
pub fn is_valid_date_format(date_str: &str) -> bool {
// Check length of the string
if date_str.len() != 10 {
return false;
}

// Split the string into year, month, and day
let parts: Vec<&str> = date_str.split('-').collect();
if parts.len() != 3 {
return false;
}

// Extract year, month, and day
let year = parts[0].parse::<u32>().ok();
let month = parts[1].parse::<u32>().ok();
let day = parts[2].parse::<u32>().ok();

// Validate the parsed values
year.is_some()
&& month.is_some()
&& day.is_some()
&& year.unwrap() >= 1
&& month.unwrap() >= 1
&& month.unwrap() <= 12
&& day.unwrap() >= 1
&& day.unwrap() <= 31
}

/// Check if String literal is matching SQL Date format: YYYY-MM-DD HH:MM:SS or YYYY-MM-DD HH:MM:SS.SSS
pub fn is_valid_datetime_format(datetime_str: &str) -> bool {
// Check length of the string
if !(19..=23).contains(&datetime_str.len()) {
return false;
}

// Split the string into date and time components
let parts: Vec<&str> = datetime_str.split_whitespace().collect();
if parts.len() != 2 {
return false;
}

// Check the validity of date and time components
is_valid_date_format(parts[0]) && is_valid_time_format(parts[1])
}
80 changes: 80 additions & 0 deletions crates/gitql-parser/src/format_checker.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
/// Check if String literal is matching SQL time format: HH:MM:SS or HH:MM:SS.SSS
pub fn is_valid_time_format(time_str: &str) -> bool {
// Check length of the string
if !(8..=12).contains(&time_str.len()) {
return false;
}

// Split the string into hours, minutes, seconds, and optional milliseconds
let parts: Vec<&str> = time_str.split(':').collect();
if parts.len() < 3 || parts.len() > 4 {
return false;
}

// Extract hours, minutes, seconds, and optionally milliseconds
let hours = parts[0].parse::<u32>().ok();
let minutes = parts[1].parse::<u32>().ok();
let seconds_parts: Vec<&str> = parts[2].split('.').collect();
let seconds = seconds_parts[0].parse::<u32>().ok();
let milliseconds = if seconds_parts.len() == 2 {
seconds_parts[1].parse::<u32>().ok()
} else {
Some(0)
};

// Validate the parsed values
hours.is_some()
&& minutes.is_some()
&& seconds.is_some()
&& milliseconds.is_some()
&& hours.unwrap() < 24
&& minutes.unwrap() < 60
&& seconds.unwrap() < 60
&& milliseconds.unwrap() < 1000
}

/// Check if String literal is matching SQL Date format: YYYY-MM-DD
pub fn is_valid_date_format(date_str: &str) -> bool {
// Check length of the string
if date_str.len() != 10 {
return false;
}

// Split the string into year, month, and day
let parts: Vec<&str> = date_str.split('-').collect();
if parts.len() != 3 {
return false;
}

// Extract year, month, and day
let year = parts[0].parse::<u32>().ok();
let month = parts[1].parse::<u32>().ok();
let day = parts[2].parse::<u32>().ok();

// Validate the parsed values
year.is_some()
&& month.is_some()
&& day.is_some()
&& year.unwrap() >= 1
&& month.unwrap() >= 1
&& month.unwrap() <= 12
&& day.unwrap() >= 1
&& day.unwrap() <= 31
}

/// Check if String literal is matching SQL Date format: YYYY-MM-DD HH:MM:SS or YYYY-MM-DD HH:MM:SS.SSS
pub fn is_valid_datetime_format(datetime_str: &str) -> bool {
// Check length of the string
if !(19..=23).contains(&datetime_str.len()) {
return false;
}

// Split the string into date and time components
let parts: Vec<&str> = datetime_str.split_whitespace().collect();
if parts.len() != 2 {
return false;
}

// Check the validity of date and time components
is_valid_date_format(parts[0]) && is_valid_time_format(parts[1])
}
1 change: 1 addition & 0 deletions crates/gitql-parser/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
pub mod context;
pub mod diagnostic;
pub mod format_checker;
pub mod parser;
pub mod tokenizer;
pub mod type_checker;
6 changes: 3 additions & 3 deletions crates/gitql-parser/src/type_checker.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
use gitql_ast::date_utils::is_valid_date_format;
use gitql_ast::date_utils::is_valid_datetime_format;
use gitql_ast::date_utils::is_valid_time_format;
use gitql_ast::environment::Environment;
use gitql_ast::expression::Expression;
use gitql_ast::expression::ExpressionKind;
Expand All @@ -9,6 +6,9 @@ use gitql_ast::expression::StringValueType;
use gitql_ast::types::DataType;

use crate::diagnostic::Diagnostic;
use crate::format_checker::is_valid_date_format;
use crate::format_checker::is_valid_datetime_format;
use crate::format_checker::is_valid_time_format;
use crate::tokenizer::Location;

/// The return result after performing types checking with implicit casting option
Expand Down

0 comments on commit 231d59f

Please sign in to comment.