From 3e17c8d8f897ee459c8f1776d8d0cd3c327e2481 Mon Sep 17 00:00:00 2001 From: Rob <rob@synchro.net> Date: Sat, 3 Oct 2020 02:50:34 -0700 Subject: [PATCH] Changed user birthdate format to YYYYMMDD, input to YYYY/MM/DD Support the old MM/DD/YY or DD/MM/YY format for reading. New users get the new format. --- src/sbbs3/newuser.cpp | 17 +++++++--- src/sbbs3/userdat.c | 75 +++++++++++++++++++++++++++++------------- src/sbbs3/userdat.h | 5 ++- src/sbbs3/useredit.cpp | 15 +++++---- 4 files changed, 78 insertions(+), 34 deletions(-) diff --git a/src/sbbs3/newuser.cpp b/src/sbbs3/newuser.cpp index 4ba1928680..95d6595c70 100644 --- a/src/sbbs3/newuser.cpp +++ b/src/sbbs3/newuser.cpp @@ -315,11 +315,20 @@ BOOL sbbs_t::newuser() bputs(text[EnterYourSex]); useron.sex=(char)getkeys("MF",0); } + str[0] = 0; while((cfg.uq&UQ_BIRTH) && online && text[EnterYourBirthday][0]) { - bprintf(text[EnterYourBirthday] - ,cfg.sys_misc&SM_EURODATE ? "DD/MM/YY" : "MM/DD/YY"); - if(gettmplt(useron.birth,"nn/nn/nn",K_EDIT)==8 && getage(&cfg,useron.birth)) - break; + bprintf(text[EnterYourBirthday], "YYYY/MM/DD"); + if(gettmplt(str, "nnnn/nn/nn", K_EDIT) < 10) + continue; + int age = getage(&cfg, str); + if(age >= 1 && age <= 150) { + SAFEPRINTF3(useron.birth, "%.4s%.2s%.2s", str, str + 5, str + 8); + break; + } + SAFEPRINTF3(str, "%04u/%02u/%02u" + ,getbirthyear(useron.birth) + ,getbirthmonth(&cfg, useron.birth) + ,getbirthday(&cfg, useron.birth)); } if(!online) return(FALSE); while(!(cfg.uq&UQ_NONETMAIL) && online && text[EnterNetMailAddress][0]) { diff --git a/src/sbbs3/userdat.c b/src/sbbs3/userdat.c index c1c7837d6b..35437cedb7 100644 --- a/src/sbbs3/userdat.c +++ b/src/sbbs3/userdat.c @@ -734,12 +734,55 @@ int putusername(scfg_t* cfg, int number, char *name) return(0); } +#define DECVAL(ch, mul) (DEC_CHAR_TO_INT(ch) * (mul)) + +int getbirthyear(const char *birth) +{ + if(isdigit(birth[2])) // CCYYMMYY format + return DECVAL(birth[0], 1000) + + DECVAL(birth[1], 100) + + DECVAL(birth[2], 10) + + DECVAL(birth[3], 1); + // DD/MM/YY or MM/DD/YY format + time_t now = time(NULL); + struct tm tm; + if(localtime_r(&now, &tm) == NULL) + return 0; + tm.tm_year += 1900; + int year = 1900 + DECVAL(birth[6], 10) + DECVAL(birth[7], 1); + if(tm.tm_year - year > 105) + year += 100; + return year; +} + +int getbirthmonth(scfg_t* cfg, const char *birth) +{ + if(isdigit(birth[5])) // CCYYMMYY format + return DECVAL(birth[4], 10) + DECVAL(birth[5], 1); + if(cfg->sys_misc & SM_EURODATE) { // DD/MM/YY format + return DECVAL(birth[3], 10) + DECVAL(birth[4], 1); + } else { // MM/DD/YY format + return DECVAL(birth[0], 10) + DECVAL(birth[1], 1); + } +} + +int getbirthday(scfg_t* cfg, const char *birth) +{ + if(isdigit(birth[5])) // CCYYMMYY format + return DECVAL(birth[6], 10) + DECVAL(birth[7], 1); + if(cfg->sys_misc & SM_EURODATE) { // DD/MM/YY format + return DECVAL(birth[0], 10) + DECVAL(birth[1], 1); + } else { // MM/DD/YY format + return DECVAL(birth[3], 10) + DECVAL(birth[4], 1); + } +} + /****************************************************************************/ -/* Returns the age derived from the string 'birth' in the format MM/DD/YY */ +/* Returns the age derived from the string 'birth' in the format CCYYMMDD */ +/* or legacy: MM/DD/YY or DD/MM/YY */ /****************************************************************************/ -uint getage(scfg_t* cfg, char *birth) +int getage(scfg_t* cfg, const char *birth) { - uint age; struct tm tm; time_t now; @@ -752,26 +795,14 @@ uint getage(scfg_t* cfg, char *birth) now=time(NULL); if(localtime_r(&now,&tm)==NULL) return(0); - age=(tm.tm_year)-(((birth[6]&0xf)*10)+(birth[7]&0xf)); - if(age>105) - age-=100; + tm.tm_mon++; /* convert to 1 based */ - if(cfg->sys_misc&SM_EURODATE) { /* DD/MM/YY format */ - if(atoi(birth)>31 || atoi(birth+3)>12) - return(0); - if(((birth[3]&0xf)*10)+(birth[4]&0xf)>tm.tm_mon || - (((birth[3]&0xf)*10)+(birth[4]&0xf)==tm.tm_mon && - ((birth[0]&0xf)*10)+(birth[1]&0xf)>tm.tm_mday)) - age--; - } else { /* MM/DD/YY format */ - if(atoi(birth)>12 || atoi(birth+3)>31) - return(0); - if(((birth[0]&0xf)*10)+(birth[1]&0xf)>tm.tm_mon || - (((birth[0]&0xf)*10)+(birth[1]&0xf)==tm.tm_mon && - ((birth[3]&0xf)*10)+(birth[4]&0xf)>tm.tm_mday)) - age--; - } - return(age); + int year = getbirthyear(birth); + int age = (1900 + tm.tm_year) - year; + int mon = getbirthmonth(cfg, birth); + if(mon > tm.tm_mon || (mon == tm.tm_mon && getbirthday(cfg, birth) > tm.tm_mday)) + age--; + return age; } /****************************************************************************/ diff --git a/src/sbbs3/userdat.h b/src/sbbs3/userdat.h index 37ec8c4139..e0af4b2afe 100644 --- a/src/sbbs3/userdat.h +++ b/src/sbbs3/userdat.h @@ -80,7 +80,10 @@ DLLEXPORT int putusername(scfg_t*, int number, char * name); DLLEXPORT uint total_users(scfg_t*); DLLEXPORT uint lastuser(scfg_t*); DLLEXPORT BOOL del_lastuser(scfg_t*); -DLLEXPORT uint getage(scfg_t*, char *birthdate); +DLLEXPORT int getage(scfg_t*, const char* birthdate); +DLLEXPORT int getbirthmonth(scfg_t*, const char* birthdate); +DLLEXPORT int getbirthday(scfg_t*, const char* birthdate); +DLLEXPORT int getbirthyear(const char* birthdate); DLLEXPORT char* username(scfg_t*, int usernumber, char * str); DLLEXPORT char* usermailaddr(scfg_t*, char* addr, const char* name); DLLEXPORT int opennodedat(scfg_t*); diff --git a/src/sbbs3/useredit.cpp b/src/sbbs3/useredit.cpp index a137eb3056..231ee4cd0e 100644 --- a/src/sbbs3/useredit.cpp +++ b/src/sbbs3/useredit.cpp @@ -101,7 +101,8 @@ void sbbs_t::useredit(int usernumber) ,user.level>useron.level && console&CON_R_ECHO ? "XXX-XXX-XXXX" : user.phone); bprintf(text[UeditAddressBirthday] - ,user.address,getage(&cfg,user.birth),user.sex,user.birth); + ,user.address,getage(&cfg,user.birth),user.sex,user.birth + ,getbirthyear(user.birth), getbirthmonth(&cfg, user.birth), getbirthday(&cfg, user.birth)); bprintf(text[UeditLocationZipcode],user.location,user.zipcode); bprintf(text[UeditNoteHandle],user.note,user.handle); bprintf(text[UeditComputerModem],user.comp,user.modem); @@ -186,12 +187,12 @@ void sbbs_t::useredit(int usernumber) putuserrec(&cfg,user.number,U_HANDLE,LEN_HANDLE,user.handle); break; case 'B': - bprintf(text[EnterYourBirthday] - ,cfg.sys_misc&SM_EURODATE ? "DD/MM/YY" : "MM/DD/YY"); - gettmplt(user.birth,"nn/nn/nn",kmode); - if(sys_status&SS_ABORT) - break; - putuserrec(&cfg,user.number,U_BIRTH,LEN_BIRTH,user.birth); + bprintf(text[EnterYourBirthday], "YYYY/MM/DD"); + SAFEPRINTF3(str, "%04u/%02u/%02u", getbirthyear(user.birth), getbirthmonth(&cfg, user.birth), getbirthday(&cfg, user.birth)); + if(gettmplt(str, "nnnn/nn/nn", kmode) == 10) { + SAFEPRINTF3(user.birth, "%.4s%.2s%.2s", str, str + 5, str + 8); + putuserrec(&cfg,user.number,U_BIRTH,LEN_BIRTH,user.birth); + } break; case 'C': bputs(text[EnterYourComputer]); -- GitLab