├── .coveralls.yml
├── .gitignore
├── .travis.yml
├── LICENSE
├── README.md
├── rockspecs
├── valua-0.2.1-1.rockspec
├── valua-0.2.1-2.rockspec
├── valua-0.2.2-1.rockspec
├── valua-0.2.2-2.rockspec
├── valua-0.2.2-3.rockspec
├── valua-0.3-1.rockspec
└── valua-current-1.rockspec
├── valua-test.lua
└── valua.lua
/.coveralls.yml:
--------------------------------------------------------------------------------
1 | service_name: travis-pro
2 | repo_token: GmAUEIWICvwIaQh2aHQSuIhnZO4wJ81Kb
3 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | luacov.report.out
2 | luacov.stats.out
3 |
4 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: python
2 | sudo: false
3 |
4 | env:
5 | - LUA="lua 5.1" COMPAT=default
6 | - LUA="lua 5.2" COMPAT=default
7 | - LUA="lua 5.2" COMPAT=none
8 | - LUA="lua 5.3" COMPAT=default
9 | - LUA="lua 5.3" COMPAT=none
10 | - LUA="lua 5.3" COMPAT=default CFLAGS="-DLUA_NOCVTN2S -DLUA_NOCVTS2N"
11 | - LUA="luajit 2.0" COMPAT=none
12 | - LUA="luajit 2.0" COMPAT=all
13 | - LUA="luajit 2.1" COMPAT=none
14 | - LUA="luajit 2.1" COMPAT=all
15 |
16 | before_install:
17 | - pip install hererocks
18 | - hererocks HERE --$LUA --compat $COMPAT --cflags="$CFLAGS" --no-readline --luarocks latest --verbose
19 | - hererocks HERE --show
20 | - source HERE/bin/activate
21 |
22 | install:
23 | - luarocks install luacheck
24 | - luarocks install luacov-coveralls
25 |
26 | script:
27 | - luacheck --codes --std=max *.lua --ignore 211/_ENV
28 | - lua valua-test.lua
29 |
30 | after_success:
31 | - lua -lluacov valua-test.lua
32 | - luacov-coveralls
33 |
34 | notifications:
35 | email:
36 | on_success: change
37 | on_failure: always
38 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2014 Etiene Dalcol
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ## Valua - Validation for Lua
2 |
3 | [](https://travis-ci.org/sailorproject/valua)
4 | [](https://coveralls.io/github/sailorproject/valua?branch=master)
5 |
6 | A module for making chained validations. Create your objects, append your tests, use and reuse it!
7 |
8 | Originally bundled with Sailor MVC Web Framework, now released as a separated module.
9 | https://github.com/Etiene/sailor
10 |
11 | This module provides tools for validating values, very useful in forms, but also usable elsewhere. It works in appended chains. Create a new validation object and start chaining your test functions. If your value fails a test, it breaks the chain and does not evaluate the rest of it. It returns a boolean and an error string (nil when tests succeeded).
12 |
13 | Valua is also available through luarocks
14 | ````
15 | luarocks install valua
16 | ````
17 |
18 | #### Usage
19 | Example 1 - Just create, chain and use:
20 | ```lua
21 | valua:new().type("string").len(3,5)("test string!") -- false, "should have 3-5 characters"
22 | ```
23 | Example 2 - Create, chain and later use it multiple times:
24 | ```lua
25 | local reusable_validation = valua:new().type("string").len(3,5)
26 | reusable_validation("test string!") -- false, "should have 3-5 characters"
27 | reusable_validation("test!") -- true
28 | ```
29 |
30 | #### Current validation functions
31 |
32 | * alnum() -
33 | Checks if string is alphanumeric.
34 | * boolean() -
35 | Checks if value is a boolean.
36 | * compare(another_value) -
37 | Checks if value is equal to another value.
38 | * contains(substr) -
39 | Checks if a string contains a substring.
40 | * date() or date(format) -
41 | Checks if a string is a valid date. Default format is UK (dd/mm/yyyy). Also checks for US and ISO formats.
42 | * email() -
43 | Checks if a string is a valid email address.
44 | * empty() -
45 | Checks if a value is empty.
46 | * integer() -
47 | Checks if a number is an integer;
48 | * in_list(list) -
49 | Checks if a value is inside an array.
50 | * len(min,max) -
51 | Checks if a string's length is between min and max.
52 | * match(pattern) -
53 | Checks if a string matches a given pattern.
54 | * max(n) -
55 | Checks if a number is equal or less than n.
56 | * min(n) -
57 | Checks if a number is equal or greater than n.
58 | * not_empty() -
59 | Checks if a value is not empty.
60 | * no_white() -
61 | Checks if a string contains no white spaces.
62 | * number() -
63 | Checks if a value is a number.
64 | * string() -
65 | Checks if a value is a string.
66 | * type(t) -
67 | Checks if a value is of type t.
68 | * optional(t) -
69 | If value is `nil` it would be accepted. If it's not `nil` it would be processed with other chained validation functions as usually done.
70 |
71 |
72 | Copyright (c) 2014 Etiene Dalcol
73 |
74 | http://etiene.net
75 |
76 | http://twitter.com/etiene_d
77 |
78 | License: MIT
79 |
80 |
81 |
82 | Inspired by Respect Validation for PHP
83 |
84 | https://github.com/Respect/Validation
85 |
--------------------------------------------------------------------------------
/rockspecs/valua-0.2.1-1.rockspec:
--------------------------------------------------------------------------------
1 | package = "Valua"
2 | version = "0.2.1-1"
3 | source = {
4 | url = "git://github.com/Etiene/valua",
5 | tag = "v0.2.1"
6 | }
7 | description = {
8 | summary = "Validation for Lua!",
9 | detailed = [[
10 | This module provides tools for validating values, very useful in forms, but also usable elsewhere. It works in appended chains. Create a new validation object and start chaining your test functions.
11 | ]],
12 | homepage = "https://github.com/Etiene/valua",
13 | license = "MIT"
14 | }
15 | dependencies = {
16 | "lua >= 5.1, < 5.3"
17 | }
18 | build = {
19 | type = "builtin",
20 | modules = {
21 | ["valua"] = "valua.lua",
22 | }
23 | }
--------------------------------------------------------------------------------
/rockspecs/valua-0.2.1-2.rockspec:
--------------------------------------------------------------------------------
1 | package = "Valua"
2 | version = "0.2.1-1"
3 | source = {
4 | url = "git://github.com/Etiene/valua",
5 | tag = "v0.2.1"
6 | }
7 | description = {
8 | summary = "Validation for Lua!",
9 | detailed = [[
10 | This module provides tools for validating values, very useful in forms, but also usable elsewhere. It works in appended chains. Create a new validation object and start chaining your test functions.
11 | ]],
12 | homepage = "https://github.com/Etiene/valua",
13 | license = "MIT"
14 | }
15 | dependencies = {
16 | "lua >= 5.1, < 5.4"
17 | }
18 | build = {
19 | type = "builtin",
20 | modules = {
21 | ["valua"] = "valua.lua",
22 | }
23 | }
--------------------------------------------------------------------------------
/rockspecs/valua-0.2.2-1.rockspec:
--------------------------------------------------------------------------------
1 | package = "valua"
2 | version = "0.2.2-1"
3 | source = {
4 | url = "https://github.com/Etiene/valua/releases/download/0.2.2/valua-0.2.2.tar.gz",
5 | tag = "valua-0.2.2"
6 | }
7 | description = {
8 | summary = "Validation for Lua!",
9 | detailed = [[
10 | This module provides tools for validating values, very useful in forms, but also usable elsewhere. It works in appended chains. Create a new validation object and start chaining your test functions.
11 | ]],
12 | homepage = "https://github.com/Etiene/valua",
13 | license = "MIT"
14 | }
15 | dependencies = {
16 | "lua >= 5.1, < 5.3"
17 | }
18 | build = {
19 | type = "none",
20 | install ={
21 | lua ={
22 | valua = "valua.lua"
23 | }
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/rockspecs/valua-0.2.2-2.rockspec:
--------------------------------------------------------------------------------
1 | package = "valua"
2 | version = "0.2.2-2"
3 | source = {
4 | url = "git://github.com/Etiene/valua",
5 | tag = "0.2.2"
6 | }
7 | description = {
8 | summary = "Validation for Lua!",
9 | detailed = [[
10 | This module provides tools for validating values, very useful in forms, but also usable elsewhere. It works in appended chains. Create a new validation object and start chaining your test functions.
11 | ]],
12 | homepage = "https://github.com/Etiene/valua",
13 | license = "MIT"
14 | }
15 | dependencies = {
16 | "lua >= 5.1, < 5.4"
17 | }
18 | build = {
19 | type = "none",
20 | install ={
21 | lua ={
22 | valua = "valua.lua"
23 | }
24 | }
25 | }
--------------------------------------------------------------------------------
/rockspecs/valua-0.2.2-3.rockspec:
--------------------------------------------------------------------------------
1 | package = "valua"
2 | version = "0.2.2-3"
3 | source = {
4 | url = "https://github.com/sailorproject/valua/releases/download/0.2.2/valua-0.2.2.tar.gz",
5 | tag = "0.2.2"
6 | }
7 | description = {
8 | summary = "Validation for Lua!",
9 | detailed = [[
10 | This module provides tools for validating values, very useful in forms, but also usable elsewhere. It works in appended chains. Create a new validation object and start chaining your test functions.
11 | ]],
12 | homepage = "https://github.com/sailorproject/valua",
13 | license = "MIT"
14 | }
15 | dependencies = {
16 | "lua >= 5.1, < 5.4"
17 | }
18 | build = {
19 | type = "none",
20 | install ={
21 | lua ={
22 | valua = "valua.lua"
23 | }
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/rockspecs/valua-0.3-1.rockspec:
--------------------------------------------------------------------------------
1 | package = "valua"
2 | version = "0.3-1"
3 | source = {
4 | url = "git://github.com/sailorproject/valua",
5 | tag = "0.3"
6 | }
7 | description = {
8 | summary = "Validation for Lua!",
9 | detailed = [[
10 | This module provides tools for validating values, very useful in forms, but also usable elsewhere. It works in appended chains. Create a new validation object and start chaining your test functions.
11 | ]],
12 | homepage = "https://github.com/sailorproject/valua",
13 | license = "MIT"
14 | }
15 | dependencies = {
16 | "lua >= 5.1, < 5.4"
17 | }
18 | build = {
19 | type = "none",
20 | install ={
21 | lua ={
22 | valua = "valua.lua"
23 | }
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/rockspecs/valua-current-1.rockspec:
--------------------------------------------------------------------------------
1 | package = "valua"
2 | version = "current-1"
3 | source = {
4 | url = "git://github.com/sailorproject/sailor",
5 | }
6 | description = {
7 | summary = "Validation for Lua!",
8 | detailed = [[
9 | This module provides tools for validating values, very useful in forms, but also usable elsewhere. It works in appended chains. Create a new validation object and start chaining your test functions.
10 | ]],
11 | homepage = "https://github.com/sailorproject/valua",
12 | license = "MIT"
13 | }
14 | dependencies = {
15 | "lua >= 5.1, < 5.5",
16 | "busted >= 2.0.rc10",
17 | }
18 | build = {
19 | type = "builtin",
20 | modules = {
21 | valua = "valua.lua"
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/valua-test.lua:
--------------------------------------------------------------------------------
1 | local v = require "valua"
2 | local passing = true
3 |
4 | local function check(val_test, test_value, expected, n)
5 | local res,err = val_test(test_value)
6 | local msg = "Validation "..tostring(n).." "
7 |
8 | if res == expected then
9 | msg = msg.. "succeeded"
10 | else
11 | passing = false
12 | msg = msg.. " \27[31m FAILED \27[0m"
13 | end
14 | msg = msg.." on '"..(tostring(test_value)).."'. Expected: "..tostring(expected)..", result: "..tostring(res)..". "
15 | print(msg)
16 | if err then print("\tTest Msg: value "..(err or "")) end
17 | end
18 |
19 | local test_values = {
20 | [1] = "test string!",
21 | [2] = "hey",
22 | [3] = "",
23 | [4] = nil,
24 | [5] = true,
25 | [6] = 42,
26 | [7] = 1337,
27 | [8] = '26/10/1980',
28 | [9] = '10-26-1980',
29 | [10] = '29.02.2014',
30 | [11] = '29/02/2016',
31 | [12] = 'a@a.com',
32 | [13] = 'asd123',
33 | [14] = 5.7,
34 | [15] = {},
35 | [16] = {3,46},
36 | [17] = "",
37 | [18] = "test-123_maria.2@newdomain.wow.movie",
38 | [19] = "10/06/1980 10:32:10"
39 | }
40 |
41 | local tests = {
42 | {v:new().type("string").len(3,5), {1,false}},
43 | {v:new().type("number").len(3,5), {1,false}},
44 | {v:new().type("table").empty(), {15,true, 16,false, 1,false}},
45 | -- require('mobdebug').start('127.0.0.1')
46 | {v:new().not_empty(), {2,true, 3,false, 4,false, 16,true, 5,true, 6,true}},
47 | {v:new().len(2,10), {2,true}},
48 | {v:new().type("number"), {2,false}},
49 | {v:new().empty(), {3,true, 4,true, 5,false, 6,false}},
50 | {v:new().boolean(), {1,false, 5,true}},
51 | {v:new().compare("hey"), {1,false, 2,true}},
52 | {v:new().number().min(45), {2,false, 6,false, 7,true, 4,false}},
53 | {v:new().number().max(1009), {7,false, 6,true}},
54 | {v:new().date(), {9,false, 10,false, 11,true, 8,true}},
55 | {v:new().date('us'), {8,false, 9,true}},
56 | {v:new().email(), {13,false, 12,true, 17,false, 18,true}},
57 | {v:new().in_list({"hey",42}), {12,false, 6,true, 2,true}},
58 | {v:new().match("^%d+%p%d+%p%d%d%d%d$"), {1,false, 8,true}},
59 | {v:new().alnum(), {8,false, 13,true}},
60 | {v:new().integer(), {14,false, 6,true,}},
61 | {v:new().string(), {14,false, 1,true, 4,false}},
62 | {v:new().string().alnum(), {6,false}},
63 | {v:new().contains(" "), {2,false, 1,true}},
64 | {v:new().no_white(), {1,false, 2,true}},
65 | {v:new().datetime(), {19,true, 9,false}},
66 | {v:new().number().min(45).optional(), {2,false, 6,false, 7,true, 4,true}},
67 | {v:new().number().optional().min(45), {2,false, 6,false, 7,true, 4,true}},
68 | {v:new().string().optional(), {14,false, 1,true, 4,true}},
69 | }
70 |
71 | for n,t in ipairs(tests) do
72 | for i = 1, #t[2], 2 do
73 | check(t[1],test_values[t[2][i]],t[2][i+1],n)
74 | end
75 | end
76 |
77 | if not passing then
78 | error('Tests are failing')
79 | end
80 |
--------------------------------------------------------------------------------
/valua.lua:
--------------------------------------------------------------------------------
1 | -- Valua 0.2.1
2 | -- Copyright (c) 2014 Etiene Dalcol
3 | -- License: MIT
4 | --
5 | -- Originally bundled with Sailor MVC Web Framework, now released as a separated module.
6 | -- http://sailorproject.org
7 | --
8 | -- This module provides tools for validating values, very useful in forms, but also usable elsewhere.
9 | -- It works in appended chains. Create a new validation object and start chaining your test functions.
10 | -- If your value fails a test, it breaks the chain and does not evaluate the rest of it.
11 | -- It returns a boolean and an error string (nil when tests succeeded)
12 | --
13 | -- Example 1 - Just create, chain and use:
14 | -- valua:new().type("string").len(3,5)("test string!") -- false, "should have 3-5 characters"
15 | --
16 | -- Example 2 - Create, chain and later use it multiple times:
17 | -- local reusable_validation = valua:new().type("string").len(3,5)
18 | -- reusable_validation("test string!") -- false, "should have 3-5 characters"
19 | -- reusable_validation("test!") -- true
20 | --
21 |
22 | local tinsert,setmetatable,len,match = table.insert,setmetatable,string.len,string.match
23 | local tonumber,tostring = tonumber,tostring
24 | local next,type,floor,ipairs = next,type,math.floor, ipairs
25 | local unpack = unpack or table.unpack
26 | local pack = table.pack or function(...) return { n = select('#', ...), ... } end
27 |
28 | local _ENV = nil
29 |
30 | local valua = {}
31 |
32 | -- CORE
33 | -- Caution, this is confusing
34 |
35 | -- creates a new validation object, useful for reusable stuff and creating many validation tests at a time
36 | function valua:new(obj)
37 | obj = obj or {}
38 | setmetatable(obj,self)
39 | -- __index will be called always when chaining validation functions
40 | self.__index = function(t,k)
41 | --saves a function named _ with its args in a funcs table, to be used later when validating
42 | return function(...)
43 | local args = pack(...)
44 | if k == 'optional' then
45 | obj.allow_nil = true
46 | else
47 | local f = function(value) return valua['_'..k](value, unpack(args, 1, args.n)) end
48 | tinsert(t.funcs,f)
49 | end
50 | return t
51 | end
52 | end
53 |
54 | -- __call will run only when the value is validated
55 | self.__call = function(t,value)
56 | local res = true
57 | local err = nil
58 | local fres
59 |
60 | if value == nil and t.allow_nil then
61 | return res, err
62 | end
63 |
64 | -- iterates through all chained validations funcs that were packed, passing the value to be validated
65 | for _,f in ipairs(t.funcs) do
66 | fres,err = f(value)
67 | res = res and fres
68 | -- breaks the chain if a test fails
69 | if err then
70 | break
71 | end
72 | end
73 | -- boolean, error message or nil
74 | return res,err
75 | end
76 | obj.funcs = {}
77 | obj.allow_nil = false
78 | return obj
79 | end
80 | --
81 |
82 | -- VALIDATION FUNCS
83 | -- Add new funcs at will, they all should have the value to be validated as first parameter
84 | -- and their names must be preceded by '_'.
85 | -- For example, if you want to use .custom_val(42) on your validation chain, you need to create a
86 | -- function valua._custom_val(,). Just remember the value var will be known
87 | -- at the end of the chain and the other var, in this case, will receive '42'. You can add multiple other vars.
88 | -- These functions can be called directly (valua._len("test",2,5))in a non-chained and isolated way of life
89 | -- for quick stuff, but chaining is much cooler!
90 | -- Return false,'' if the value fails the test and simply true if it succeeds.
91 |
92 | -- aux funcs
93 | local function empty(v)
94 | return not v or (type(v)=='string' and len(v) == 0) or (type(v)=='table' and not next(v))
95 | end
96 | --
97 |
98 | -- String
99 | function valua._len(value,min,max)
100 | local l = len(value or '')
101 | if l < min or l > max then return false,"should have "..tostring(min).."-"..tostring(max).." characters" end
102 | return true
103 | end
104 |
105 | function valua._compare(value,another_value)
106 | if value ~= another_value then return false, "values are not equal" end
107 | return true
108 | end
109 |
110 | function valua._email(value)
111 | if not empty(value) and not value:match("^[%w+%.%-_]+@[%w+%.%-_]+%.%a%a+$") then
112 | return false, "is not a valid email address"
113 | end
114 | return true
115 | end
116 |
117 | function valua._match(value,pattern)
118 | if not empty(value) and not value:match(pattern) then return false, "does not match pattern" end
119 | return true
120 | end
121 |
122 | function valua._alnum(value)
123 | if not empty(value) and value:match("%W") then return false, "constains improper characters" end
124 | return true
125 | end
126 |
127 | function valua._contains(value,substr)
128 | if not empty(value) and not value:find(substr) then return false, "does not contain '"..substr.."'" end
129 | return true
130 | end
131 |
132 | function valua._no_white(value)
133 | if not empty(value) and value:find("%s") then return false, "must not contain white spaces" end
134 | return true
135 | end
136 | --
137 |
138 | -- Numbers
139 | function valua._min(value,n)
140 | if not empty(value) and value < n then return false,"must be greater than "..tostring(n) end
141 | return true
142 | end
143 |
144 | function valua._max(value,n)
145 | if not empty(value) and value > n then return false,"must not be greater than "..tostring(n) end
146 | return true
147 | end
148 |
149 | function valua._integer(value)
150 | if not empty(value) and floor(tonumber(value)) ~= tonumber(value) then return false, "must be an integer" end
151 | return true
152 | end
153 | --
154 |
155 | -- Date
156 |
157 | -- Check for a UK date pattern dd/mm/yyyy , dd-mm-yyyy, dd.mm.yyyy
158 | -- or US pattern mm/dd/yyyy, mm-dd-yyyy, mm.dd.yyyy
159 | -- or ISO pattern yyyy/mm/dd, yyyy-mm-dd, yyyy.mm.dd
160 | -- Default is UK
161 | function valua._date(value,format)
162 | local valid = true
163 | if (match(value, "^%d+%p%d+%p%d%d%d%d$")) then
164 | local d, m, y
165 | if format and format:lower() == 'us' then
166 | m, d, y = match(value, "(%d+)%p(%d+)%p(%d+)")
167 | elseif format and format:lower() == 'iso' then
168 | y, m, d = match(value, "(%d+)%p(%d+)%p(%d+)")
169 | else
170 | d, m, y = match(value, "(%d+)%p(%d+)%p(%d+)")
171 | end
172 | d, m, y = tonumber(d), tonumber(m), tonumber(y)
173 |
174 | local dm2 = d*m*m
175 | if d>31 or m>12 or dm2==116 or dm2==120 or dm2==124 or dm2==496 or dm2==1116 or dm2==2511 or dm2==3751 then
176 | -- invalid unless leap year
177 | if not (dm2==116 and (y%400 == 0 or (y%100 ~= 0 and y%4 == 0))) then
178 | valid = false
179 | end
180 | end
181 | else
182 | valid = false
183 | end
184 | if not valid then return false, "is not a valid date" end
185 | return true
186 | end
187 | --
188 |
189 | -- Datetime
190 |
191 | -- Check for a UK date pattern dd/mm/yyyy hh:mi:ss, dd-mm-yyyy, dd.mm.yyyy
192 | -- or US pattern mm/dd/yyyy, mm-dd-yyyy, mm.dd.yyyy
193 | -- or ISO pattern yyyy/mm/dd, yyyy-mm-dd, yyyy.mm.dd
194 | -- Default is UK
195 | function valua._datetime(value,format)
196 | local valid = true
197 | if (match(value, "^%d+%p%d+%p%d%d%d%d %d%d%p%d%d%p%d%d$")) then
198 | local d, m, y, hh, mm, ss
199 | if format and format:lower() == 'us' then
200 | m, d, y, hh, mm, ss = match(value, "(%d+)%p(%d+)%p(%d+) (%d%d)%p(%d%d)%p(%d%d)")
201 | elseif format and format:lower() == 'iso' then
202 | y, m, d, hh, mm, ss = match(value, "(%d+)%p(%d+)%p(%d+) (%d%d)%p(%d%d)%p(%d%d)")
203 | else
204 | d, m, y, hh, mm, ss = match(value, "(%d+)%p(%d+)%p(%d+) (%d%d)%p(%d%d)%p(%d%d)")
205 | end
206 | d, m, y, hh, mm, ss = tonumber(d), tonumber(m), tonumber(y), tonumber(hh), tonumber(mm), tonumber(ss)
207 |
208 | local dm2 = d*m*m
209 | if d>31 or m>12 or dm2==116 or dm2==120 or dm2==124 or dm2==496 or dm2==1116 or dm2==2511 or dm2==3751 then
210 | -- invalid unless leap year
211 | if not (dm2==116 and (y%400 == 0 or (y%100 ~= 0 and y%4 == 0))) then
212 | valid = false
213 | end
214 | end
215 |
216 | -- time validation
217 | if not (hh >= 0 and hh <= 24) then
218 | valid = false
219 | end
220 |
221 | if not (mm >= 0 and mm <= 60) then
222 | valid = false
223 | end
224 |
225 | if not (ss >= 0 and ss <= 60) then
226 | valid = false
227 | end
228 |
229 | else
230 | valid = false
231 | end
232 | if not valid then return false, "is not a valid datetime" end
233 | return true
234 | end
235 | --
236 |
237 | -- Abstract
238 | function valua._empty(value)
239 | if not empty(value) then return false,"must be empty" end
240 | return true
241 | end
242 |
243 | function valua._not_empty(value)
244 | if empty(value) then return false,"must not be empty" end
245 | return true
246 | end
247 |
248 | function valua._type(value,value_type)
249 | if type(value) ~= value_type then return false,"must be a "..value_type end
250 | return true
251 | end
252 |
253 | function valua._boolean(value)
254 | if type(value) ~= 'boolean' then return false,"must be a boolean" end
255 | return true
256 | end
257 |
258 | function valua._number(value)
259 | if type(value) ~= 'number' then return false,"must be a number" end
260 | return true
261 | end
262 |
263 | function valua._string(value)
264 | if type(value) ~= 'string' then return false,"must be a string" end
265 | return true
266 | end
267 |
268 | function valua._in_list(value,list)
269 | local valid = false
270 | for _,v in ipairs(list) do
271 | if value == v then
272 | valid = true
273 | break
274 | end
275 | end
276 | if not valid then return false,"is not in the list" end
277 | return true
278 | end
279 | --
280 |
281 | --
282 | return valua
283 |
--------------------------------------------------------------------------------