CDatePickerCommon.js 28 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099
  1. /*
  2. *+------------------------------------------------------------------------+
  3. *| Licensed Materials - Property of IBM
  4. *| BI and PM: prmt
  5. *| (C) Copyright IBM Corp. 2002, 2018
  6. *|
  7. *| US Government Users Restricted Rights - Use, duplication or
  8. *| disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
  9. *|
  10. *+------------------------------------------------------------------------+
  11. */
  12. /*
  13. CDatePickerCommon.js
  14. This script provides utility functions for the date and dateTime
  15. prompt controls
  16. */
  17. //global variable
  18. var g_dNow = new Date();
  19. //get the current date
  20. //default to today's date
  21. var curYear = g_dNow.getFullYear();
  22. var curMonth = g_dNow.getMonth();
  23. var curDay = g_dNow.getDate();
  24. var PRMT_DateUtils = {
  25. 'mediumDateFormat' : null,
  26. 'mediumDateSeparator' : null
  27. };
  28. PRMT_DateUtils.dateRegexFromDateOrder = function(dateOrder) {
  29. var dateFormatReString;
  30. var dateSeparatorReString;
  31. var reDateParts;
  32. var datePartsOrder;
  33. if (dateOrder == 'MYD') {
  34. dateFormatReString = '([Mm]+.+[Yy]+.+[Dd]+)';
  35. reDateParts = '([Mm]+)(.+?)([Yy]+)[^Dd]+([Dd]+)';
  36. datePartsOrder = ['monthFormat','yearFormat','dayFormat'];
  37. } else if (dateOrder == 'MDY') {
  38. dateFormatReString = '^([Mm]+.+[Dd]+.+[Yy]+)';
  39. reDateParts = '([Mm]+)(.+?)([Dd]+)[^Yy]+([Yy]+)$';
  40. datePartsOrder = ['monthFormat','dayFormat','yearFormat'];
  41. } else if (dateOrder == 'YMD') {
  42. dateFormatReString = '([Yy]+.+[Mm]+.+[Dd]+)';
  43. reDateParts = '([Yy]+)(.+?)([Mm]+)[^Dd]+([Dd]+)';
  44. datePartsOrder = ['yearFormat', 'monthFormat','dayFormat'];
  45. } else if (dateOrder == 'YDM') {
  46. dateFormatReString = '([Yy]+.+[Dd]+.+[Mm]+)';
  47. reDateParts = '([Yy]+)(.+?)([Dd]+)[^Mm]+([Mm]+)';
  48. datePartsOrder = ['yearFormat','dayFormat', 'monthFormat'];
  49. } else if (dateOrder == 'DMY') {
  50. dateFormatReString = '([Dd]+.+[Mm]+.+[Yy]+)';
  51. reDateParts = '([Dd]+)(.+?)([Mm]+)[^Yy]+([Yy]+)';
  52. datePartsOrder = ['dayFormat','monthFormat','yearFormat'];
  53. } else if (dateOrder == 'DYM') {
  54. dateFormatReString = '([Dd]+.+[Yy]+.+[Mm]+)';
  55. reDateParts = '([Dd]+)(.+?)([Yy]+)[^Mm]+([Mm]+)';
  56. datePartsOrder = ['dayFormat', 'yearFormat', 'monthFormat'];
  57. }
  58. return { 'reDateFormat' : new RegExp(dateFormatReString), 'reDateParts': new RegExp(reDateParts), 'datePartsOrder': datePartsOrder };
  59. };
  60. //dateLength : medium | short
  61. PRMT_DateUtils.parseDateFormat = function (dateFormatToParse, dateOrder, defaultDateFormat, defaultDateSeparator, dateLenght) {
  62. var dateFormats = PRMT_DateUtils.dateRegexFromDateOrder(dateOrder);
  63. var extractedMatch = dateFormats['reDateFormat'].exec(dateFormatToParse);
  64. var dateFormat = defaultDateFormat, dateSeparator = defaultDateSeparator, datePartFormat = {};
  65. if (extractedMatch != null) {
  66. dateFormat = extractedMatch[1];
  67. //console.log("g_mediumFormat: \"" + g_mediumFormat + "\" dateFormat: \""+ dateFormat + "\"");
  68. extractedMatch = dateFormats['reDateParts'].exec(dateFormat);
  69. if (extractedMatch != null) {
  70. dateSeparator = extractedMatch[2];
  71. datePartFormat[dateFormats['datePartsOrder'][0]] = extractedMatch[1];
  72. datePartFormat[dateFormats['datePartsOrder'][1]] = extractedMatch[3];
  73. datePartFormat[dateFormats['datePartsOrder'][2]] = extractedMatch[4];
  74. //console.log("g_dateSeparatorMedium: \"" + g_dateSeparatorMedium + "\" dateSeparator: \""+ dateSeparator + "\"");
  75. //console.log("g_yearFormatMedium: \"" + g_yearFormatMedium + "\" mediumDatePartFormat.yearFormat: \""+ datePartFormat.yearFormat + "\"");
  76. }
  77. } else {
  78. //console.log("no match");
  79. }
  80. PRMT_DateUtils[dateLenght + 'DateFormat'] = dateFormat;
  81. PRMT_DateUtils[dateLenght + 'DateSeparator'] = dateSeparator;
  82. PRMT_DateUtils[dateLenght + 'DatePartFormat'] = datePartFormat;
  83. };
  84. // invoke this function when changing formats
  85. PRMT_DateUtils.resetDateFormats = function() { PRMT_DateUtils.mediumDateFormat = null; };
  86. //return a formatted text string based on a given day
  87. function getFormatDate(dSetDay, iType)
  88. {
  89. if (! PRMT_DateUtils.mediumDateFormat) {
  90. PRMT_DateUtils.parseDateFormat(g_mediumFormat, g_dateOrder, 'MMM d, yyyy', ' ','medium');
  91. PRMT_DateUtils.parseDateFormat(g_shortFormat, g_shortFormatDateOrder, "M/d/yy", '/','short');
  92. }
  93. if (!dSetDay)
  94. {
  95. return false;
  96. }
  97. //locale medium format
  98. var yearFormat = PRMT_DateUtils.mediumDatePartFormat.yearFormat; //g_yearFormatMedium;
  99. var monthFormat = PRMT_DateUtils.mediumDatePartFormat.monthFormat; // g_monthFormatMedium;
  100. var dayFormat = PRMT_DateUtils.mediumDatePartFormat.dayFormat; //g_dayFormatMedium;
  101. var sY = K_PRMT_sEMPTY;
  102. var sM = K_PRMT_sEMPTY;
  103. var sD = K_PRMT_sEMPTY;
  104. //0 = standard ; 1 = japaneseEmperor
  105. if (iType == 1)
  106. {
  107. sY = getJapaneseEra(dSetDay);
  108. }
  109. else
  110. {
  111. sY = dSetDay.getFullYear();
  112. sY = "0000" + sY;
  113. sY = sY.substring(sY.length-4, sY.length);
  114. //show as two digit year for those locales that require it
  115. if ((yearFormat == "yy") && (parseInt(sY, 10) > 1900))
  116. {
  117. sY = sY.substring(sY.length-2, sY.length);
  118. }
  119. }
  120. //get the formatted month
  121. if (monthFormat == "M")
  122. {
  123. sM = dSetDay.getMonth() + 1;
  124. }
  125. else if (monthFormat == "MMM")
  126. {
  127. sM = g_arMonthsAbbr[dSetDay.getMonth()];
  128. }
  129. else if (monthFormat == "MMMM")
  130. {
  131. sM = g_arMonths[dSetDay.getMonth()];
  132. }
  133. else
  134. {
  135. var iM = dSetDay.getMonth() + 1;
  136. sM = iM.toString();
  137. if (sM.length == 1)
  138. {
  139. sM = "0" + sM;
  140. }
  141. }
  142. if (dayFormat.match(/DD/i))
  143. {
  144. var iD = dSetDay.getDate();
  145. sD = iD.toString();
  146. if (sD.length == 1)
  147. {
  148. sD = "0" + sD;
  149. }
  150. }
  151. else
  152. {
  153. sD = dSetDay.getDate();
  154. }
  155. // show in medium date format
  156. sFormatDate = PRMT_DateUtils.mediumDateFormat;
  157. sFormatDate = sFormatDate.replace(RegExp(yearFormat, K_PRMT_sG), sY);
  158. sFormatDate = sFormatDate.replace(RegExp(dayFormat, K_PRMT_sG), sD);
  159. sFormatDate = sFormatDate.replace(RegExp(monthFormat, K_PRMT_sG), sM);
  160. return sFormatDate;
  161. }
  162. //return the number of days in the month
  163. function intGetDays(intMonth, intYear)
  164. {
  165. switch (intMonth)
  166. {
  167. case 0:
  168. return 31; // jan
  169. case 1:
  170. return (boolLeapYear(intYear))? 29:28; //feb
  171. case 2:
  172. return 31; //mar
  173. case 3:
  174. return 30;//apr
  175. case 4:
  176. return 31;//may
  177. case 5:
  178. return 30;//jun
  179. case 6:
  180. return 31;//jul
  181. case 7:
  182. return 31;//aug
  183. case 8:
  184. return 30;//sep
  185. case 9:
  186. return 31;//oct
  187. case 10:
  188. return 30;//nov
  189. case 11:
  190. return 31;//dec
  191. default:
  192. return -1; //problem determining month
  193. }
  194. }
  195. //return the text for a given month
  196. function sGetMonth(iMonth)
  197. {
  198. return g_arMonthsAbbr[iMonth];
  199. }
  200. //return the text for a given day
  201. function sGetDay(iDay)
  202. {
  203. return g_arDaysAbbr[iDay];
  204. }
  205. //check to see if this is a leap year
  206. /*if divisible evenly by 4, a Gregorian year is a leap year, with a February 29 and 366 days
  207. (e.g. 1996/4 = 499, so 1996 is a leap year), UNLESS
  208. if divisible evenly by 100, a Gregorian year is a normal year with 365 days
  209. (e.g.1900/100=19, so 1900 is a normal year of 365 days), UNLESS
  210. if divisible evenly by 400, a Gregorian year is a leap year;
  211. so the year 2000 is a leap year.
  212. */
  213. function boolLeapYear(iYear)
  214. {
  215. if ((iYear % 4 === 0) && ( (!(iYear % 100 === 0)) || (iYear % 400 === 0) ) )
  216. {
  217. return true;
  218. }
  219. else
  220. {
  221. return false;
  222. }
  223. }
  224. //return true if a string is a valid year
  225. function boolTestYear(sTestYear)
  226. {
  227. var reYear = new RegExp("^\\s*\\d{1,4}\\s*$");
  228. return ( typeof sTestYear == "string" && sTestYear.match(reYear) ? true : false );
  229. }
  230. //use this function to see if a string
  231. //can be turned into a valid date
  232. function boolTestDate(sTestDate)
  233. {
  234. var dTestDate = Date.parse(sTestDate);
  235. if (dTestDate) //this is a valid date
  236. {
  237. return true;
  238. }
  239. else
  240. {
  241. return false;
  242. }
  243. }
  244. //TODO
  245. function boolTestDateValidity(mdate)
  246. {
  247. if (mdate.getTime()) //this is a valid date
  248. {
  249. return true;
  250. }
  251. else
  252. {
  253. return false;
  254. }
  255. }
  256. //remove non alpha numeric data from a string
  257. function sStripNonAlphanumerics(sString)
  258. {
  259. var charDelimiters = /[\s,-]/g;
  260. var arTestDateStrip = sString.split(charDelimiters);
  261. var sTestDateStrip = arTestDateStrip.join(K_PRMT_sSP);
  262. return sTestDateStrip;
  263. }
  264. //parse string input and return a date object
  265. //return false if the value is not a date
  266. //if the input order is supplied, the parser
  267. //can determine ambiguous dates
  268. //ToDo: handle japanese days e.g. do any of the strings start with numbers, strip out day characters
  269. //ToDo: handle imperial time strings (this may need to happen prior to launching this function
  270. function dParseDate(sTestDate, sInputOrder)
  271. {
  272. //////////////////////
  273. // this logic should be able to properly parse any of the following typed in values
  274. //
  275. // jan 01 2001
  276. // june/05-2002
  277. // 29-MAY-1999
  278. // 01/02/2002 (requires inputOrder)
  279. // 2002-02-10 (requires inputOrder)
  280. // 2002/Feb/28
  281. //declare variables
  282. var iMonth = null;
  283. var iDay = null;
  284. var iYear = null;
  285. var bFoundDay = false;
  286. var iDayPos = null;
  287. var bFoundMonth = false;
  288. var iMonthPos = null;
  289. var bFoundYear = false;
  290. var iYearPos = null;
  291. //determine input order from locale
  292. //declare variables and default to international standard YMD
  293. var iYearExpectedPos = 0;
  294. var iMonthExpectedPos = 1;
  295. var iDayExpectedPos = 2;
  296. var rNoIntegers = /[^0-9]/;
  297. var myTestDate = null;
  298. //get the input order
  299. if (sInputOrder)
  300. {
  301. switch(sInputOrder)
  302. {
  303. case "MYD":
  304. iYearExpectedPos=1;
  305. iMonthExpectedPos=0;
  306. iDayExpectedPos=2;
  307. break;
  308. case "MDY":
  309. iYearExpectedPos=2;
  310. iMonthExpectedPos=0;
  311. iDayExpectedPos=1;
  312. break;
  313. case "YMD":
  314. iYearExpectedPos=0;
  315. iMonthExpectedPos=1;
  316. iDayExpectedPos=2;
  317. break;
  318. case "YDM":
  319. iYearExpectedPos=0;
  320. iMonthExpectedPos=2;
  321. iDayExpectedPos=1;
  322. break;
  323. case "DMY":
  324. iYearExpectedPos=2;
  325. iMonthExpectedPos=1;
  326. iDayExpectedPos=0;
  327. break;
  328. case "DYM":
  329. iYearExpectedPos=1;
  330. iMonthExpectedPos=2;
  331. iDayExpectedPos=0;
  332. break;
  333. default:
  334. iYearExpectedPos=0;
  335. iMonthExpectedPos=1;
  336. iDayExpectedPos=2;
  337. break;
  338. }
  339. }
  340. //strip out any extraneous characters
  341. //pass 1 (strip out the medium and short delimiters)
  342. var sTestDateReplace = sTestDate;
  343. var specialCharacters = "?.[]^$(){}|\\&";
  344. // g_dateSeparatorShort may not be a single character
  345. var dateSepShortArray = g_dateSeparatorShort.split("");
  346. var dateSepShort = "";
  347. for (var i = 0; i < dateSepShortArray.length; i++)
  348. {
  349. dateSepShort +=
  350. specialCharacters.indexOf(dateSepShortArray[i]) >= 0 ? ("\\" + dateSepShortArray[i]) : dateSepShortArray[i];
  351. }
  352. var rShortDateDelimiter = new RegExp(dateSepShort, K_PRMT_sG);
  353. sTestDateReplace = sTestDateReplace.replace(rShortDateDelimiter, K_PRMT_sSP);
  354. //Norwegian locale dates has ". " as mediumDateSeparator
  355. var norwegianSep = ". ";
  356. var mediumDateSeparator = PRMT_DateUtils.mediumDateSeparator; // old g_dateSeparatorMedium
  357. var dateSepMedium = ((specialCharacters.indexOf(mediumDateSeparator) >= 0)
  358. || (norwegianSep == mediumDateSeparator)) ? ("\\" + mediumDateSeparator) : mediumDateSeparator;
  359. var rMediumDateDelimiter = new RegExp(dateSepMedium, K_PRMT_sG);
  360. sTestDateReplace = sTestDateReplace.replace(rMediumDateDelimiter, K_PRMT_sSP);
  361. //pass 2 (strip out other known delimiters)
  362. var rDelimiters = /[\s,\-\/\\#\:]/g;
  363. //split the string into tokens
  364. var arDateTokens = sTestDateReplace.split(rDelimiters);
  365. //do we have enough tokens to proceed?
  366. if (arDateTokens.length != 3)
  367. {
  368. var rDelimitersWithDecimal = /[\s,\.\-\/\\#\:]/g;
  369. arDateTokens = sTestDateReplace.split(rDelimitersWithDecimal);
  370. }
  371. //check to see if there are enough tokens. (we need 3)
  372. if (arDateTokens.length < 3)
  373. {
  374. // we have less than three tokens,
  375. // the date is not valid
  376. return false;
  377. }
  378. else if (arDateTokens.length > 3)
  379. {
  380. //remove any empty array items
  381. //NS7 will create empty array items
  382. var arCleanArray = new Array();
  383. for (var x=0; x < arDateTokens.length; x++)
  384. {
  385. if (arDateTokens[x] !== K_PRMT_sEMPTY)
  386. {
  387. arCleanArray = arCleanArray.concat(arDateTokens[x]);
  388. }
  389. }
  390. //use the stripped array
  391. arDateTokens = arCleanArray;
  392. }
  393. if (arDateTokens.length > 3)
  394. {
  395. //we have more than three tokens
  396. //remove any character data and try again
  397. //this could be because of locale
  398. //for example, Japanese dates include symbols
  399. //strip any tokens with alpha numeric characters from the array of tokens
  400. var arStrippedArray = new Array();
  401. for (var i=0; i < arDateTokens.length; i++)
  402. {
  403. var z = arDateTokens[i].search(rNoIntegers);
  404. if (z == -1)
  405. {
  406. if (arDateTokens[i])
  407. {
  408. arStrippedArray = arStrippedArray.concat(arDateTokens[i]);
  409. }
  410. }
  411. }
  412. //check again
  413. //do we have 3 characters? if not error
  414. if (arStrippedArray.length == 3)
  415. {
  416. //use the stripped array
  417. arDateTokens = arStrippedArray;
  418. }
  419. else
  420. {
  421. //there is an incorrect number of tokens
  422. return false;
  423. }
  424. }
  425. for(var i = 0; i < arDateTokens.length; i++)
  426. {
  427. if(!validateStringForInvalidChars(arDateTokens[i]))
  428. {
  429. return false; // special chars in value
  430. }
  431. }
  432. //try to match the tokens according to input order
  433. //try and match year (medium and short formats)
  434. //what is the year position?
  435. if (arDateTokens[iYearExpectedPos] && arDateTokens[iYearExpectedPos].search(rNoIntegers) == -1)
  436. {
  437. if ((arDateTokens[iYearExpectedPos].length >= 1) && (arDateTokens[iYearExpectedPos].length <= 4))
  438. {
  439. iYear = arDateTokens[iYearExpectedPos];
  440. if (iYear.length == 2)
  441. {
  442. iYear = sShortToFullYearConversion(iYear);
  443. }
  444. bFoundYear = true;
  445. iYearPos= iYearExpectedPos;
  446. }
  447. }
  448. //try and match month (medium and short formats)
  449. //see if it matches the a localized month
  450. var sTestMonth = false;
  451. var iTestMonth = false;
  452. if (bNumbersOnly(arDateTokens[iMonthExpectedPos]) === true)
  453. {
  454. iTestMonth = parseInt(arDateTokens[iMonthExpectedPos],10) - 1;
  455. }
  456. else
  457. {
  458. sTestMonth = iCheckMonthString(arDateTokens[iMonthExpectedPos]);
  459. }
  460. if ((parseInt(sTestMonth,10) >= 0) && (parseInt(sTestMonth,10) <= 11))
  461. {
  462. iMonth = sTestMonth;
  463. bFoundMonth = true;
  464. iMonthPos = iMonthExpectedPos;
  465. }
  466. //see if it is a valid month by number
  467. else if (checkMonth(iTestMonth))
  468. {
  469. iMonth = iTestMonth;
  470. bFoundMonth = true;
  471. iMonthPos = iMonthExpectedPos;
  472. }
  473. //try and match day
  474. //we need a valid year and month to do this
  475. if ((bFoundMonth) && (bFoundYear))
  476. {
  477. if (checkDay(arDateTokens[iDayExpectedPos], parseInt(iMonth, 10), parseInt(iYear, 10)))
  478. {
  479. iDay = arDateTokens[iDayExpectedPos];
  480. bFoundDay = true;
  481. iDayPos = iDayExpectedPos;
  482. }
  483. }
  484. // do we have a valid date
  485. // if yes, update date
  486. if ((bFoundMonth) && (bFoundYear) && (bFoundDay))
  487. {
  488. // everything looks good, so use the javascript Date object to return a day
  489. myTestDate = prmt_createDateObject(iYear, iMonth, iDay);
  490. //set the year 'full' year explicitly
  491. myTestDate.setFullYear(iYear);
  492. if (!boolTestDateValidity(myTestDate))
  493. {
  494. //check on the date failed, return false
  495. return false;
  496. }
  497. else
  498. {
  499. //got a valid date, return it to the user
  500. return myTestDate;
  501. }
  502. }
  503. //The input did not match the locale's input order
  504. //perform a deeper analysis of the input
  505. bFoundYear = false;
  506. bFoundMonth = false;
  507. bFoundDay = false;
  508. iYear = null;
  509. iMonth = null;
  510. iDay = null;
  511. //try to match against SQL format
  512. iYearExpectedPos=0;
  513. iMonthExpectedPos=1;
  514. iDayExpectedPos=2;
  515. iYear = arDateTokens[0];
  516. iMonth = parseInt(arDateTokens[1],10)-1;
  517. iDay = parseInt(arDateTokens[2],10);
  518. //match year
  519. if ((bCheckFullYear(iYear)) && (checkMonth(iMonth)) && checkDay(iDay, iMonth, parseInt(iYear,10)))
  520. {
  521. myTestDate = new Date (iYear, iMonth, iDay);
  522. //set the year 'full' year explicitly
  523. myTestDate.setFullYear(iYear);
  524. return myTestDate;
  525. }
  526. //look for landmarks (such as a string month name or 4 digit year)
  527. //try to find the month (match against medium format) by string
  528. iYear = null;
  529. iMonth = null;
  530. iDay = null;
  531. var k=0;
  532. for (k=0; k < arDateTokens.length; k++)
  533. {
  534. var sSearchMonth = iCheckMonthString(arDateTokens[k]);
  535. if ((parseInt(sSearchMonth, 10) >= 0) && (parseInt(sSearchMonth, 10) <= 11))
  536. {
  537. iMonth = parseInt(sSearchMonth, 10);
  538. bFoundMonth = true;
  539. iMonthPos = k;
  540. }
  541. }
  542. //try to find the year (match 3 or 4 digits)
  543. var l=0;
  544. for (l=0; l < arDateTokens.length; l++)
  545. {
  546. if (bCheckFullYear(arDateTokens[l]) === true)
  547. {
  548. iYear= arDateTokens[l];
  549. bFoundYear = true;
  550. iYearPos = l;
  551. }
  552. }
  553. //do we have a month and year? try to assign day
  554. //found the year and month -- can we nail the day??
  555. if ((bFoundYear) && (bFoundMonth))
  556. {
  557. //grab the day
  558. var m = 0;
  559. for (m=0; m < arDateTokens.length; m++)
  560. {
  561. if ((m != iYearPos) && (m != iMonthPos))
  562. {
  563. if (arDateTokens[m].search(rNoIntegers) == -1)
  564. {
  565. //is this a valid day?
  566. if (checkDay(arDateTokens[m], parseInt(iMonth,10), parseInt(iYear,10)))
  567. {
  568. iDay = arDateTokens[m];
  569. bFoundDay = true;
  570. iDayPos= m;
  571. }
  572. }
  573. }
  574. }
  575. }
  576. // do we have a valid date
  577. // if yes, update date
  578. if ((bFoundMonth) && (bFoundYear) && (bFoundDay))
  579. {
  580. // everything looks good, so use the javascript Date object to return a day
  581. myTestDate = prmt_createDateObject(iYear, iMonth, iDay);
  582. //set the year 'full' year explicitly
  583. myTestDate.setFullYear(iYear);
  584. if (!boolTestDate(myTestDate))
  585. {
  586. //this is not a valid date, return false
  587. return false;
  588. }
  589. else
  590. {
  591. //got a valid date, return it to the user
  592. return myTestDate;
  593. }
  594. }
  595. else
  596. {
  597. // if no, error
  598. return false;
  599. }
  600. }
  601. // create a day object, shift the hour if DST change the date
  602. function prmt_createDateObject(iYear, iMonth, iDay) {
  603. var result = new Date (iYear, iMonth, iDay);
  604. var iHourShift = 1;
  605. while (result.getDate() != iDay && iHourShift < 6) {
  606. result = new Date(iYear, iMonth, iDay, iHourShift);
  607. iHourShift++;
  608. }
  609. return result;
  610. }
  611. //test to see if a string is a year
  612. function bCheckFullYear(sTestYear)
  613. {
  614. var rNoIntegers = /[^0-9]/;
  615. var z = sTestYear.search(rNoIntegers);
  616. if (z == -1)
  617. {
  618. if ((sTestYear.length == 3) || (sTestYear.length == 4))
  619. {
  620. return true;
  621. }
  622. }
  623. return false;
  624. }
  625. //Check to see if the passed in string contains regex chars, return true if none, false for an invalid string (contains regex special chars)
  626. function validateStringForInvalidChars(dateString)
  627. {
  628. //we can ignore '-', '.' and '/' here, as these are used in dates
  629. return !/[\[\]\{\}\(\)\*\+\?\\\^\$\|]/g.test(dateString);
  630. }
  631. //check to see if a string is a month
  632. function iCheckMonthString(sTestMonth)
  633. {
  634. //make the test month name the same size or smaller than the month
  635. //find the first match
  636. var rPeriod = new RegExp("\\.", K_PRMT_sGI);
  637. var sTestMonthNoDots = sTestMonth.replace(rPeriod, K_PRMT_sEMPTY);
  638. var j=0;
  639. for (j=0; j<g_arMonthsAbbr.length; j++)
  640. {
  641. //some locales use an optional '.' in the abbreviation
  642. //strip any periods off
  643. var sMonthCompare = g_arMonthsAbbr[j];
  644. sMonthCompare = sMonthCompare.replace(rPeriod,K_PRMT_sEMPTY);
  645. var iMonthLength = sMonthCompare.length;
  646. var sTestMonthTest = null;
  647. if (sTestMonthNoDots.length > iMonthLength)
  648. {
  649. sTestMonthTest = sTestMonthNoDots.substr(0, iMonthLength);
  650. }
  651. else
  652. {
  653. sTestMonthTest = sTestMonthNoDots;
  654. }
  655. //strip periods
  656. //sTestMonthTest = sTestMonthTest.replace(rPeriod, K_PRMT_sEMPTY);
  657. var myPattern = new RegExp("^" + sTestMonthTest, "i"); //ignore case
  658. //is there a match?
  659. if (sMonthCompare.match(myPattern))
  660. {
  661. //found a month, return it
  662. return j;
  663. }
  664. }
  665. return false;
  666. }
  667. //check month from a string
  668. function checkMonth(s)
  669. {
  670. var num = parseInt (s,10);
  671. if ((num >= 0) && (num <= 11))
  672. {
  673. return true;
  674. }
  675. else
  676. {
  677. return false;
  678. }
  679. }
  680. //check the number of days in the month
  681. function checkDay(s, iTestMonth, iTestYear)
  682. {
  683. var iMaxDays = intGetDays(iTestMonth, iTestYear);
  684. var num = parseInt(s,10);
  685. return ((num >= 1) && (num <= iMaxDays));
  686. }
  687. function bIsDateLater(dDate, dTestDate)
  688. {
  689. //remove the time portions
  690. dDate.setHours(0);
  691. dDate.setSeconds(0);
  692. dDate.setMinutes(0);
  693. dDate.setMilliseconds(0);
  694. dTestDate.setHours(0);
  695. dTestDate.setSeconds(0);
  696. dTestDate.setMinutes(0);
  697. dTestDate.setMilliseconds(0);
  698. if (dDate > dTestDate)
  699. {
  700. return true;
  701. }
  702. else
  703. {
  704. return false;
  705. }
  706. }
  707. function bIsDateEarlier(dDate, dTestDate)
  708. {
  709. //remove the time portions
  710. dDate.setHours(0);
  711. dDate.setSeconds(0);
  712. dDate.setMinutes(0);
  713. dDate.setMilliseconds(0);
  714. dTestDate.setHours(0);
  715. dTestDate.setSeconds(0);
  716. dTestDate.setMinutes(0);
  717. dTestDate.setMilliseconds(0);
  718. if (dDate < dTestDate)
  719. {
  720. return true;
  721. }
  722. else
  723. {
  724. return false;
  725. }
  726. }
  727. //japanese emperor time functions
  728. //create a japanese era object
  729. // sName: the name of the era
  730. // sStartYear: beginning year of the era
  731. // sStartMonth: beginning month of the era
  732. // sStartDay: beginning day of the era
  733. // sEndYear: end year of the era
  734. // sEndMonth: end month of the era
  735. // sEndDay: end day of the era
  736. function japaneseEra (sName, sStartYear, sStartMonth, sStartDay, sEndYear, sEndMonth, sEndDay)
  737. {
  738. this.m_sName = sName;
  739. this.m_dStartDate = new Date(sStartYear, (parseInt(sStartMonth,10) -1).toString(), sStartDay, 0, 0, 0);
  740. this.m_dEndDate = new Date(sEndYear, (parseInt(sEndMonth,10) -1).toString(), sEndDay, 23, 59, 59);
  741. }
  742. //return the japanese era from a date
  743. function getJapaneseEra (dTestDate)
  744. {
  745. var sJapaneseEra = K_PRMT_sEMPTY;
  746. updateJapaneseEraNames();
  747. for (var i = 0; i < japaneseEras.length; i++)
  748. {
  749. if (dTestDate >= japaneseEras[i].m_dStartDate && dTestDate <= japaneseEras[i].m_dEndDate)
  750. {
  751. sJapaneseEra = japaneseEras[i].m_sName;
  752. var eraYear = (parseInt(dTestDate.getFullYear(), 10) - parseInt(japaneseEras[i].m_dStartDate.getFullYear(), 10) +1);
  753. sJapaneseEra += K_PRMT_sSP + eraYear.toString();
  754. return sJapaneseEra;
  755. }
  756. }
  757. //this date did no match any known values, so return the current year
  758. sJapaneseEra = dTestDate.getFullYear();
  759. return sJapaneseEra;
  760. }
  761. function updateJapaneseEraNames()
  762. {
  763. if ( !(japaneseEras instanceof Array) || japaneseEras.length < 5)
  764. {
  765. return;
  766. }
  767. if (typeof PMT_EMP_JAPANESE_EMPORER_1 == K_PRMT_sSTRING)
  768. {
  769. japaneseEras[0].m_sName = PMT_EMP_JAPANESE_EMPORER_1;
  770. }
  771. if (typeof PMT_EMP_JAPANESE_EMPORER_2 == K_PRMT_sSTRING)
  772. {
  773. japaneseEras[1].m_sName = PMT_EMP_JAPANESE_EMPORER_2;
  774. }
  775. if (typeof PMT_EMP_JAPANESE_EMPORER_3 == K_PRMT_sSTRING)
  776. {
  777. japaneseEras[2].m_sName = PMT_EMP_JAPANESE_EMPORER_3;
  778. }
  779. if (typeof PMT_EMP_JAPANESE_EMPORER_4 == K_PRMT_sSTRING)
  780. {
  781. japaneseEras[3].m_sName = PMT_EMP_JAPANESE_EMPORER_4;
  782. }
  783. if (typeof PMT_EMP_JAPANESE_EMPORER_5 == K_PRMT_sSTRING)
  784. {
  785. japaneseEras[4].m_sName = PMT_EMP_JAPANESE_EMPORER_5;
  786. }
  787. }
  788. //function that will return the year from a given era
  789. function getYearfromEra (sEra, iEraYear)
  790. {
  791. updateJapaneseEraNames();
  792. for (var i=0; i < japaneseEras.length; i++)
  793. {
  794. if (sEra == japaneseEras[i].m_sName)
  795. {
  796. iEraYear = japaneseEras[i].m_dStartDate.getFullYear() + iEraYear - 1;
  797. return iEraYear;
  798. }
  799. }
  800. return false;
  801. }
  802. //this will test for a valid japanese era,
  803. //strip it out and then pass the value to the standard
  804. //date parser to finish the job
  805. function dParseEra(sTestDate, sInputOrder)
  806. {
  807. //split the string into an array based on non alphanumeric delimeters
  808. var rDelimiters = /[\s,\.-\/\\#\:]/g;
  809. var rNoIntegers = /[^0-9]/;
  810. var sEra = null;
  811. var iEraYear = null;
  812. var bFoundEra = false;
  813. var bFoundEraYear = false;
  814. var iEraPosition = null;
  815. var dEraDate = false;
  816. var arDateTokens = sTestDate.split(rDelimiters);
  817. updateJapaneseEraNames();
  818. //find the token with the era
  819. for (var i=0; i < arDateTokens.length; i++)
  820. {
  821. //there are characters in this token?
  822. if (arDateTokens[i].search(rNoIntegers) != -1)
  823. {
  824. //is it an era?
  825. for (var j=0; j < japaneseEras.length; j++)
  826. {
  827. var sTestEra = arDateTokens[i];
  828. if (sTestEra.length > japaneseEras[j].m_sName.length)
  829. {
  830. sTestEra = sTestEra.substring(0, japaneseEras[j].m_sName.length);
  831. }
  832. var myEra = new RegExp("^" + sTestEra, "i"); //ignore case
  833. //is there a match?
  834. if (japaneseEras[j].m_sName.match(myEra))
  835. {
  836. bFoundEra=true;
  837. iEraPosition = i;
  838. sEra = japaneseEras[j].m_sName;
  839. //is there a number to the right of the era?
  840. if (iEraPosition + 1 < arDateTokens.length )
  841. {
  842. //is it a number?
  843. //var rNoIntegers = /[^0-9]/;
  844. var y = arDateTokens[iEraPosition + 1].search(rNoIntegers);
  845. if (y == -1)
  846. {
  847. bFoundEraYear= true;
  848. iEraYearPosition = i+1;
  849. iEraYear = parseInt(arDateTokens[iEraPosition + 1],10);
  850. }
  851. }
  852. }
  853. }
  854. }
  855. }
  856. if ((bFoundEra === true) && (bFoundEraYear === true))
  857. {
  858. var sProcessedDate = K_PRMT_sEMPTY;
  859. var sConvertedEraYear = getYearfromEra(sEra, iEraYear);
  860. //concatenate back into a string
  861. for (var m=0; m < arDateTokens.length; m++)
  862. {
  863. if (m == iEraPosition)
  864. {
  865. //add the converted era to the string
  866. sProcessedDate += K_PRMT_sSP + sConvertedEraYear;
  867. }
  868. else if (m==iEraYearPosition)
  869. {
  870. //do nothing
  871. }
  872. else
  873. {
  874. //add to the end of the string
  875. sProcessedDate += K_PRMT_sSP + arDateTokens[m];
  876. }
  877. }
  878. dEraDate = dParseDate(sProcessedDate, sInputOrder);
  879. }
  880. //couldn't find a valid era, it might still be a valid date
  881. else
  882. {
  883. dEraDate = dParseDate(sTestDate, sInputOrder);
  884. }
  885. return dEraDate;
  886. }
  887. //test to a year to see if there is a corresponding
  888. //Imperial era
  889. function iTestEra(sTestYear)
  890. {
  891. var rDelimiters = /[\s,\.-\/\\#\:]/g;
  892. var arDateTokens = sTestYear.split(rDelimiters);
  893. var sTestEra = arDateTokens[0];
  894. var bFoundEra = false;
  895. var sFoundEra =K_PRMT_sEMPTY;
  896. var iFoundEraYear = null;
  897. if (arDateTokens.length == 2)
  898. {
  899. updateJapaneseEraNames();
  900. //is it an era?
  901. for (var j=0; j < japaneseEras.length; j++)
  902. {
  903. if (sTestEra.length > japaneseEras[j].m_sName.length)
  904. {
  905. sTestEra = sTestEra.substring(0, japaneseEras[j].m_sName.length);
  906. }
  907. var myEra = new RegExp("^" + sTestEra, "i"); //ignore case
  908. //is there a match?
  909. if (japaneseEras[j].m_sName.match(myEra))
  910. {
  911. bFoundEra = true;
  912. sFoundEra = japaneseEras[j].m_sName;
  913. iFoundEraYear = parseInt(arDateTokens[1],10);
  914. }
  915. }
  916. if (bFoundEra === true)
  917. {
  918. return getYearfromEra (sFoundEra, iFoundEraYear);
  919. }
  920. }
  921. return false;
  922. }
  923. //this function will convert 2 digit years to a 4 digit
  924. //year using the following convention:
  925. // 00-49 converted to 20**
  926. // 50-99 converted to 19**
  927. function sShortToFullYearConversion(sShortYear)
  928. {
  929. if (sShortYear.length == 2)
  930. {
  931. var iTestYear = parseInt(sShortYear,10);
  932. if (iTestYear >= MIN_YEAR && iTestYear <= MAX_YEAR)
  933. {
  934. iTestYear = iTestYear + 2000;
  935. }
  936. else
  937. {
  938. iTestYear = iTestYear + 1900;
  939. }
  940. var sConvertedYear = iTestYear.toString();
  941. return sConvertedYear;
  942. }
  943. else
  944. {
  945. //not a valid 2 digit year
  946. return false;
  947. }
  948. }
  949. // Default Date Arrays
  950. //these values are used if locale information is not available.
  951. g_arMonths = new Array("January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December");
  952. g_arMonthsAbbr = new Array("Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec");
  953. g_arDays = new Array("Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday");
  954. g_arDaysAbbr = new Array("Su", "Mo", "Tu", "We", "Th", "Fr", "Sa");
  955. g_amString = "AM";
  956. g_pmString = "PM";
  957. g_startDayOfWeek = 1; // 1 = Sunday, 2 = Monday, etc...
  958. g_mediumFormat = "MMM d, yyyy h:mm:ss a";
  959. g_shortFormat = "M/d/yy h:mm a";
  960. g_dateOrder = "MDY";
  961. g_shortFormatDateOrder = "MDY";
  962. g_yearFormatMedium = "yyyy";
  963. g_monthFormatMedium = "MMM";
  964. g_dayFormatMedium = "d";
  965. g_hourFormatMedium = "h";
  966. g_minuteFormatMedium = "mm";
  967. g_secondFormatMedium = "ss";
  968. g_yearFormatShort = "yy";
  969. g_monthFormatShort = "M";
  970. g_dayFormatShort = "d";
  971. g_hourFormatShort = "h";
  972. g_minuteFormatShort = "mm";
  973. g_secondFormatShort = K_PRMT_sEMPTY;
  974. g_dateSeparatorMedium = K_PRMT_sSP;
  975. g_dateSeparatorShort = "/";
  976. g_timeSeparator = K_PRMT_sCOLON;
  977. var japaneseEras = new Array();
  978. japaneseEras[0] = new japaneseEra('Meiji', '1868', '8', '8', '1912', '7', '29');
  979. japaneseEras[1] = new japaneseEra('Taisho', '1912', '7', '30', '1926', '12', '24');
  980. japaneseEras[2] = new japaneseEra('Showa', '1926', '12', '25', '1989', '1', '7');
  981. japaneseEras[3] = new japaneseEra('Heisei', '1989', '1', '8', '2019', '4', '30');
  982. japaneseEras[4] = new japaneseEra('Reiwa', '2019', '5', '1', '2087', '12', '31');
  983. //2 digit year conversions
  984. MIN_YEAR = 0;
  985. MAX_YEAR = 49;