Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Validate dates #59

Merged
merged 3 commits into from
Feb 18, 2014
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,7 @@ Supported constraints:
* `type` -- specifies an XML Schema data type. Values of the column must be a valid value for that type
* `minimum` -- specify a minimum range for values, the value will be parsed as specified by `type`
* `maximum` -- specify a maximum range for values, the value will be parsed as specified by `type`
* `datePattern` -- specify a `strftime` compatible date pattern to be used when parsing date values and min/max constraints

Supported data types (this is still a work in progress):

Expand All @@ -180,6 +181,11 @@ Supported data types (this is still a work in progress):
* Positive Integer -- `http://www.w3.org/2001/XMLSchema#positiveInteger`
* Non Negative Integer -- `http://www.w3.org/2001/XMLSchema#nonNegativeInteger`
* Negative Integer -- `http://www.w3.org/2001/XMLSchema#negativeInteger`
* Date -- `http://www.w3.org/2001/XMLSchema#date`
* Date Time -- `http://www.w3.org/2001/XMLSchema#dateTime`
* Year -- `http://www.w3.org/2001/XMLSchema#gYear`
* Year Month -- `http://www.w3.org/2001/XMLSchema#gYearMonth`
* Time -- `http://www.w3.org/2001/XMLSchema#time`

Schema validation provides some additional types of error and warning messages:

Expand Down
53 changes: 42 additions & 11 deletions lib/csvlint/field.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
require 'set'
require 'date'

module Csvlint

Expand All @@ -8,39 +9,69 @@ class Field
attr_reader :name, :constraints, :title, :description

TYPE_VALIDATIONS = {
'http://www.w3.org/2001/XMLSchema#int' => lambda { |value| Integer value },
'http://www.w3.org/2001/XMLSchema#float' => lambda { |value| Float value },
'http://www.w3.org/2001/XMLSchema#double' => lambda { |value| Float value },
'http://www.w3.org/2001/XMLSchema#anyURI' => lambda do |value|
'http://www.w3.org/2001/XMLSchema#int' => lambda { |value, constraints| Integer value },
'http://www.w3.org/2001/XMLSchema#float' => lambda { |value, constraints| Float value },
'http://www.w3.org/2001/XMLSchema#double' => lambda { |value, constraints| Float value },
'http://www.w3.org/2001/XMLSchema#anyURI' => lambda do |value, constraints|
u = URI.parse value
raise ArgumentError unless u.kind_of?(URI::HTTP) || u.kind_of?(URI::HTTPS)
u
end,
'http://www.w3.org/2001/XMLSchema#boolean' => lambda do |value|
'http://www.w3.org/2001/XMLSchema#boolean' => lambda do |value, constraints|
return true if ['true', '1'].include? value
return false if ['false', '0'].include? value
raise ArgumentError
end,
'http://www.w3.org/2001/XMLSchema#nonPositiveInteger' => lambda do |value|
'http://www.w3.org/2001/XMLSchema#nonPositiveInteger' => lambda do |value, constraints|
i = Integer value
raise ArgumentError unless i <= 0
i
end,
'http://www.w3.org/2001/XMLSchema#negativeInteger' => lambda do |value|
'http://www.w3.org/2001/XMLSchema#negativeInteger' => lambda do |value, constraints|
i = Integer value
raise ArgumentError unless i < 0
i
end,
'http://www.w3.org/2001/XMLSchema#nonNegativeInteger' => lambda do |value|
'http://www.w3.org/2001/XMLSchema#nonNegativeInteger' => lambda do |value, constraints|
i = Integer value
raise ArgumentError unless i >= 0
i
end,
'http://www.w3.org/2001/XMLSchema#positiveInteger' => lambda do |value|
'http://www.w3.org/2001/XMLSchema#positiveInteger' => lambda do |value, constraints|
i = Integer value
raise ArgumentError unless i > 0
i
end
end,
'http://www.w3.org/2001/XMLSchema#dateTime' => lambda do |value, constraints|
date_pattern = constraints["datePattern"] || "%Y-%m-%dT%H:%M:%SZ"
d = DateTime.strptime(value, date_pattern)
raise ArgumentError unless d.strftime(date_pattern) == value
d
end,
'http://www.w3.org/2001/XMLSchema#date' => lambda do |value, constraints|
date_pattern = constraints["datePattern"] || "%Y-%m-%d"
d = Date.strptime(value, date_pattern)
raise ArgumentError unless d.strftime(date_pattern) == value
d
end,
'http://www.w3.org/2001/XMLSchema#time' => lambda do |value, constraints|
date_pattern = constraints["datePattern"] || "%H:%M:%S"
d = DateTime.strptime(value, date_pattern)
raise ArgumentError unless d.strftime(date_pattern) == value
d
end,
'http://www.w3.org/2001/XMLSchema#gYear' => lambda do |value, constraints|
date_pattern = constraints["datePattern"] || "%Y"
d = Date.strptime(value, date_pattern)
raise ArgumentError unless d.strftime(date_pattern) == value
d
end,
'http://www.w3.org/2001/XMLSchema#gYearMonth' => lambda do |value, constraints|
date_pattern = constraints["datePattern"] || "%Y-%m"
d = Date.strptime(value, date_pattern)
raise ArgumentError unless d.strftime(date_pattern) == value
d
end
}

def initialize(name, constraints={}, title=nil, description=nil)
Expand Down Expand Up @@ -121,7 +152,7 @@ def convert_to_type(value)
tv = TYPE_VALIDATIONS[constraints["type"]]
if tv
begin
parsed = tv.call value
parsed = tv.call value, constraints
rescue ArgumentError
end
end
Expand Down
69 changes: 67 additions & 2 deletions spec/field_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -141,9 +141,74 @@
expect( field.validate_column("41")).to be(false)
expect( field.errors.first.type ).to eql(:out_of_range)

end
end

context "when validating dates" do
it "should validate a date time" do
field = Csvlint::Field.new("test", {
"type" => "http://www.w3.org/2001/XMLSchema#dateTime"
})
expect( field.validate_column("2014-02-17T11:09:00Z")).to be(true)
expect( field.validate_column("invalid-date")).to be(false)
expect( field.validate_column("2014-02-17")).to be(false)
end
it "should validate a date" do
field = Csvlint::Field.new("test", {
"type" => "http://www.w3.org/2001/XMLSchema#date"
})
expect( field.validate_column("2014-02-17T11:09:00Z")).to be(false)
expect( field.validate_column("invalid-date")).to be(false)
expect( field.validate_column("2014-02-17")).to be(true)
end
it "should validate a time" do
field = Csvlint::Field.new("test", {
"type" => "http://www.w3.org/2001/XMLSchema#time"
})
expect( field.validate_column("11:09:00")).to be(true)
expect( field.validate_column("2014-02-17T11:09:00Z")).to be(false)
expect( field.validate_column("not-a-time")).to be(false)
expect( field.validate_column("27:97:00")).to be(false)
end
it "should validate a year" do
field = Csvlint::Field.new("test", {
"type" => "http://www.w3.org/2001/XMLSchema#gYear"
})
expect( field.validate_column("1999")).to be(true)
expect( field.validate_column("2525")).to be(true)
expect( field.validate_column("0001")).to be(true)
expect( field.validate_column("2014-02-17T11:09:00Z")).to be(false)
expect( field.validate_column("not-a-time")).to be(false)
expect( field.validate_column("27:97:00")).to be(false)
end
it "should validate a year-month" do
field = Csvlint::Field.new("test", {
"type" => "http://www.w3.org/2001/XMLSchema#gYearMonth"
})
expect( field.validate_column("1999-12")).to be(true)
expect( field.validate_column("2525-01")).to be(true)
expect( field.validate_column("2014-02-17T11:09:00Z")).to be(false)
expect( field.validate_column("not-a-time")).to be(false)
expect( field.validate_column("27:97:00")).to be(false)
end
it "should allow user to specify custom date time pattern" do
field = Csvlint::Field.new("test", {
"type" => "http://www.w3.org/2001/XMLSchema#dateTime",
"datePattern" => "%Y-%m-%d %H:%M:%S"
})
expect( field.validate_column("1999-12-01 10:00:00")).to be(true)
expect( field.validate_column("invalid-date")).to be(false)
expect( field.validate_column("2014-02-17")).to be(false)
end
it "should allow user to compare dates" do
field = Csvlint::Field.new("test", {
"type" => "http://www.w3.org/2001/XMLSchema#dateTime",
"datePattern" => "%Y-%m-%d %H:%M:%S",
"minimum" => "1990-01-01 10:00:00"
})
expect( field.validate_column("1999-12-01 10:00:00")).to be(true)
expect( field.validate_column("1989-12-01 10:00:00")).to be(false)
end


end
end
end