Getting around Date field limitations

3 minute read time.

CRM has a limitation on dates in that you cannot enter dates before the 30th of December 1899. In rare cases you may need to store dates before this date, recently I helped a customer who had this requirement. I came up with a workaround of sorts which I will share with you in this post.

To get technical, the reason that this limitation exists is due to the core eware.dll being written in Delphi which has the limitation on date fields. The technique I am about to share with you will fail if there is any logic that requires CRM to evaluate the date as CRM will instantly squish the date into a Delphi date object that has this limitation and odd things could happen. If you are not doing anything too complicated with the date however this will probably work... This is a hack so please read my hack faq.

Here are the steps to implement:

1. Create a new text field with the same name as the date field with the letters str at the end of the name. For example your date field might be pers_birthday so your text field should be called pers_birthdaystr.

2. This field must be added onto the screen that has the date field. The javascript will hide this field from the user so they won't see it.

3. In the screen that has this field the following Custom Content must be added:

<script>
function HideField (fieldName) {
 document.getElementById('_Capt' + fieldName).style.visibility='hidden';
 document.getElementById('_Data' + fieldName).style.visibility='hidden';
}
function FormatDate(dateStr) {
 // accepts a date in the format of yyyy-mm-dd and formats it into the date format in the user preferences
 var dateFormat = CurrentUser.user_prf.toLowerCase();
 var pos = 0; var dayPos = 0; var monthPos = 0; var yearPos = 0; var seperator='';
 for (i = 1; i<dateFormat.length; i++)
  switch (dateFormat.substr(i, 1)) {
  case 'd': dayPos = pos; break;
  case 'm': monthPos = pos; break;
  case 'y': yearPos = pos; break;
  default : if (seperator=='') seperator = dateFormat.substr(i, 1); pos++;
  };
 var dateParts = dateStr.match(/[0123456789]+/g);
 var formattedDate = '';
 for (i=0; i<=2; i++) {
  switch (i) {
  case dayPos: formattedDate += dateParts[2]; break;
  case monthPos: formattedDate += dateParts[1]; break;
  case yearPos: formattedDate += dateParts[0]; break;
  }
  if (i<2) formattedDate += seperator;
 }
 return formattedDate;
}
function GetDateFromStr(fieldName) {
 var dateStr = document.getElementById('_HIDDEN' + fieldName + 'str').value;
 if (dateStr != '') {
  var formattedDate = FormatDate(dateStr);
  var dateField = document.getElementById(fieldName);
  if (dateField != null) {
   dateField.value = formattedDate;
  } else {
   var dataSpan = document.getElementById('_Data' + fieldName);
   dataSpan.appendChild(document.createTextNode(formattedDate));
  }
 }
 HideField(fieldName + 'str');
}
window.attachEvent('onload',
 function () {
  GetDateFromStr('pers_birthday'); // Note you must change this to have the name of your date field
 }
);
</script>


4. Next you need to create a table level script on the entity that the date field is on:

// ******** TLS Events ********
function InsertRecord() {
 StoreInString('pers_birthday'); // Note you must change this to have the name of your date field
}
function PostInsertRecord() {}
function UpdateRecord()
{
 StoreInString('pers_birthday '); // Note you must change this to have the name of your date field
}
function DeleteRecord() {}
// ******** Other functions ********
function StoreInString(fieldName) {
 if (defined(FormValues(fieldName))) {
  var sqlDate = DateInput2SQLDate(FormValues(fieldName));
  Values(fieldName + 'str') = sqlDate;
  Values(fieldName) = sqlDate;
 }
}
function defined(x) { return (x+'' != 'undefined'); }
function ZPad(x, n) { return String(new Array(n+1).join("0") + x).slice(-1 * n); }
function DateInput2SQLDate(strDate) {
 // Converts a date (only date-no time) input into a SQL date formatted yyyy-mm-dd
 var dateFormat = CurrentUser['user_prf'].toLowerCase();
 var pos = 0; var dayPos = 0; var monthPos = 0; var yearPos = 0; var seperator='';
 for (i = 1; i<dateFormat.length; i++)
  switch (dateFormat.substr(i, 1)) {
  case 'd': dayPos = pos; break;
  case 'm': monthPos = pos; break;
  case 'y': yearPos = pos; break;
  default : if (seperator=='') seperator = dateFormat.substr(i, 1); pos++;
  };
 var dateParts = strDate.match(/[0123456789]+/g);
 var day = ZPad(dateParts[dayPos], 2);
 var month = ZPad(dateParts[monthPos], 2);
 var year = dateParts[yearPos];
 var sqlDate = year + '-' + month + '-' + day;
 return sqlDate;
}