Skip to content
Permalink
Browse files

Early date format checking.

  • Loading branch information...
Raymanns committed Aug 3, 2018
1 parent c6129af commit 2d9feb86ce6ce3a6e2a77605cb1cb4f403e105b2
Showing with 69 additions and 17 deletions.
  1. +1 −0 .gitignore
  2. +0 −6 src/bin/main.rs
  3. +1 −1 src/check/mod.rs
  4. +55 −4 src/check/post.rs
  5. +11 −6 src/readstat/handler.rs
  6. +1 −0 src/report/mod.rs
@@ -3,6 +3,7 @@
**/*.rs.bk
output.json
index.html
*scratch*

# Created by https://www.gitignore.io/api/vim,emacs

@@ -8,8 +8,6 @@ extern crate toml;
use qamd::readstat::read::read;
use qamd::config::{ Config, Valid };
use qamd::html::to_html;
// use qamd::config::{ VariableConfig, ValueConfig, Setting, Level };
// use qamd::report::Report;

use std::io;
use std::io::prelude::*;
@@ -88,12 +86,8 @@ fn main() {
_ => false,
};

// println!("file_path: {}\nconfig_path: {}\nlocators: {}", file_path, config_path, include_locators);

match parse_config(&config_path) {
Ok(ref mut config) => {
//println!("Config: {:#?}", config);

config.include_locators = override_config(config.include_locators,
include_locators);
config.progress = override_config(config.progress,
@@ -48,6 +48,6 @@ impl fmt::Debug for Check {
pub fn contains(string: &str, patterns: &Vec<String>) -> bool {
patterns.iter()
.map(|p| string.contains(p))
.fold(false, |a, b| a || b)
.fold(false, |a, b| { a || b })
}

@@ -3,15 +3,61 @@ use readstat::context::Context;
use config::Config;
use report::{ Report, Status, Locator };
use report::missing::Missing;
use check::PostCheckFn;
use check::{ PostCheckFn, contains };

/// Returns a vec of the functions provided by this module
pub fn register() -> Vec<PostCheckFn> {
vec!(primary_variable,
date_variables,
system_missing_over_threshold,
variables_with_unique_values)
}

fn date_variables(context: &Context,
_config: &Config,
_report: &mut Report) {
// refer here for the docs on the date format. ReadStat internally
// attempts to treat data as-if it were just Stata.
// https://www.stata.com/help.cgi?datetime_display_formats

for variable in context.variables.iter() {
// println!("{:#?}", variable.value_format);
let date_time_specifiers = vec!(
// date
"JJJ", // Day within year (001 - 366)
"jjj", // Day within year (1 - 366)
"DD", // Day within month (01 - 31)
"dd", // Day within month (1 - 31)
"DAYNAME", // day of week Sunday, Monday, ... (aligned)
"Dayname", // day of week Sunday, Monday, ... (unaligned)
"Day", // day of week Sun, Mon, ...
"Da", // day of week Su, Mo, ...
"day", // day of week sun, mon, ...
"da", //day of week su, mo, ...
// time
"HH", // hour 00 - 23
"Hh", // hour 00 - 12
"hH", // hour 0 - 23
"hh", // hour 0 - 12
"MM", // minute 00 - 59
"mm", // minute 0 - 59
"SS", // second 00 - 60 (sic, due to leap seconds)
"ss", // second 0 - 60 (sic, due to leap seconds)
".s", // tenths .0 - .9
".ss", // hundredths .00 - .99
".sss", // thousandths .000 - .999
"Y",
"y",
).iter().map(|s| s.to_string()).collect();

if contains(&variable.value_format, &date_time_specifiers) {
println!("variable {} is a date! : {}",
variable.name,
variable.value_format);
}
}
}

/// Count the number of cases using the provided primary variable_count
fn primary_variable(context: &Context,
config: &Config,
@@ -21,7 +67,8 @@ fn primary_variable(context: &Context,
report.metadata.case_count = Some(0);
}

if let Some((_variable, map)) = context.frequency_table.iter().find(|(variable, _)| {
if let Some((_variable, map)) = context.frequency_table
.iter().find(|(variable, _)| {
variable.name == primary_variable.setting
}) {
// report count of distinct cases for this variable
@@ -66,7 +113,10 @@ fn system_missing_over_threshold(context: &Context,

// compare with config threhold
// and increment pass/fail
if let Some((_, count)) = map.iter().find(|(value, _)| value.missing == Missing::SYSTEM_MISSING) {
if let Some((_, count)) = map
.iter().find(|(value, _)| {
value.missing == Missing::SYSTEM_MISSING
}) {
let sys_miss = (*count as f32 / sum as f32) * 100.0;
if sys_miss > setting.setting as f32 {
status.fail += 1;
@@ -90,7 +140,8 @@ fn variables_with_unique_values(context: &Context,
include_check!(report.summary.variables_with_unique_values,
"Detects values as outliers if they unique.");

if let Some(ref mut status) = report.summary.variables_with_unique_values {
if let Some(ref mut status) = report.summary
.variables_with_unique_values {
for (variable, map) in context.frequency_table.iter() {
if let Some(_) = map.iter().find(|(_value, occ)| {
*occ <= &setting.setting
@@ -1,9 +1,7 @@

//use report::Report;
use report::{ Value, Variable };
use report::missing::Missing;
use report::anyvalue::AnyValue;
//use check::Check;

use readstat::bindings::*;
use readstat::context::Context;
@@ -50,17 +48,23 @@ pub unsafe extern "C" fn metadata_handler(metadata: *mut readstat_metadata_t,

/// Variable callback
pub unsafe extern "C" fn variable_handler(index: c_int,
variable: *mut readstat_variable_t,
val_labels: *const c_char,
ctx: *mut c_void) -> c_int {
variable: *mut readstat_variable_t,
val_labels: *const c_char,
ctx: *mut c_void) -> c_int {
let context = ctx as *mut Context;

let variable_name = ptr_to_str!(readstat_variable_get_name(variable));

let label = if readstat_variable_get_label(variable) != ptr::null() {
ptr_to_str!(readstat_variable_get_label(variable))
} else {
"".to_string()
String::new()
};

let value_format = if readstat_variable_get_format(variable) != ptr::null() {
ptr_to_str!(readstat_variable_get_format(variable))
} else {
String::new()
};

let value_labels = if val_labels != ptr::null() {
@@ -74,6 +78,7 @@ pub unsafe extern "C" fn variable_handler(index: c_int,
index: index as i32 + 1,
name: variable_name,
label: label,
value_format: value_format,
value_labels: value_labels,
};

@@ -173,6 +173,7 @@ pub struct Variable {
pub index: i32,
pub name: String,
pub label: String,
pub value_format: String,
pub value_labels: String,
}

0 comments on commit 2d9feb8

Please sign in to comment.
You can’t perform that action at this time.