lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]

No credit card expires over more than 100 years (and even, never more than 50 years; I think that most credit cards expire within 5 years at most). So convert the 2 digits by rounding to the current years +/- 50 years, and you get the implied full year of the indicated credit card.

E.g. we are in 2020, the indicated range would be between 1970 and 2069: an indicated year 70 to 99 would convert by adding 1900, an indicated year 00 to 69 would convert by adding 2000.
In 2020, the indicated range would be between 1971 and 2070: an indicated year 71 to 99 would convert by adding 1900, an indicated year 00 to 70 would convert by adding 2000.
Each year you there are two new ranges.

Anyway you can still hard code using 1970 as the starting year. Credit cards standards are very likely to change in the future and this indication will no longer be sufficient to process any payment. In fact a new system will probably exist at that time, and you'll have to change your code anyway (or your code will no longer be used at all since long) before we reach years 2060 (at which time you *may* start to see cards expiring in 2070 or later).

Le lun. 15 juin 2020 à 22:15, Wilmar Pérez <> a écrit :
Hi all,

I have an application collecting credit card data. Before sending the information out to the payment entity I am trying to make sure the information entered is, at least, valid. I already worked out the card number and cvv numbers but I am not so sure about the expiry date. The format I get the info is MMYY. So what I am doing is: 

Exported from Notepad++
-- Simple function to get current date and times function getdatetime(tz) local tz = tz or 'America/New_York'; local luatz = require 'luatz'; local function ts2tt(ts) return luatz.timetable.new_from_timestamp(ts); end local utcnow = luatz.time(); local time_zone = luatz.get_tz(tz); local datetime_raw = tostring(ts2tt(time_zone:localise(utcnow))); local year, month, day, hour, min, sec, time_reminder = string.match(datetime_raw, "^(%d%d%d%d)%-(%d%d)%-(%d%d)[Tt](%d%d%.?%d*):(%d%d):(%d%d)()"); return year, month, day, hour, min, sec; end local current_year, current_month = getdatetime() -- Get current year/Month local card_expiry_date = 'YYMM'; -- In the app this actually get a value eg: 2204, 2301, 2010, etc. local card_exp_year = string.sub(card_expiry_date , 3, 4) local card_exp_month = string.sub(card_expiry_date , 1, 2) -- Extract the last two digits of the Year current_year = string.sub(current_year , 3, 4) -- Check month is valid if(card_exp_month < '01' or card_exp_month > '12')then print("This is not a valid month") else -- Check date is this month or after if((card_exp_year < current_year) or (card_exp_year == current_year and card_exp_month < current_month))then print("Date cannot be before this month.") else print("All is good.") end end


I do not know if this is the most elegant solution but it works. However it has a huge bug: it will fail at the end of the century. Since I only know the last two digits of the expiry date year, if a card expires in 2102 for instance and we were in 2099 my logic would wrongly reject the date (02 is less than 99).

I am very aware that me an my simple app will likely not be around by then but it bugs me to leave it like this.

Can anyone please suggest a proper way to do this validation?

Thank you!

Wilmar Pérez