Bug 1527535 - Remove datepicker widget from address book; r=mkmelin
authorGeoff Lankow <geoff@darktrojan.net>
Thu, 21 Feb 2019 14:15:09 +1300
changeset 25909 3958330210079f900dc3bda64de3559e9f4ba4c0
parent 25908 753ca1edaf6528480c3fb7c74c0c9f7ee3d09737
child 25910 250655508f079c28f1987c4d3c88f0d2013abe07
push id15542
push usergeoff@darktrojan.net
push dateThu, 21 Feb 2019 01:17:53 +0000
treeherdercomm-central@395833021007 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmkmelin
bugs1527535
Bug 1527535 - Remove datepicker widget from address book; r=mkmelin
common/bindings/datetimepicker.xml
mail/base/content/bindings.css
mail/base/jar.mn
mail/components/addrbook/content/abCard.inc.xul
mail/components/addrbook/content/abCard.js
mail/locales/en-US/chrome/messenger/addressbook/abCard.dtd
mail/locales/en-US/chrome/messenger/datetimepicker.dtd
mail/locales/jar.mn
mail/themes/linux/jar.mn
mail/themes/linux/mail/addrbook/cardDialog.css
mail/themes/linux/mail/datetimepicker.css
mail/themes/osx/jar.mn
mail/themes/osx/mail/addrbook/cardDialog.css
mail/themes/osx/mail/datetimepicker.css
mail/themes/windows/jar.mn
mail/themes/windows/mail/addrbook/cardDialog.css
mail/themes/windows/mail/datetimepicker.css
deleted file mode 100644
--- a/common/bindings/datetimepicker.xml
+++ /dev/null
@@ -1,1332 +0,0 @@
-<?xml version="1.0"?>
-
-<!-- This Source Code Form is subject to the terms of the Mozilla Public
-   - License, v. 2.0. If a copy of the MPL was not distributed with this
-   - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
-
-<!DOCTYPE bindings [
-<!ENTITY % datetimepickerDTD SYSTEM
-#ifdef MOZ_SUITE
-  "chrome://communicator/locale/datetimepicker.dtd">
-#else
-  "chrome://messenger/locale/datetimepicker.dtd">
-#endif
-  %datetimepickerDTD;
-]>
-
-<bindings id="timepickerBindings"
-   xmlns="http://www.mozilla.org/xbl"
-   xmlns:html="http://www.w3.org/1999/xhtml"
-   xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
-   xmlns:xbl="http://www.mozilla.org/xbl">
-
-  <binding id="datetimepicker-base"
-           extends="chrome://global/content/bindings/general.xml#basecontrol">
-
-    <content align="center">
-      <xul:hbox class="datetimepicker-input-box" align="center"
-                xbl:inherits="context,disabled,readonly">
-        <xul:moz-input-box class="textbox-input-box datetimepicker-input-subbox"
-                           align="center">
-          <html:input class="datetimepicker-input textbox-input" anonid="input-one"
-                      size="2" maxlength="2"
-                      xbl:inherits="disabled,readonly"/>
-        </xul:moz-input-box>
-        <xul:label anonid="sep-first" class="datetimepicker-separator" value=":"/>
-        <xul:moz-input-box class="textbox-input-box datetimepicker-input-subbox"
-                           align="center">
-          <html:input class="datetimepicker-input textbox-input" anonid="input-two"
-                      size="2" maxlength="2"
-                      xbl:inherits="disabled,readonly"/>
-        </xul:moz-input-box>
-        <xul:label anonid="sep-second" class="datetimepicker-separator" value=":"/>
-        <xul:moz-input-box class="textbox-input-box datetimepicker-input-subbox"
-                           align="center">
-          <html:input class="datetimepicker-input textbox-input" anonid="input-three"
-                      size="2" maxlength="2"
-                      xbl:inherits="disabled,readonly"/>
-        </xul:moz-input-box>
-        <xul:moz-input-box class="textbox-input-box datetimepicker-input-subbox"
-                           align="center">
-          <html:input class="datetimepicker-input textbox-input" anonid="input-ampm"
-                      size="2" maxlength="2"
-                      xbl:inherits="disabled,readonly"/>
-        </xul:moz-input-box>
-      </xul:hbox>
-      <xul:spinbuttons anonid="buttons" xbl:inherits="disabled"
-                       onup="this.parentNode._increaseOrDecrease(1);"
-                       ondown="this.parentNode._increaseOrDecrease(-1);"/>
-    </content>
-
-    <implementation>
-      <field name="_dateValue">null</field>
-      <field name="_fieldOne">
-        document.getAnonymousElementByAttribute(this, "anonid", "input-one");
-      </field>
-      <field name="_fieldTwo">
-        document.getAnonymousElementByAttribute(this, "anonid", "input-two");
-      </field>
-      <field name="_fieldThree">
-        document.getAnonymousElementByAttribute(this, "anonid", "input-three");
-      </field>
-      <field name="_fieldAMPM">
-        document.getAnonymousElementByAttribute(this, "anonid", "input-ampm");
-      </field>
-      <field name="_separatorFirst">
-        document.getAnonymousElementByAttribute(this, "anonid", "sep-first");
-      </field>
-      <field name="_separatorSecond">
-        document.getAnonymousElementByAttribute(this, "anonid", "sep-second");
-      </field>
-      <field name="_lastFocusedField">null</field>
-      <field name="_hasEntry">true</field>
-      <field name="_valueEntered">false</field>
-      <field name="attachedControl">null</field>
-
-      <property name="_currentField" readonly="true">
-        <getter>
-          var focusedInput = document.activeElement;
-          if (focusedInput == this._fieldOne ||
-              focusedInput == this._fieldTwo ||
-              focusedInput == this._fieldThree ||
-              focusedInput == this._fieldAMPM)
-            return focusedInput;
-          return this._lastFocusedField || this._fieldOne;
-        </getter>
-      </property>
-
-      <property name="dateValue" onget="return new Date(this._dateValue);">
-        <setter>
-          <![CDATA[
-            if (!(val instanceof Date))
-              throw "Invalid Date";
-
-            this._setValueNoSync(val);
-            if (this.attachedControl)
-              this.attachedControl._setValueNoSync(val);
-            return val;
-          ]]>
-        </setter>
-      </property>
-
-      <property name="readOnly" onset="if (val) this.setAttribute('readonly', 'true');
-                                       else this.removeAttribute('readonly'); return val;"
-                                onget="return this.getAttribute('readonly') == 'true';"/>
-
-      <method name="_fireEvent">
-        <parameter name="aEventName"/>
-        <parameter name="aTarget"/>
-        <body>
-          var event = document.createEvent("Events");
-          event.initEvent(aEventName, true, true);
-          return !aTarget.dispatchEvent(event);
-        </body>
-      </method>
-
-      <method name="_setValueOnChange">
-        <parameter name="aField"/>
-        <body>
-          <![CDATA[
-            if (!this._hasEntry)
-              return;
-
-            if (aField == this._fieldOne ||
-                aField == this._fieldTwo ||
-                aField == this._fieldThree) {
-              var value = Number(aField.value);
-              if (isNaN(value))
-                value = 0;
-
-              value = this._constrainValue(aField, value, true);
-              this._setFieldValue(aField, value);
-            }
-          ]]>
-        </body>
-      </method>
-
-      <method name="_init">
-        <body/>
-      </method>
-
-      <constructor>
-        this._init();
-
-        var cval = this.getAttribute("value");
-        if (cval) {
-          try {
-            this.value = cval;
-            return;
-          } catch (ex) { }
-        }
-        this.dateValue = new Date();
-      </constructor>
-
-      <destructor>
-        if (this.attachedControl) {
-          this.attachedControl.attachedControl = null;
-          this.attachedControl = null;
-        }
-      </destructor>
-
-    </implementation>
-
-    <handlers>
-      <handler event="focus" phase="capturing">
-        <![CDATA[
-          var target = event.originalTarget;
-          if (target == this._fieldOne ||
-              target == this._fieldTwo ||
-              target == this._fieldThree ||
-              target == this._fieldAMPM)
-            this._lastFocusedField = target;
-        ]]>
-      </handler>
-
-      <handler event="keypress">
-        <![CDATA[
-          if (this._hasEntry && event.charCode &&
-              this._currentField != this._fieldAMPM &&
-                !(event.altKey || event.ctrlKey || event.metaKey) &&
-              (event.charCode < 48 || event.charCode > 57))
-            event.preventDefault();
-        ]]>
-      </handler>
-
-      <handler event="keypress" keycode="VK_UP">
-        if (this._hasEntry)
-          this._increaseOrDecrease(1);
-      </handler>
-      <handler event="keypress" keycode="VK_DOWN">
-        if (this._hasEntry)
-          this._increaseOrDecrease(-1);
-      </handler>
-
-      <handler event="input">
-        this._valueEntered = true;
-      </handler>
-
-      <handler event="change">
-        this._setValueOnChange(event.originalTarget);
-      </handler>
-    </handlers>
-
-  </binding>
-
-  <binding id="timepicker"
-#ifdef MOZ_SUITE
-           extends="chrome://communicator/content/bindings/datetimepicker.xml#datetimepicker-base">
-#else
-           extends="chrome://messenger/content/datetimepicker.xml#datetimepicker-base">
-#endif
-    <implementation>
-      <field name="is24HourClock">false</field>
-      <field name="hourLeadingZero">false</field>
-      <field name="minuteLeadingZero">true</field>
-      <field name="secondLeadingZero">true</field>
-      <field name="amIndicator">"AM"</field>
-      <field name="pmIndicator">"PM"</field>
-
-      <field name="hourField">null</field>
-      <field name="minuteField">null</field>
-      <field name="secondField">null</field>
-
-      <property name="value">
-        <getter>
-          <![CDATA[
-            var minute = this._dateValue.getMinutes();
-            if (minute < 10)
-              minute = "0" + minute;
-
-            var second = this._dateValue.getSeconds();
-            if (second < 10)
-              second = "0" + second;
-            return this._dateValue.getHours() + ":" + minute + ":" + second;
-          ]]>
-        </getter>
-        <setter>
-          <![CDATA[
-            var items = val.match(/^([0-9]{1,2})\:([0-9]{1,2})\:?([0-9]{1,2})?$/);
-            if (!items)
-              throw "Invalid Time";
-
-            var dt = this.dateValue;
-            dt.setHours(items[1]);
-            dt.setMinutes(items[2]);
-            dt.setSeconds(items[3] ? items[3] : 0);
-            this.dateValue = dt;
-            return val;
-          ]]>
-        </setter>
-      </property>
-      <property name="hour" onget="return this._dateValue.getHours();">
-        <setter>
-          <![CDATA[
-            var valnum = Number(val);
-            if (isNaN(valnum) || valnum < 0 || valnum > 23)
-              throw "Invalid Hour";
-            this._setFieldValue(this.hourField, valnum);
-            return val;
-          ]]>
-        </setter>
-      </property>
-      <property name="minute" onget="return this._dateValue.getMinutes();">
-        <setter>
-          <![CDATA[
-            var valnum = Number(val);
-            if (isNaN(valnum) || valnum < 0 || valnum > 59)
-              throw "Invalid Minute";
-            this._setFieldValue(this.minuteField, valnum);
-            return val;
-          ]]>
-        </setter>
-      </property>
-      <property name="second" onget="return this._dateValue.getSeconds();">
-        <setter>
-          <![CDATA[
-            var valnum = Number(val);
-            if (isNaN(valnum) || valnum < 0 || valnum > 59)
-              throw "Invalid Second";
-            this._setFieldValue(this.secondField, valnum);
-            return val;
-          ]]>
-        </setter>
-      </property>
-      <property name="isPM">
-        <getter>
-          <![CDATA[
-            return (this.hour >= 12);
-          ]]>
-        </getter>
-        <setter>
-          <![CDATA[
-            if (val) {
-              if (this.hour < 12)
-                this.hour += 12;
-            } else if (this.hour >= 12) {
-              this.hour -= 12;
-            }
-            return val;
-          ]]>
-        </setter>
-      </property>
-      <property name="hideSeconds">
-        <getter>
-          return (this.getAttribute("hideseconds") == "true");
-        </getter>
-        <setter>
-          if (val)
-            this.setAttribute("hideseconds", "true");
-          else
-            this.removeAttribute("hideseconds");
-          if (this.secondField)
-            this.secondField.parentNode.collapsed = val;
-          this._separatorSecond.collapsed = val;
-          return val;
-        </setter>
-      </property>
-      <property name="increment">
-        <getter>
-          <![CDATA[
-            var increment = this.getAttribute("increment");
-            increment = Number(increment);
-            if (isNaN(increment) || increment <= 0 || increment >= 60)
-              return 1;
-            return increment;
-          ]]>
-        </getter>
-        <setter>
-          <![CDATA[
-            if (typeof val == "number")
-              this.setAttribute("increment", val);
-            return val;
-          ]]>
-        </setter>
-      </property>
-
-      <method name="_setValueNoSync">
-        <parameter name="aValue"/>
-        <body>
-          <![CDATA[
-            var dt = new Date(aValue);
-            if (!isNaN(dt)) {
-              this._dateValue = dt;
-              this.setAttribute("value", this.value);
-              this._updateUI(this.hourField, this.hour);
-              this._updateUI(this.minuteField, this.minute);
-              this._updateUI(this.secondField, this.second);
-            }
-          ]]>
-        </body>
-      </method>
-      <method name="_increaseOrDecrease">
-        <parameter name="aDir"/>
-        <body>
-          <![CDATA[
-            if (this.disabled || this.readOnly)
-              return;
-
-            var field = this._currentField;
-            if (this._valueEntered)
-              this._setValueOnChange(field);
-
-            if (field == this._fieldAMPM) {
-              this.isPM = !this.isPM;
-              this._fireEvent("change", this);
-            } else {
-              var oldval;
-              var change = aDir;
-              if (field == this.hourField) {
-                oldval = this.hour;
-              } else if (field == this.minuteField) {
-                oldval = this.minute;
-                change *= this.increment;
-              } else if (field == this.secondField) {
-                oldval = this.second;
-              }
-
-              var newval = this._constrainValue(field, oldval + change, false);
-
-              if (field == this.hourField)
-                this.hour = newval;
-              else if (field == this.minuteField)
-                this.minute = newval;
-              else if (field == this.secondField)
-                this.second = newval;
-
-              if (oldval != newval)
-                this._fireEvent("change", this);
-            }
-            field.select();
-          ]]>
-        </body>
-      </method>
-      <method name="_setFieldValue">
-        <parameter name="aField"/>
-        <parameter name="aValue"/>
-        <body>
-          <![CDATA[
-            if (aField == this.hourField)
-              this._dateValue.setHours(aValue);
-            else if (aField == this.minuteField)
-              this._dateValue.setMinutes(aValue);
-            else if (aField == this.secondField)
-              this._dateValue.setSeconds(aValue);
-
-            this.setAttribute("value", this.value);
-            this._updateUI(aField, aValue);
-
-            if (this.attachedControl)
-              this.attachedControl._setValueNoSync(this._dateValue);
-          ]]>
-        </body>
-      </method>
-      <method name="_updateUI">
-        <parameter name="aField"/>
-        <parameter name="aValue"/>
-        <body>
-          <![CDATA[
-            this._valueEntered = false;
-
-            var prependZero = false;
-            if (aField == this.hourField) {
-              prependZero = this.hourLeadingZero;
-              if (!this.is24HourClock) {
-                if (aValue > 12)
-                  aValue -= 12;
-                else if (aValue == 0)
-                  aValue = 12;
-                this._fieldAMPM.value = this.isPM ? this.pmIndicator :
-                  this.amIndicator;
-              }
-            } else if (aField == this.minuteField) {
-              prependZero = this.minuteLeadingZero;
-            } else if (aField == this.secondField) {
-              prependZero = this.secondLeadingZero;
-            }
-
-            if (prependZero && aValue < 10)
-              aField.value = "0" + aValue;
-            else
-              aField.value = aValue;
-          ]]>
-        </body>
-      </method>
-      <method name="_constrainValue">
-        <parameter name="aField"/>
-        <parameter name="aValue"/>
-        <parameter name="aNoWrap"/>
-        <body>
-          <![CDATA[
-            // aNoWrap is true when the user entered a value, so just
-            // constrain within limits. If false, the value is being
-            // incremented or decremented, so wrap around values
-            var max = 60;
-            if (aField == this.hourField) {
-              max = 24;
-              // User input in the hour field should be adjusted as
-              // needed for 12-hour vs. 24-hour time.
-              if (aNoWrap && !this.is24HourClock) {
-                if (aValue && aValue < 12 && this.isPM)
-                  aValue += 12;
-                else if (aValue == 12 && !this.isPM)
-                  aValue = 0;
-              }
-            }
-            if (aValue < 0)
-              return aNoWrap ? 0 : max + aValue;
-            if (aValue >= max)
-              return aNoWrap ? max - 1 : aValue - max;
-            return aValue;
-          ]]>
-        </body>
-      </method>
-      <method name="_init">
-        <body>
-          <![CDATA[
-            const {Services} = ChromeUtils.import("resource://gre/modules/Services.jsm");
-
-            this.hourField = this._fieldOne;
-            this.minuteField = this._fieldTwo;
-            this.secondField = this._fieldThree;
-
-            var numberOrder = /^(\D*)\s*(\d+)(\D*)(\d+)(\D*)(\d+)\s*(\D*)$/;
-
-            // XXX TODO: The following hack should be fixed once Intl.Locale arrives in bug 1433303.
-            var locale = Services.locale.regionalPrefsLocales[0];
-            if (locale.includes("-u-"))
-              locale += "-ca-gregory-nu-latn";
-            else
-              locale += "-u-ca-gregory-nu-latn";
-            var dtf = new Services.intl.DateTimeFormat(locale, { timeStyle: "long" });
-
-            var pmTime = dtf.format(new Date(2000, 0, 1, 16, 7, 9));
-            var numberFields = pmTime.match(numberOrder);
-            if (numberFields) {
-              this._separatorFirst.value = numberFields[3];
-              this._separatorSecond.value = numberFields[5];
-              if (Number(numberFields[2]) > 12)
-                this.is24HourClock = true;
-              else
-                this.pmIndicator = numberFields[1] || numberFields[7];
-            }
-
-            var amTime = dtf.format(new Date(2000, 0, 1, 1, 7, 9));
-            numberFields = amTime.match(numberOrder);
-            if (numberFields) {
-              this.hourLeadingZero = (numberFields[2].length > 1);
-              this.minuteLeadingZero = (numberFields[4].length > 1);
-              this.secondLeadingZero = (numberFields[6].length > 1);
-
-              if (!this.is24HourClock) {
-                this.amIndicator = numberFields[1] || numberFields[7];
-                if (numberFields[1]) {
-                  var mfield = this._fieldAMPM.parentNode;
-                  var mcontainer = mfield.parentNode;
-                  mcontainer.insertBefore(mfield, mcontainer.firstChild);
-                }
-                var size = (numberFields[1] || numberFields[7]).length;
-                if (this.pmIndicator.length > size)
-                  size = this.pmIndicator.length;
-                this._fieldAMPM.size = size;
-                this._fieldAMPM.maxLength = size;
-              } else {
-                this._fieldAMPM.parentNode.collapsed = true;
-              }
-            }
-
-            this.hideSeconds = this.hideSeconds;
-          ]]>
-        </body>
-      </method>
-    </implementation>
-
-    <handlers>
-      <handler event="keypress">
-        <![CDATA[
-          // just allow any printable character to switch the AM/PM state
-          if (event.charCode && !this.disabled && !this.readOnly &&
-              this._currentField == this._fieldAMPM) {
-            this.isPM = !this.isPM;
-            this._fieldAMPM.select();
-            this._fireEvent("change", this);
-            event.preventDefault();
-          }
-        ]]>
-      </handler>
-    </handlers>
-
-  </binding>
-
-  <binding id="datepicker"
-#ifdef MOZ_SUITE
-           extends="chrome://communicator/content/bindings/datetimepicker.xml#datetimepicker-base">
-#else
-           extends="chrome://messenger/content/datetimepicker.xml#datetimepicker-base">
-#endif
-    <implementation>
-      <field name="yearLeadingZero">false</field>
-      <field name="monthLeadingZero">true</field>
-      <field name="dateLeadingZero">true</field>
-
-      <field name="yearField"/>
-      <field name="monthField"/>
-      <field name="dateField"/>
-
-      <property name="value">
-        <getter>
-          <![CDATA[
-            var month = this._dateValue.getMonth();
-            month = (month < 9) ? month = "0" + ++month : month + 1;
-
-            var date = this._dateValue.getDate();
-            if (date < 10)
-              date = "0" + date;
-            return this._dateValue.getFullYear() + "-" + month + "-" + date;
-          ]]>
-
-        </getter>
-        <setter>
-          <![CDATA[
-            var results = val.match(/^([0-9]{1,4})\-([0-9]{1,2})\-([0-9]{1,2})$/);
-            if (!results)
-              throw "Invalid Date";
-
-            this.dateValue = new Date(results[1] + "/" + results[2] + "/" + results[3]);
-            this.setAttribute("value", this.value);
-            return val;
-          ]]>
-        </setter>
-      </property>
-      <property name="year" onget="return this._dateValue.getFullYear();">
-        <setter>
-          <![CDATA[
-            var valnum = Number(val);
-            if (isNaN(valnum) || valnum < 1 || valnum > 9999)
-              throw "Invalid Year";
-            this._setFieldValue(this.yearField, valnum);
-            return val;
-          ]]>
-        </setter>
-      </property>
-      <property name="month" onget="return this._dateValue.getMonth();">
-        <setter>
-          <![CDATA[
-            var valnum = Number(val);
-            if (isNaN(valnum) || valnum < 0 || valnum > 11)
-              throw "Invalid Month";
-            this._setFieldValue(this.monthField, valnum);
-            return val;
-          ]]>
-        </setter>
-      </property>
-      <property name="date" onget="return this._dateValue.getDate();">
-        <setter>
-          <![CDATA[
-            var valnum = Number(val);
-            if (isNaN(valnum) || valnum < 1 || valnum > 31)
-              throw "Invalid Date";
-            this._setFieldValue(this.dateField, valnum);
-            return val;
-          ]]>
-        </setter>
-      </property>
-      <property name="open" onget="return false;" onset="return val;"/>
-
-      <property name="displayedMonth" onget="return this.month;"
-                onset="this.month = val; return val;"/>
-      <property name="displayedYear" onget="return this.year;"
-                onset="this.year = val; return val;"/>
-
-      <method name="_setValueNoSync">
-        <parameter name="aValue"/>
-        <body>
-          <![CDATA[
-            var dt = new Date(aValue);
-            if (!isNaN(dt)) {
-              this._dateValue = dt;
-              this.setAttribute("value", this.value);
-              this._updateUI(this.yearField, this.year);
-              this._updateUI(this.monthField, this.month);
-              this._updateUI(this.dateField, this.date);
-            }
-          ]]>
-        </body>
-      </method>
-      <method name="_increaseOrDecrease">
-        <parameter name="aDir"/>
-        <body>
-          <![CDATA[
-            if (this.disabled || this.readOnly)
-              return;
-
-            var field = this._currentField;
-            if (this._valueEntered)
-              this._setValueOnChange(field);
-
-            var oldval;
-            if (field == this.yearField)
-              oldval = this.year;
-            else if (field == this.monthField)
-              oldval = this.month;
-            else if (field == this.dateField)
-              oldval = this.date;
-
-            var newval = this._constrainValue(field, oldval + aDir, false);
-
-            if (field == this.yearField)
-              this.year = newval;
-            else if (field == this.monthField)
-              this.month = newval;
-            else if (field == this.dateField)
-              this.date = newval;
-
-            if (oldval != newval)
-              this._fireEvent("change", this);
-            field.select();
-          ]]>
-        </body>
-      </method>
-      <method name="_setFieldValue">
-        <parameter name="aField"/>
-        <parameter name="aValue"/>
-        <body>
-          <![CDATA[
-            if (aField == this.yearField) {
-              let oldDate = this.date;
-              this._dateValue.setFullYear(aValue);
-              if (oldDate != this.date) {
-                this._dateValue.setDate(0);
-                this._updateUI(this.dateField, this.date);
-              }
-            } else if (aField == this.monthField) {
-              let oldDate = this.date;
-              this._dateValue.setMonth(aValue);
-              if (oldDate != this.date) {
-                this._dateValue.setDate(0);
-                this._updateUI(this.dateField, this.date);
-              }
-            } else if (aField == this.dateField) {
-              this._dateValue.setDate(aValue);
-            }
-
-            this.setAttribute("value", this.value);
-            this._updateUI(aField, aValue);
-
-            if (this.attachedControl)
-              this.attachedControl._setValueNoSync(this._dateValue);
-          ]]>
-        </body>
-      </method>
-      <method name="_updateUI">
-        <parameter name="aField"/>
-        <parameter name="aValue"/>
-        <body>
-          <![CDATA[
-            this._valueEntered = false;
-
-            var prependZero = false;
-            if (aField == this.yearField) {
-              if (this.yearLeadingZero) {
-                aField.value = ("000" + aValue).slice(-4);
-                return;
-              }
-            } else if (aField == this.monthField) {
-              aValue++;
-              prependZero = this.monthLeadingZero;
-            } else if (aField == this.dateField) {
-              prependZero = this.dateLeadingZero;
-            }
-            if (prependZero && aValue < 10)
-              aField.value = "0" + aValue;
-            else
-              aField.value = aValue;
-          ]]>
-        </body>
-      </method>
-      <method name="_constrainValue">
-        <parameter name="aField"/>
-        <parameter name="aValue"/>
-        <parameter name="aNoWrap"/>
-        <body>
-          <![CDATA[
-            // the month will be 1 to 12 if entered by the user, so subtract 1
-            if (aNoWrap && aField == this.monthField)
-              aValue--;
-
-            if (aField == this.dateField) {
-              if (aValue < 1)
-                return new Date(this.year, this.month + 1, 0).getDate();
-
-              var currentMonth = this.month;
-              var dt = new Date(this.year, currentMonth, aValue);
-              return (dt.getMonth() != currentMonth ? 1 : aValue);
-            }
-            var min = (aField == this.monthField) ? 0 : 1;
-            var max = (aField == this.monthField) ? 11 : 9999;
-            if (aValue < min)
-              return aNoWrap ? min : max;
-            if (aValue > max)
-              return aNoWrap ? max : min;
-            return aValue;
-          ]]>
-        </body>
-      </method>
-      <method name="_init">
-        <body>
-          <![CDATA[
-            const {Services} = ChromeUtils.import("resource://gre/modules/Services.jsm");
-
-            // We'll default to YYYY/MM/DD to start.
-            var yfield = "input-one";
-            var mfield = "input-two";
-            var dfield = "input-three";
-            var twoDigitYear = false;
-            this.yearLeadingZero = true;
-            this.monthLeadingZero = true;
-            this.dateLeadingZero = true;
-
-            var numberOrder = /^(\D*)\s*(\d+)(\D*)(\d+)(\D*)(\d+)\s*(\D*)$/;
-
-            // XXX TODO: The following hack should be fixed once Intl.Locale arrives in bug 1433303.
-            var locale = Services.locale.regionalPrefsLocales[0];
-            if (locale.includes("-u-"))
-              locale += "-ca-gregory-nu-latn";
-            else
-              locale += "-u-ca-gregory-nu-latn";
-            var dtf = new Services.intl.DateTimeFormat(locale, { dateStyle: "short" });
-
-            var dt = dtf.format(new Date(2002, 9, 4));
-            var numberFields = dt.match(numberOrder);
-            if (numberFields) {
-              this._separatorFirst.value = numberFields[3];
-              this._separatorSecond.value = numberFields[5];
-
-              var yi = 2, mi = 4, di = 6;
-
-              function fieldForNumber(i) {
-                if (i == 2)
-                  return "input-one";
-                if (i == 4)
-                  return "input-two";
-                return "input-three";
-              }
-
-              for (var i = 1; i < numberFields.length; i++) {
-                switch (Number(numberFields[i])) {
-                  case 2:
-                    twoDigitYear = true; // fall through
-                  case 2002:
-                    yi = i;
-                    yfield = fieldForNumber(i);
-                    break;
-                  case 9:
-                  case 10:
-                    mi = i;
-                    mfield = fieldForNumber(i);
-                    break;
-                  case 4:
-                    di = i;
-                    dfield = fieldForNumber(i);
-                    break;
-                }
-              }
-
-              this.yearLeadingZero = (numberFields[yi].length > 1);
-              this.monthLeadingZero = (numberFields[mi].length > 1);
-              this.dateLeadingZero = (numberFields[di].length > 1);
-            }
-
-            this.yearField = document.getAnonymousElementByAttribute(this, "anonid", yfield);
-            if (!twoDigitYear)
-              this.yearField.parentNode.classList.add("datetimepicker-input-subbox", "datetimepicker-year");
-            this.monthField = document.getAnonymousElementByAttribute(this, "anonid", mfield);
-            this.dateField = document.getAnonymousElementByAttribute(this, "anonid", dfield);
-
-            this._fieldAMPM.parentNode.collapsed = true;
-            this.yearField.size = twoDigitYear ? 2 : 4;
-            this.yearField.maxLength = twoDigitYear ? 2 : 4;
-          ]]>
-        </body>
-      </method>
-    </implementation>
-
-  </binding>
-
-  <binding id="datepicker-grid"
-#ifdef MOZ_SUITE
-           extends="chrome://communicator/content/bindings/datetimepicker.xml#datepicker">
-#else
-           extends="chrome://messenger/content/datetimepicker.xml#datepicker">
-#endif
-    <content>
-      <vbox class="datepicker-mainbox"
-            xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
-        <hbox class="datepicker-monthbox" align="center">
-          <button class="datepicker-previous datepicker-button" type="repeat"
-                  xbl:inherits="disabled"
-                  oncommand="document.getBindingParent(this)._increaseOrDecreaseMonth(-1);"/>
-          <spacer flex="1"/>
-          <deck anonid="monthlabeldeck">
-            <label class="datepicker-gridlabel" value=""/>
-            <label class="datepicker-gridlabel" value=""/>
-            <label class="datepicker-gridlabel" value=""/>
-            <label class="datepicker-gridlabel" value=""/>
-            <label class="datepicker-gridlabel" value=""/>
-            <label class="datepicker-gridlabel" value=""/>
-            <label class="datepicker-gridlabel" value=""/>
-            <label class="datepicker-gridlabel" value=""/>
-            <label class="datepicker-gridlabel" value=""/>
-            <label class="datepicker-gridlabel" value=""/>
-            <label class="datepicker-gridlabel" value=""/>
-            <label class="datepicker-gridlabel" value=""/>
-          </deck>
-          <label anonid="yearlabel" class="datepicker-gridlabel"/>
-          <spacer flex="1"/>
-          <button class="datepicker-next datepicker-button" type="repeat"
-                  xbl:inherits="disabled"
-                  oncommand="document.getBindingParent(this)._increaseOrDecreaseMonth(1);"/>
-        </hbox>
-        <grid class="datepicker-grid" role="grid">
-          <columns>
-            <column class="datepicker-gridrow" flex="1"/>
-            <column class="datepicker-gridrow" flex="1"/>
-            <column class="datepicker-gridrow" flex="1"/>
-            <column class="datepicker-gridrow" flex="1"/>
-            <column class="datepicker-gridrow" flex="1"/>
-            <column class="datepicker-gridrow" flex="1"/>
-            <column class="datepicker-gridrow" flex="1"/>
-          </columns>
-          <rows anonid="datebox">
-            <row anonid="dayofweekbox">
-              <label class="datepicker-weeklabel" role="columnheader"/>
-              <label class="datepicker-weeklabel" role="columnheader"/>
-              <label class="datepicker-weeklabel" role="columnheader"/>
-              <label class="datepicker-weeklabel" role="columnheader"/>
-              <label class="datepicker-weeklabel" role="columnheader"/>
-              <label class="datepicker-weeklabel" role="columnheader"/>
-              <label class="datepicker-weeklabel" role="columnheader"/>
-            </row>
-            <row>
-              <label class="datepicker-gridlabel" role="gridcell"/>
-              <label class="datepicker-gridlabel" role="gridcell"/>
-              <label class="datepicker-gridlabel" role="gridcell"/>
-              <label class="datepicker-gridlabel" role="gridcell"/>
-              <label class="datepicker-gridlabel" role="gridcell"/>
-              <label class="datepicker-gridlabel" role="gridcell"/>
-              <label class="datepicker-gridlabel" role="gridcell"/>
-            </row>
-            <row>
-              <label class="datepicker-gridlabel" role="gridcell"/>
-              <label class="datepicker-gridlabel" role="gridcell"/>
-              <label class="datepicker-gridlabel" role="gridcell"/>
-              <label class="datepicker-gridlabel" role="gridcell"/>
-              <label class="datepicker-gridlabel" role="gridcell"/>
-              <label class="datepicker-gridlabel" role="gridcell"/>
-              <label class="datepicker-gridlabel" role="gridcell"/>
-            </row>
-            <row>
-              <label class="datepicker-gridlabel" role="gridcell"/>
-              <label class="datepicker-gridlabel" role="gridcell"/>
-              <label class="datepicker-gridlabel" role="gridcell"/>
-              <label class="datepicker-gridlabel" role="gridcell"/>
-              <label class="datepicker-gridlabel" role="gridcell"/>
-              <label class="datepicker-gridlabel" role="gridcell"/>
-              <label class="datepicker-gridlabel" role="gridcell"/>
-            </row>
-            <row>
-              <label class="datepicker-gridlabel" role="gridcell"/>
-              <label class="datepicker-gridlabel" role="gridcell"/>
-              <label class="datepicker-gridlabel" role="gridcell"/>
-              <label class="datepicker-gridlabel" role="gridcell"/>
-              <label class="datepicker-gridlabel" role="gridcell"/>
-              <label class="datepicker-gridlabel" role="gridcell"/>
-              <label class="datepicker-gridlabel" role="gridcell"/>
-            </row>
-            <row>
-              <label class="datepicker-gridlabel" role="gridcell"/>
-              <label class="datepicker-gridlabel" role="gridcell"/>
-              <label class="datepicker-gridlabel" role="gridcell"/>
-              <label class="datepicker-gridlabel" role="gridcell"/>
-              <label class="datepicker-gridlabel" role="gridcell"/>
-              <label class="datepicker-gridlabel" role="gridcell"/>
-              <label class="datepicker-gridlabel" role="gridcell"/>
-            </row>
-            <row>
-              <label class="datepicker-gridlabel" role="gridcell"/>
-              <label class="datepicker-gridlabel" role="gridcell"/>
-              <label class="datepicker-gridlabel" role="gridcell"/>
-              <label class="datepicker-gridlabel" role="gridcell"/>
-              <label class="datepicker-gridlabel" role="gridcell"/>
-              <label class="datepicker-gridlabel" role="gridcell"/>
-              <label class="datepicker-gridlabel" role="gridcell"/>
-            </row>
-          </rows>
-        </grid>
-      </vbox>
-    </content>
-
-    <implementation>
-      <field name="_hasEntry">false</field>
-      <field name="_weekStart">&firstdayofweek.default;</field>
-      <field name="_displayedDate">null</field>
-      <field name="_todayItem">null</field>
-
-      <field name="yearField">
-        document.getAnonymousElementByAttribute(this, "anonid", "yearlabel");
-      </field>
-      <field name="monthField">
-        document.getAnonymousElementByAttribute(this, "anonid", "monthlabeldeck");
-      </field>
-      <field name="dateField">
-        document.getAnonymousElementByAttribute(this, "anonid", "datebox");
-      </field>
-
-      <field name="_selectedItem">null</field>
-
-      <property name="selectedItem" onget="return this._selectedItem">
-        <setter>
-          <![CDATA[
-            if (!val.value)
-              return val;
-            if (val.parentNode.parentNode != this.dateField)
-              return val;
-
-            if (this._selectedItem)
-              this._selectedItem.removeAttribute("selected");
-            this._selectedItem = val;
-            val.setAttribute("selected", "true");
-            this._displayedDate.setDate(val.value);
-            return val;
-          ]]>
-        </setter>
-      </property>
-
-      <property name="displayedMonth">
-        <getter>
-          return this._displayedDate.getMonth();
-        </getter>
-        <setter>
-          this._updateUI(this.monthField, val, true);
-          return val;
-        </setter>
-      </property>
-      <property name="displayedYear">
-        <getter>
-          return this._displayedDate.getFullYear();
-        </getter>
-        <setter>
-          this._updateUI(this.yearField, val, true);
-          return val;
-        </setter>
-      </property>
-
-      <method name="_init">
-        <body>
-          <![CDATA[
-            const {Services} = ChromeUtils.import("resource://gre/modules/Services.jsm");
-
-            // XXX TODO: The following hack should be fixed once Intl.Locale arrives in bug 1433303.
-            var locale = Services.locale.regionalPrefsLocales[0];
-            if (locale.includes("-u-"))
-              locale += "-ca-gregory";
-            else
-              locale += "-u-ca-gregory";
-            var dtfMonth = new Services.intl.DateTimeFormat(locale, {month: "long", timeZone: "UTC"});
-            var dtfWeekday = new Services.intl.DateTimeFormat(locale, {weekday: "narrow"});
-
-            var monthLabel = this.monthField.firstChild;
-            var tempDate = new Date(Date.UTC(2005, 0, 1));
-            for (var month = 0; month < 12; month++) {
-              tempDate.setUTCMonth(month);
-              monthLabel.setAttribute("value", dtfMonth.format(tempDate));
-              monthLabel = monthLabel.nextSibling;
-            }
-
-            var fdow = Number(this.getAttribute("firstdayofweek"));
-            if (!isNaN(fdow) && fdow >= 0 && fdow <= 6)
-              this._weekStart = fdow;
-
-            var weekbox = document.getAnonymousElementByAttribute(this, "anonid", "dayofweekbox").childNodes;
-            var date = new Date();
-            date.setDate(date.getDate() - (date.getDay() - this._weekStart));
-            for (var i = 0; i < weekbox.length; i++) {
-              weekbox[i].value = dtfWeekday.format(date);
-              date.setDate(date.getDate() + 1);
-            }
-          ]]>
-        </body>
-      </method>
-      <method name="_setValueNoSync">
-        <parameter name="aValue"/>
-        <body>
-          <![CDATA[
-            var dt = new Date(aValue);
-            if (!isNaN(dt)) {
-              this._dateValue = dt;
-              this.setAttribute("value", this.value);
-              this._updateUI();
-            }
-          ]]>
-        </body>
-      </method>
-      <method name="_updateUI">
-        <parameter name="aField"/>
-        <parameter name="aValue"/>
-        <parameter name="aCheckMonth"/>
-        <body>
-          <![CDATA[
-            var date;
-            var currentMonth;
-            if (aCheckMonth) {
-              if (!this._displayedDate)
-                this._displayedDate = this.dateValue;
-
-              var expectedMonth = aValue;
-              if (aField == this.monthField) {
-                this._displayedDate.setMonth(aValue);
-              } else {
-                expectedMonth = this._displayedDate.getMonth();
-                this._displayedDate.setFullYear(aValue);
-              }
-
-              if (expectedMonth != -1 && expectedMonth != 12 &&
-                  expectedMonth != this._displayedDate.getMonth()) {
-                // If the month isn't what was expected, then the month overflowed.
-                // Setting the date to 0 will go back to the last day of the right month.
-                this._displayedDate.setDate(0);
-              }
-
-              date = new Date(this._displayedDate);
-              currentMonth = this._displayedDate.getMonth();
-            } else {
-              var samemonth = (this._displayedDate &&
-                               this._displayedDate.getMonth() == this.month &&
-                               this._displayedDate.getFullYear() == this.year);
-              if (samemonth) {
-                var items = this.dateField.getElementsByAttribute("value", this.date);
-                if (items.length)
-                  this.selectedItem = items[0];
-                return;
-              }
-
-              date = this.dateValue;
-              this._displayedDate = new Date(date);
-              currentMonth = this.month;
-            }
-
-            if (this._todayItem) {
-              this._todayItem.removeAttribute("today");
-              this._todayItem = null;
-            }
-
-            if (this._selectedItem) {
-              this._selectedItem.removeAttribute("selected");
-              this._selectedItem = null;
-            }
-
-            // Update the month and year title
-            this.monthField.selectedIndex = currentMonth;
-            this.yearField.setAttribute("value", date.getFullYear());
-
-            date.setDate(1);
-            var firstWeekday = (7 + date.getDay() - this._weekStart) % 7;
-            date.setDate(date.getDate() - firstWeekday);
-
-            var today = new Date();
-            var datebox = this.dateField;
-            for (var k = 1; k < datebox.childNodes.length; k++) {
-              var row = datebox.childNodes[k];
-              for (var i = 0; i < 7; i++) {
-                var item = row.childNodes[i];
-
-                if (currentMonth == date.getMonth()) {
-                  item.value = date.getDate();
-
-                  // highlight today
-                  if (this._isSameDay(today, date)) {
-                    this._todayItem = item;
-                    item.setAttribute("today", "true");
-                  }
-
-                  // highlight the selected date
-                  if (this._isSameDay(this._dateValue, date)) {
-                    this._selectedItem = item;
-                    item.setAttribute("selected", "true");
-                  }
-                } else {
-                  item.value = "";
-                }
-
-                date.setDate(date.getDate() + 1);
-              }
-            }
-
-            this._fireEvent("monthchange", this);
-          ]]>
-        </body>
-      </method>
-      <method name="_increaseOrDecreaseDateFromEvent">
-        <parameter name="aEvent"/>
-        <parameter name="aDiff"/>
-        <body>
-          <![CDATA[
-            if (aEvent.originalTarget == this && !this.disabled && !this.readOnly) {
-              var newdate = this.dateValue;
-              newdate.setDate(newdate.getDate() + aDiff);
-              this.dateValue = newdate;
-              this._fireEvent("change", this);
-            }
-            aEvent.stopPropagation();
-            aEvent.preventDefault();
-          ]]>
-        </body>
-      </method>
-      <method name="_increaseOrDecreaseMonth">
-        <parameter name="aDir"/>
-        <body>
-          <![CDATA[
-            if (!this.disabled) {
-              var month = this._displayedDate ? this._displayedDate.getMonth() :
-                                                this.month;
-              this._updateUI(this.monthField, month + aDir, true);
-            }
-          ]]>
-        </body>
-      </method>
-      <method name="_isSameDay">
-        <parameter name="aDate1"/>
-        <parameter name="aDate2"/>
-        <body>
-          <![CDATA[
-            return (aDate1 && aDate2 &&
-                    aDate1.getDate() == aDate2.getDate() &&
-                    aDate1.getMonth() == aDate2.getMonth() &&
-                    aDate1.getFullYear() == aDate2.getFullYear());
-          ]]>
-        </body>
-      </method>
-
-    </implementation>
-
-    <handlers>
-      <handler event="click">
-        <![CDATA[
-          if (event.button != 0 || this.disabled || this.readOnly)
-            return;
-
-          var target = event.originalTarget;
-          if (target.classList.contains("datepicker-gridlabel") &&
-              target != this.selectedItem) {
-            this.selectedItem = target;
-            this._dateValue = new Date(this._displayedDate);
-            if (this.attachedControl)
-              this.attachedControl._setValueNoSync(this._dateValue);
-            this._fireEvent("change", this);
-
-            if (this.attachedControl && "open" in this.attachedControl)
-              this.attachedControl.open = false; // close the popup
-          }
-        ]]>
-      </handler>
-      <handler event="MozMousePixelScroll" preventdefault="true"/>
-      <handler event="DOMMouseScroll" preventdefault="true">
-        <![CDATA[
-          this._increaseOrDecreaseMonth(event.detail < 0 ? -1 : 1);
-        ]]>
-      </handler>
-      <handler event="keypress" keycode="VK_LEFT"
-               action="this._increaseOrDecreaseDateFromEvent(event, -1);"/>
-      <handler event="keypress" keycode="VK_RIGHT"
-               action="this._increaseOrDecreaseDateFromEvent(event, 1);"/>
-      <handler event="keypress" keycode="VK_UP"
-               action="this._increaseOrDecreaseDateFromEvent(event, -7);"/>
-      <handler event="keypress" keycode="VK_DOWN"
-               action="this._increaseOrDecreaseDateFromEvent(event, 7);"/>
-      <handler event="keypress" keycode="VK_PAGE_UP" preventdefault="true"
-               action="this._increaseOrDecreaseMonth(-1);"/>
-      <handler event="keypress" keycode="VK_PAGE_DOWN" preventdefault="true"
-               action="this._increaseOrDecreaseMonth(1);"/>
-    </handlers>
-  </binding>
-
-  <binding id="datepicker-popup" display="xul:menu"
-#ifdef MOZ_SUITE
-           extends="chrome://communicator/content/bindings/datetimepicker.xml#datepicker">
-#else
-           extends="chrome://messenger/content/datetimepicker.xml#datepicker">
-#endif
-    <content align="center">
-      <xul:moz-input-box class="textbox-input-box datetimepicker-input-box"
-                         align="center"
-                         allowevents="true"
-                         xbl:inherits="context,disabled,readonly">
-        <xul:hbox class="datetimepicker-input-subbox" align="baseline">
-          <html:input class="datetimepicker-input textbox-input" anonid="input-one"
-                      size="2" maxlength="2"
-                      xbl:inherits="disabled,readonly"/>
-        </xul:hbox>
-        <xul:label anonid="sep-first" class="datetimepicker-separator" value=":"/>
-        <xul:hbox class="datetimepicker-input-subbox" align="baseline">
-          <html:input class="datetimepicker-input textbox-input" anonid="input-two"
-                      size="2" maxlength="2"
-                      xbl:inherits="disabled,readonly"/>
-        </xul:hbox>
-        <xul:label anonid="sep-second" class="datetimepicker-separator" value=":"/>
-        <xul:hbox class="datetimepicker-input-subbox" align="center">
-          <html:input class="datetimepicker-input textbox-input" anonid="input-three"
-                      size="2" maxlength="2"
-                      xbl:inherits="disabled,readonly"/>
-        </xul:hbox>
-        <xul:hbox class="datetimepicker-input-subbox" align="center">
-          <html:input class="datetimepicker-input textbox-input" anonid="input-ampm"
-                      size="2" maxlength="2"
-                      xbl:inherits="disabled,readonly"/>
-        </xul:hbox>
-      </xul:moz-input-box>
-      <xul:spinbuttons anonid="buttons" xbl:inherits="disabled" allowevents="true"
-                       onup="this.parentNode._increaseOrDecrease(1);"
-                       ondown="this.parentNode._increaseOrDecrease(-1);"/>
-      <xul:dropmarker class="datepicker-dropmarker" xbl:inherits="disabled"/>
-      <xul:panel onpopupshown="this.firstChild.focus();" level="top">
-        <xul:datepicker anonid="grid" type="grid" class="datepicker-popupgrid"
-                        xbl:inherits="disabled,readonly,firstdayofweek"/>
-      </xul:panel>
-    </content>
-    <implementation>
-      <constructor>
-        var grid = document.getAnonymousElementByAttribute(this, "anonid", "grid");
-        this.attachedControl = grid;
-        grid.attachedControl = this;
-        grid._setValueNoSync(this._dateValue);
-      </constructor>
-      <property name="open" onget="return this.hasAttribute('open');">
-        <setter>
-          <![CDATA[
-            if (this.hasMenu())
-              this.openMenu(val);
-            return val;
-          ]]>
-        </setter>
-      </property>
-      <property name="displayedMonth">
-        <getter>
-          return document.getAnonymousElementByAttribute(this, "anonid", "grid").displayedMonth;
-        </getter>
-        <setter>
-          document.getAnonymousElementByAttribute(this, "anonid", "grid").displayedMonth = val;
-          return val;
-        </setter>
-      </property>
-      <property name="displayedYear">
-        <getter>
-          return document.getAnonymousElementByAttribute(this, "anonid", "grid").displayedYear;
-        </getter>
-        <setter>
-          document.getAnonymousElementByAttribute(this, "anonid", "grid").displayedYear = val;
-          return val;
-        </setter>
-      </property>
-    </implementation>
-  </binding>
-
-</bindings>
--- a/mail/base/content/bindings.css
+++ b/mail/base/content/bindings.css
@@ -1,17 +1,16 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 @import url("chrome://global/skin/textbox.css");
 @import url("chrome://messenger/skin/numberbox.css");
 @import url("chrome://messenger/skin/xbl-notification.css");
 @import url("chrome://messenger/skin/spinbuttons.css");
-@import url("chrome://messenger/skin/datetimepicker.css");
 @import url("chrome://messenger/content/menulist.css");
 
 @namespace url("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul");
 
 toolbox {
   -moz-binding: url("chrome://messenger/content/toolbar.xml#toolbox");
 }
 
@@ -53,24 +52,16 @@ xbl-notification {
 button[type="menu-button"] {
   -moz-binding: url("chrome://messenger/content/menubutton.xml#menu-button");
 }
 
 menulist[type="description"] > menupopup > menuitem[description] {
   -moz-binding: url("chrome://messenger/content/mailWidgets.xml#menuitem-iconic-desc-noaccel");
 }
 
-datepicker[type="popup"] {
-  -moz-binding: url('chrome://messenger/content/datetimepicker.xml#datepicker-popup');
-}
-
-datepicker[type="grid"] {
-  -moz-binding: url('chrome://messenger/content/datetimepicker.xml#datepicker-grid');
-}
-
 textbox[type="number"] {
   -moz-binding: url('chrome://messenger/content/numberbox.xml#numberbox');
 }
 
 spinbuttons {
   -moz-binding: url("chrome://messenger/content/spinbuttons.xml#spinbuttons");
 }
 
--- a/mail/base/jar.mn
+++ b/mail/base/jar.mn
@@ -31,17 +31,16 @@ messenger.jar:
     content/messenger/mailWidgets.js                (content/mailWidgets.js)
     content/messenger/customElements.js             (content/customElements.js)
     content/messenger/customizeToolbar.css          (../../common/src/customizeToolbar.css)
     content/messenger/customizeToolbar.js           (../../common/src/customizeToolbar.js)
 *   content/messenger/customizeToolbar.xul          (../../common/src/customizeToolbar.xul)
     content/messenger/viewSource.css                (../../common/src/viewSource.css)
     content/messenger/viewSource.js                 (../../common/src/viewSource.js)
 *   content/messenger/viewSource.xul                (../../common/src/viewSource.xul)
-*   content/messenger/datetimepicker.xml            (../../common/bindings/datetimepicker.xml)
     content/messenger/generalBindings.xml           (../../common/bindings/generalBindings.xml)
     content/messenger/generalBindings.js            (../../common/bindings/generalBindings.js)
     content/messenger/menubutton.xml                (../../common/bindings/menubutton.xml)
     content/messenger/menulist.css                  (../../common/bindings/menulist.css)
     content/messenger/menulist.xml                  (../../common/bindings/menulist.xml)
     content/messenger/notificationbox.xml           (../../common/bindings/notificationbox.xml)
     content/messenger/numberbox.xml                 (../../common/bindings/numberbox.xml)
     content/messenger/richlistbox.xml               (../../common/bindings/richlistbox.xml)
--- a/mail/components/addrbook/content/abCard.inc.xul
+++ b/mail/components/addrbook/content/abCard.inc.xul
@@ -225,26 +225,31 @@
             <textbox id="WebPage2" flex="1" class="uri-element"/>
           </hbox>
         </hbox>
         <hbox id="birthdayField" align="center">
           <spacer flex="1"/>
           <label control="Birthday" value="&Birthday.label;"
                  accesskey="&Birthday.accesskey;"/>
           <hbox class="AddressCardEditWidth" align="center">
-            <!-- NOTE: This datepicker is modified.
-                 See abCardOverlay.js for details-->
-            <datepicker id="Birthday" type="popup"/>
-            <label value="&In.label;"/>
+            <menulist id="BirthMonth">
+              <menupopup>
+                <menuitem label="&Month.placeholder;" value="-1" class="placeholderOption"/>
+              </menupopup>
+            </menulist>
+            <menulist id="BirthDay">
+              <menupopup>
+                <menuitem label="&Day.placeholder;" value="-1" class="placeholderOption"/>
+              </menupopup>
+            </menulist>
             <textbox id="BirthYear" maxlength="4"
                      placeholder="&Year.placeholder;" class="YearWidth" />
-            <label control="Age" value="&Or.value;"/>
+            <label control="Age" value="&Age.label;"/>
             <textbox id="Age" maxlength="4"
                      placeholder="&Age.placeholder;" class="YearWidth" />
-            <label value="&YearsOld.label;"/>
             <spacer flex="1"/>
           </hbox>
         </hbox>
       </vbox>
 
       <!-- ** Business Address Tab ** -->
       <vbox id="abBusinessTab" >
         <hbox id="JobTitleDepartmentContainer" align="center">
--- a/mail/components/addrbook/content/abCard.js
+++ b/mail/components/addrbook/content/abCard.js
@@ -285,17 +285,18 @@ function OnLoadEditCard() {
 
       if (directory.readOnly) {
         // Set all the editable vcard fields to read only
         for (var i = kVcardFields.length; i-- > 0;) {
           document.getElementById(kVcardFields[i][0]).readOnly = true;
         }
 
         // the birthday fields
-        document.getElementById("Birthday").readOnly = true;
+        document.getElementById("BirthDay").readOnly = true;
+        document.getElementById("BirthMonth").readOnly = true;
         document.getElementById("BirthYear").readOnly = true;
         document.getElementById("Age").readOnly = true;
 
         // the photo field and buttons
         document.getElementById("PhotoType").disabled        = true;
         document.getElementById("GenericPhotoList").disabled = true;
         document.getElementById("PhotoURI").disabled         = true;
         document.getElementById("PhotoURI").placeholder      = "";
@@ -379,18 +380,46 @@ function InitPhoneticFields() {
   // show phonetic fields if indicated by the pref
   if (showPhoneticFields == "true") {
     for (var i = kPhoneticFields.length; i-- > 0;) {
       document.getElementById(kPhoneticFields[i]).hidden = false;
     }
   }
 }
 
+function InitBirthDateFields() {
+  let birthMonth = document.getElementById("BirthMonth");
+  let birthDay = document.getElementById("BirthDay");
+  let birthYear = document.getElementById("BirthYear");
+
+  if (birthMonth.menupopup.childElementCount == 1) {
+    let formatter = Intl.DateTimeFormat(undefined, { month: "long" });
+    for (let m = 1; m <= 12; m++) {
+      let menuitem = document.createElement("menuitem");
+      menuitem.setAttribute("value", m);
+      menuitem.setAttribute("label", formatter.format(new Date(2000, m - 1, 2)));
+      birthMonth.menupopup.appendChild(menuitem);
+    }
+
+    formatter = Intl.DateTimeFormat(undefined, { day: "numeric" });
+    for (let d = 1; d <= 31; d++) {
+      let menuitem = document.createElement("menuitem");
+      menuitem.setAttribute("value", d);
+      menuitem.setAttribute("label", formatter.format(new Date(2000, 0, d)));
+      birthDay.menupopup.appendChild(menuitem);
+    }
+  }
+
+  birthMonth.addEventListener("command", setDisabledMonthDays);
+  birthYear.addEventListener("change", setDisabledMonthDays);
+}
+
 function InitEditCard() {
   InitPhoneticFields();
+  InitBirthDateFields();
 
   InitCommonJS();
 
   // Create gEditCard object that contains global variables for the current js
   //   file.
   gEditCard = {};
 
   // get specific prefs that gEditCard will need
@@ -455,50 +484,47 @@ function GetCardValues(cardproperty, doc
   // to give extensions a chance to populate custom fields.
   NotifyLoadListeners(cardproperty, doc);
 
   for (var i = kVcardFields.length; i-- > 0;) {
     doc.getElementById(kVcardFields[i][0]).value =
       cardproperty.getProperty(kVcardFields[i][1], "");
   }
 
-  var birthday = doc.getElementById("Birthday");
-  modifyDatepicker(birthday);
-
   // Get the year first, so that the following month/day
   // calculations can take leap years into account.
   var year = cardproperty.getProperty("BirthYear", null);
   var birthYear = doc.getElementById("BirthYear");
   // set the year in the datepicker to the stored year
-  birthday.year = saneBirthYear(year);
   birthYear.value = year;
 
-  // get the month of the year (1 - 12)
   var month = cardproperty.getProperty("BirthMonth", null);
-  if (month > 0 && month < 13)
-    birthday.month = month - 1;
-  else
-    birthday.monthField.value = null;
-
-  // get the date of the month (1 - 31)
-  var date = cardproperty.getProperty("BirthDay", null);
-  if (date > 0 && date < 32)
-    birthday.date = date;
-  else
-    birthday.dateField.value = null;
+  var day = cardproperty.getProperty("BirthDay", null);
+  var birthMonth = doc.getElementById("BirthMonth");
+  var birthDay = doc.getElementById("BirthDay");
+  birthDay.value = -1;
+  if (month > 0 && month < 13) {
+    birthMonth.value = month;
+    setDisabledMonthDays();
+    if (day > 0 && day < 32)
+      birthDay.value = day;
+  } else {
+    birthMonth.value = -1;
+  }
 
   // get the current age
-  calculateAge(null, birthYear);
+  calculateAge();
 
   // when the birth year changes, update the datepicker's year to the new value
   // or to kDefaultYear if the value is null
-  birthYear.onchange = calculateAge;
-  birthday.onchange = calculateAge;
+  birthMonth.addEventListener("command", calculateAge);
+  birthDay.addEventListener("command", calculateAge);
+  birthYear.addEventListener("change", calculateAge);
   var age = doc.getElementById("Age");
-  age.onchange = calculateYear;
+  age.addEventListener("change", calculateYear);
 
   var popup = document.getElementById("PreferMailFormatPopup");
   if (popup)
     popup.value = cardproperty.getProperty("PreferMailFormat", "");
 
   var preferDisplayNameEl = document.getElementById("preferDisplayName");
   if (preferDisplayNameEl)
     // getProperty may return a "1" or "0" string, we want a boolean
@@ -545,19 +571,18 @@ function CheckAndSetCardValues(cardprope
     return true;
 
   for (var i = kVcardFields.length; i-- > 0;) {
     cardproperty.setProperty(kVcardFields[i][1],
       doc.getElementById(kVcardFields[i][0]).value);
   }
 
   // get the birthday information from the dialog
-  var birthdayElem = doc.getElementById("Birthday");
-  var birthMonth = birthdayElem.monthField.value;
-  var birthDay = birthdayElem.dateField.value;
+  var birthMonth = document.getElementById("BirthMonth").value;
+  var birthDay = document.getElementById("BirthDay").value;
   var birthYear = doc.getElementById("BirthYear").value;
 
   // set the birth day, month, and year properties
   cardproperty.setProperty("BirthDay", birthDay);
   cardproperty.setProperty("BirthMonth", birthMonth);
   cardproperty.setProperty("BirthYear", birthYear);
 
   var popup = document.getElementById("PreferMailFormatPopup");
@@ -668,207 +693,69 @@ function DisplayNameChanged() {
 }
 
 function SetCardDialogTitle(displayName) {
   document.title = displayName
     ? gAddressBookBundle.getFormattedString(gEditCard.titleProperty + "WithDisplayName", [displayName])
     : gAddressBookBundle.getString(gEditCard.titleProperty);
 }
 
-/**
- * Calculates the duration of time between an event and now and updates the year
- * of whichever element did not call this function.
- * @param aEvent   The event calling this method.
- * @param aElement Optional, but required if this function is not called from an
- *                 element's event listener. The element that would call this.
- */
-function calculateAge(aEvent, aElement) {
-  var datepicker, yearElem, ageElem;
-  if (aEvent)
-    aElement = this;
-  if (aElement.id == "BirthYear" || aElement.id == "Birthday") {
-    datepicker = document.getElementById("Birthday");
-    yearElem = document.getElementById("BirthYear");
-    ageElem = document.getElementById("Age");
-  }
-  if (!datepicker || !yearElem || !ageElem)
-    return;
+function setDisabledMonthDays() {
+  let birthMonth = document.getElementById("BirthMonth").value;
+  let birthYear = document.getElementById("BirthYear").value;
+  let popup = document.getElementById("BirthDay").menupopup;
 
-  // if the datepicker was updated, update the year element
-  if (aElement == datepicker && !(datepicker.year == kDefaultYear && !yearElem.value))
-    yearElem.value = datepicker.year;
-
-  var year = yearElem.value;
-  // if the year element's value is invalid set the year and age elements to null
-  if (isNaN(year) || year < kMinYear || year > kMaxYear) {
-    yearElem.value = null;
-    ageElem.value = null;
-    datepicker.year = kDefaultYear;
-    return;
-  } else if (aElement == yearElem) {
-    datepicker.year = year;
+  if (!isNaN(birthYear) && birthYear >= kMinYear && birthYear <= kMaxYear) {
+    popup.children[29].disabled = (birthYear % 4 != 0) && birthMonth == "2";
   }
-  // calculate the length of time between the event and now
-  try {
-    var event = new Date(datepicker.year, datepicker.month, datepicker.date);
-    // if the year is only 2 digits, then the year won't be set correctly
-    // using setFullYear fixes this issue
-    event.setFullYear(datepicker.year);
-    // get the difference between today and the event
-    var age = new Date(new Date() - event);
-    // get the number of years of the difference and subtract 1970 (epoch)
-    ageElem.value = age.getFullYear() - 1970;
-  } catch (e) {
-    datepicker.year = kDefaultYear;
-    // if there was an error (like invalid year) set the year and age to null
-    yearElem.value = null;
-    ageElem.value = null;
-  }
-}
-
-/**
- * Calculates the year an event occurred based on the number of years, months,
- * and days since the event and updates the relevant element.
- * @param aEvent   The event calling this method.
- * @param aElement Optional, but required if this function is not called from an
- *                 element's event listener. The element that would call this.
- */
-function calculateYear(aEvent, aElement) {
-  var yearElem, datepicker;
-  if (aEvent)
-    aElement = this;
-  if (aElement.id == "Age") {
-    datepicker = document.getElementById("Birthday");
-    yearElem = document.getElementById("BirthYear");
-  }
-  if (!datepicker || !yearElem)
-    return;
-
-  // if the age is null, remove the year from the year element, and set the
-  // datepicker to the default year
-  if (!aElement.value) {
-    datepicker.year = kDefaultYear;
-    yearElem.value = null;
-    return;
-  }
-  var today = new Date();
-  try {
-    var date = new Date(aElement.value, datepicker.month, datepicker.date);
-    date.setFullYear(aElement.value);
-    // get the difference between today and the age (the year is offset by 1970)
-    var difference = new Date(today - date);
-    datepicker.year = yearElem.value = difference.getFullYear() - 1970;
-  } catch (e) {
-    // The above code may throw an invalid year exception. If that happens, set
-    // the year to kDefaultYear and set the year element's value to 0.
-    datepicker.year = kDefaultYear;
-    // if there was an error (like invalid year) set the year and age to null
-    yearElem.value = null;
-    let ageElem = document.getElementById("Age");
-    if (ageElem)
-      ageElem.value = null;
-  }
+  popup.children[30].disabled = birthMonth == "2";
+  popup.children[31].disabled = ["2", "4", "6", "9", "11"].includes(birthMonth);
 }
 
-/**
- * Modifies a datepicker in the following ways:
- *  - Removes the scroll arrows
- *  - Hides the year
- *  - Allows the day and month to be blank
- * NOTE:
- * The datepicker's date, month, year, and dateValue properties are not always
- * what appear physically to the user in the datepicker fields.
- * If any field is blank, the corresponding property is either the previous
- * value if there was one since the card was opened or the relevant portion of
- * the current date.
- *
- * To get the displayed values, get the value of the individual field, such as
- * datepicker.yyyyField.value where yyyy is "year", "month", or "date" for the
- * year, month, and day, respectively.
- * If the value is null, then the field is blank and vice versa.
- * @param aDatepicker The datepicker to modify.
- */
-function modifyDatepicker(aDatepicker) {
-  // collapse the year field and separator
-  aDatepicker.yearField.parentNode.collapsed = true;
-  if (aDatepicker.yearField == aDatepicker._fieldThree ||
-      aDatepicker.yearField == aDatepicker._fieldTwo)
-    aDatepicker._separatorSecond.collapsed = true;
-  else
-    aDatepicker._separatorFirst.collapsed = true;
-  // collapse the spinner element
-  document.getAnonymousElementByAttribute(aDatepicker, "anonid", "buttons")
-          .collapsed = true;
-  // this modified constrain value function ignores values less than the minimum
-  // to let the value be blank (null)
-  // from: mozilla/toolkit/content/widgets/datetimepicker.xml#759
-  aDatepicker._constrainValue = function(aField, aValue, aNoWrap) {
-    // if the value is less than one, make the field's value null
-    if (aValue < 1) {
-      aField.value = null;
-      return null;
-    }
-    if (aNoWrap && aField == this.monthField)
-      aValue--;
-    // make sure the date is valid for the given month
-    if (aField == this.dateField) {
-      var currentMonth = this.month;
-      var dt = new Date(this.year, currentMonth, aValue);
-      return dt.getMonth() != currentMonth ? 1 : aValue;
-    }
-    var min = (aField == this.monthField) ? 0 : 1;
-    var max = (aField == this.monthField) ? 11 : kMaxYear;
-    // make sure the value isn't too high
-    if (aValue > max)
-      return aNoWrap ? max : min;
-    return aValue;
-  };
-  // sets the specified field to the given value, but allows blank fields
-  // from: mozilla/toolkit/content/widgets/datetimepicker.xml#698
-  aDatepicker._setFieldValue = function(aField, aValue) {
-    if (aField == this.yearField && aValue >= kMinYear && aValue <= kMaxYear) {
-      let oldDate = this._dateValue;
-      this._dateValue.setFullYear(aValue);
-      if (oldDate != this._dateValue) {
-        this._dateValue.setDate(0);
-        this._updateUI(this.dateField, this.date);
-      }
-    } else if (aField == this.monthField && aValue != null) {
-      // update the month if the value isn't null
-      let oldDate = this.date;
-      this._dateValue.setMonth(aValue);
-      if (oldDate != this.date)
-        this._dateValue.setDate(0);
-      this._updateUI(this.dateField, this.date);
-      let date = this._dateValue.getDate();
-      this.dateField.value = date < 10 && this.dateLeadingZero ? "0" + date : date;
-      let month = this._dateValue.getMonth() + 1;
-      this.monthField.value = month < 10 && this.monthLeadingZero ? "0" + month : month;
-    } else if (aField == this.dateField && aValue != null) {
-      // update the date if the value isn't null
-      this._dateValue.setDate(aValue);
-      this._updateUI(this.dateField, this.date);
-      let date = this._dateValue.getDate();
-      this.dateField.value = date < 10 && this.dateLeadingZero ? "0" + date : date;
-      let month = this._dateValue.getMonth() + 1;
-      this.monthField.value = month < 10 && this.monthLeadingZero ? "0" + month : month;
-    }
-    this.setAttribute("value", this.value);
+function calculateAge() {
+  let birthMonth = document.getElementById("BirthMonth").value;
+  let birthDay = document.getElementById("BirthDay").value;
+  let birthYear = document.getElementById("BirthYear").value;
+  document.getElementById("Age").value = "";
+
+  if (birthMonth == -1 || birthDay == -1) {
+    return;
+  }
+  if (isNaN(birthYear) || birthYear < kMinYear || birthYear > kMaxYear) {
+    return;
+  }
 
-    if (this.attachedControl)
-      this.attachedControl._setValueNoSync(this._dateValue);
-    // if the aField's value is null or 0, set both field's values to null
-    if (!aField.value && aField != this.yearField) {
-      this.dateField.value = null;
-      this.monthField.value = null;
-    }
-    // make the field's value null if aValue is null and the field's value isn't
-    if (aValue == null && aField.value != null)
-      aField.value = null;
-  };
+  let today = new Date();
+  let age = today.getFullYear() - birthYear;
+  if (birthMonth > today.getMonth()) {
+    age--;
+  } else if (birthMonth == today.getMonth() && birthDay > today.getDate()) {
+    age--;
+  }
+  document.getElementById("Age").value = age;
+}
+
+function calculateYear() {
+  let age = document.getElementById("Age").value;
+  if (isNaN(age)) {
+    return;
+  }
+
+  let today = new Date();
+  let year = today.getFullYear() - age;
+
+  let birthMonth = document.getElementById("BirthMonth").value;
+  let birthDay = document.getElementById("BirthDay").value;
+  if (birthMonth > today.getMonth()) {
+    year--;
+  } else if (birthMonth == today.getMonth() && birthDay > today.getDate()) {
+    year--;
+  }
+  document.getElementById("BirthYear").value = year;
+  setDisabledMonthDays();
 }
 
 var chatNameFieldIds =
   ["Gtalk", "AIM", "Yahoo", "Skype", "QQ", "MSN", "ICQ", "XMPP", "IRC"];
 
 /**
  * Show the 'Chat' tab and focus the first field that has a value, or
  * the first field if none of them has a value.
--- a/mail/locales/en-US/chrome/messenger/addressbook/abCard.dtd
+++ b/mail/locales/en-US/chrome/messenger/addressbook/abCard.dtd
@@ -71,21 +71,21 @@
 <!ENTITY HomeZipCode.label              "ZIP/Postal Code:">
 <!ENTITY HomeZipCode.accesskey          "Z">
 <!ENTITY HomeCountry.label              "Country:">
 <!ENTITY HomeCountry.accesskey          "u">
 <!ENTITY HomeWebPage.label              "Web Page:">
 <!ENTITY HomeWebPage.accesskey          "e">
 <!ENTITY Birthday.label                 "Birthday:">
 <!ENTITY Birthday.accesskey             "B">
-<!ENTITY In.label                       "">
+<!ENTITY Month.placeholder              "Month">
+<!ENTITY Day.placeholder                "Day">
 <!ENTITY Year.placeholder               "Year">
-<!ENTITY Or.value                       "or">
+<!ENTITY Age.label                      "Age:">
 <!ENTITY Age.placeholder                "Age">
-<!ENTITY YearsOld.label                 "">
 
 <!ENTITY Work.tab                       "Work">
 <!ENTITY Work.accesskey                 "W">
 <!ENTITY JobTitle.label                 "Title:">
 <!ENTITY JobTitle.accesskey             "i">
 <!ENTITY Department.label               "Department:">
 <!ENTITY Department.accesskey           "m">
 <!ENTITY Company.label                  "Organization:">
deleted file mode 100644
--- a/mail/locales/en-US/chrome/messenger/datetimepicker.dtd
+++ /dev/null
@@ -1,7 +0,0 @@
-<!-- This Source Code Form is subject to the terms of the Mozilla Public
-   - License, v. 2.0. If a copy of the MPL was not distributed with this
-   - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
-
-<!-- first day of week to display in datepicker, a value from 0 to 6,
-     0 = Sunday, 1 = Monday, etc. -->
-<!ENTITY firstdayofweek.default "0">
--- a/mail/locales/jar.mn
+++ b/mail/locales/jar.mn
@@ -25,17 +25,16 @@
   locale/@AB_CD@/messenger/accountCreationModel.properties              (%chrome/messenger/accountCreationModel.properties)
   locale/@AB_CD@/messenger/accountCreationUtil.properties               (%chrome/messenger/accountCreationUtil.properties)
   locale/@AB_CD@/messenger/addons.properties                            (%chrome/messenger/addons.properties)
   locale/@AB_CD@/messenger/charsetTitles.properties                     (%chrome/messenger/charsetTitles.properties)
   locale/@AB_CD@/messenger/customizeToolbar.dtd                         (%chrome/messenger/customizeToolbar.dtd)
   locale/@AB_CD@/messenger/customizeToolbar.properties                  (%chrome/messenger/customizeToolbar.properties)
   locale/@AB_CD@/messenger/viewSource.dtd                               (%chrome/messenger/viewSource.dtd)
   locale/@AB_CD@/messenger/viewSource.properties                        (%chrome/messenger/viewSource.properties)
-  locale/@AB_CD@/messenger/datetimepicker.dtd                           (%chrome/messenger/datetimepicker.dtd)
   locale/@AB_CD@/messenger/systemIntegrationDialog.dtd                  (%chrome/messenger/systemIntegrationDialog.dtd)
   locale/@AB_CD@/messenger/virtualFolderProperties.dtd                  (%chrome/messenger/virtualFolderProperties.dtd)
   locale/@AB_CD@/messenger/virtualFolderListDialog.dtd                  (%chrome/messenger/virtualFolderListDialog.dtd)
   locale/@AB_CD@/messenger/multimessageview.properties                  (%chrome/messenger/multimessageview.properties)
   locale/@AB_CD@/messenger/multimessageview.dtd                         (%chrome/messenger/multimessageview.dtd)
   locale/@AB_CD@/messenger/mailOverlay.dtd                              (%chrome/messenger/mailOverlay.dtd)
   locale/@AB_CD@/messenger/messenger.dtd                                (%chrome/messenger/messenger.dtd)
   locale/@AB_CD@/messenger/viewZoomOverlay.dtd                          (%chrome/messenger/viewZoomOverlay.dtd)
--- a/mail/themes/linux/jar.mn
+++ b/mail/themes/linux/jar.mn
@@ -17,17 +17,16 @@ classic.jar:
 * skin/classic/messenger/imRichlistbox.css                    (../../components/im/themes/imRichlistbox.css)
   skin/classic/messenger/founder.png                          (../../components/im/themes/founder.png)
   skin/classic/messenger/operator.png                         (../../components/im/themes/operator.png)
   skin/classic/messenger/half-operator.png                    (../../components/im/themes/half-operator.png)
   skin/classic/messenger/voice.png                            (../../components/im/themes/voice.png)
   skin/classic/messenger/browserRequest.css                   (mail/browserRequest.css)
   skin/classic/messenger/compacttheme.css                     (mail/compacttheme.css)
   skin/classic/messenger/customizeToolbar.css                 (mail/customizeToolbar.css)
-  skin/classic/messenger/datetimepicker.css                   (mail/datetimepicker.css)
   skin/classic/messenger/section_collapsed.png                (mail/section_collapsed.png)
   skin/classic/messenger/section_expanded.png                 (mail/section_expanded.png)
   skin/classic/messenger/menulist.css                         (mail/menulist.css)
   skin/classic/messenger/messageBody.css                      (mail/messageBody.css)
   skin/classic/messenger/messageHeader.css                    (mail/messageHeader.css)
   skin/classic/messenger/messageIcons.css                     (mail/messageIcons.css)
   skin/classic/messenger/messageQuotes.css                    (mail/messageQuotes.css)
   skin/classic/messenger/messenger.css                        (mail/messenger.css)
--- a/mail/themes/linux/mail/addrbook/cardDialog.css
+++ b/mail/themes/linux/mail/addrbook/cardDialog.css
@@ -19,16 +19,22 @@
 .PhoneEditWidth {
   width: 24ch;
 }
 
 .AddressCardEditWidth {
   width: 72ch;
 }
 
+#BirthMonth[value="-1"],
+#BirthDay[value="-1"],
+.placeholderOption {
+  color: GrayText;
+}
+
 .YearWidth {
   width: 8ch;
 }
 
 .stateZipSpacer {
   width: 6ch;
 }
 
deleted file mode 100644
--- a/mail/themes/linux/mail/datetimepicker.css
+++ /dev/null
@@ -1,107 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-/* ===== datetimepicker.css =============================================
-  == Styles used by the XUL datepicker and timepicker elements.
-  ======================================================================= */
-
-@namespace url("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul");
-@namespace html url("http://www.w3.org/1999/xhtml");
-
-datepicker, timepicker {
-  padding: 0;
-  border: none;
-  background: none;
-  cursor: default;
-}
-
-panel > datepicker {
-  margin: 0;
-}
-
-.datetimepicker-input-box {
-  -moz-appearance: textfield;
-  cursor: text;
-  margin-inline-end: 2px;
-  padding: 2px 0 3px;
-  padding-inline-start: 4px;
-  padding-inline-end: 2px;
-  color: -moz-FieldText;
-}
-
-.datetimepicker-input-subbox {
-  width: 1.6em;
-}
-
-html|*.datetimepicker-input {
-  text-align: end;
-}
-
-.datepicker-dropmarker {
-  min-width: 2em;
-  min-height: 2em;
-}
-
-.datetimepicker-separator {
-  margin: 0 !important;
-}
-
-.datetimepicker-year {
-  width: 3.2em;
-}
-
-datepicker[readonly="true"],
-timepicker[readonly="true"] {
-  background-color: -moz-Dialog;
-  color: -moz-DialogText;
-}
-
-datepicker[disabled="true"],
-timepicker[disabled="true"] {
-  cursor: default;
-  background-color: -moz-Dialog;
-  color: GrayText;
-}
-
-.datepicker-mainbox {
-  margin: 2px 4px;
-  border: 1px ThreeDShadow;
-  background-color: -moz-Field;
-  color: -moz-FieldText;
-}
-
-.datepicker-popupgrid > .datepicker-mainbox {
-  margin: 0;
-  border: none;
-}
-
-.datepicker-gridlabel, .datepicker-weeklabel {
-  text-align: center;
-}
-
-.datepicker-gridlabel[today="true"] {
-  background-color: darkgrey;
-  color: white;
-}
-
-.datepicker-gridlabel[selected="true"] {
-  background-color: Highlight;
-  color: HighlightText;
-}
-
-.datepicker-button {
-  -moz-appearance: none;
-  min-width: 8px;
-  padding: 0;
-}
-
-.datepicker-previous,
-.datepicker-next:-moz-locale-dir(rtl) {
-  list-style-image: url("chrome://messenger/skin/icons/arrow/arrow-left.png");
-}
-
-.datepicker-next,
-.datepicker-previous:-moz-locale-dir(rtl) {
-  list-style-image: url("chrome://messenger/skin/icons/arrow/arrow-right.png");
-}
--- a/mail/themes/osx/jar.mn
+++ b/mail/themes/osx/jar.mn
@@ -22,17 +22,16 @@ classic.jar:
 * skin/classic/messenger/imRichlistbox.css                       (../../components/im/themes/imRichlistbox.css)
   skin/classic/messenger/founder.png                             (../../components/im/themes/founder.png)
   skin/classic/messenger/operator.png                            (../../components/im/themes/operator.png)
   skin/classic/messenger/half-operator.png                       (../../components/im/themes/half-operator.png)
   skin/classic/messenger/voice.png                               (../../components/im/themes/voice.png)
   skin/classic/messenger/browserRequest.css                      (mail/browserRequest.css)
   skin/classic/messenger/compacttheme.css                        (mail/compacttheme.css)
   skin/classic/messenger/customizeToolbar.css                    (mail/customizeToolbar.css)
-  skin/classic/messenger/datetimepicker.css                      (mail/datetimepicker.css)
   skin/classic/messenger/section_collapsed.png                   (mail/section_collapsed.png)
   skin/classic/messenger/section_expanded.png                    (mail/section_expanded.png)
   skin/classic/messenger/menulist.css                            (mail/menulist.css)
   skin/classic/messenger/messageBody.css                         (mail/messageBody.css)
   skin/classic/messenger/messageHeader.css                       (mail/messageHeader.css)
   skin/classic/messenger/messageIcons.css                        (mail/messageIcons.css)
   skin/classic/messenger/messageQuotes.css                       (mail/messageQuotes.css)
   skin/classic/messenger/messageWindow.css                       (mail/messageWindow.css)
--- a/mail/themes/osx/mail/addrbook/cardDialog.css
+++ b/mail/themes/osx/mail/addrbook/cardDialog.css
@@ -19,16 +19,22 @@
 .PhoneEditWidth {
   width: 24ch;
 }
 
 .AddressCardEditWidth {
   width: 72ch;
 }
 
+#BirthMonth[value="-1"],
+#BirthDay[value="-1"],
+.placeholderOption {
+  color: GrayText;
+}
+
 .YearWidth {
   width: 8ch;
 }
 
 .stateZipSpacer {
   width: 6ch;
 }
 
deleted file mode 100644
--- a/mail/themes/osx/mail/datetimepicker.css
+++ /dev/null
@@ -1,101 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-@namespace url("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul");
-@namespace html url("http://www.w3.org/1999/xhtml");
-
-datepicker, timepicker {
-  padding: 0 0 1px;
-  margin: 4px;
-  border: none;
-}
-
-panel > datepicker {
-  margin: 0;
-}
-
-.datetimepicker-input-box {
-  -moz-appearance: textfield;
-  cursor: text;
-  margin-right: 4px;
-  margin-bottom: 2px;
-  padding: 0;
-  background-color: -moz-Field;
-  color: -moz-FieldText;
-}
-
-.datetimepicker-input-subbox {
-  width: 1.6em;
-}
-
-html|*.datetimepicker-input {
-  text-align: end;
-}
-
-.datetimepicker-separator {
-  margin: 0 !important;
-}
-
-.datetimepicker-year {
-  width: 3.2em;
-}
-
-.datepicker-dropmarker {
-  margin-bottom: 2px;
-}
-
-datepicker[readonly="true"],
-timepicker[readonly="true"] {
-  background-color: -moz-Dialog;
-  color: -moz-DialogText;
-}
-
-datepicker[disabled="true"],
-timepicker[disabled="true"] {
-  cursor: default;
-  background-color: -moz-Dialog;
-  color: GrayText;
-}
-
-.datepicker-mainbox {
-  margin: 2px 4px;
-  border: 1px solid ThreeDShadow;
-  background-color: #EEEEEE;
-  color: -moz-DialogText;
-}
-
-.datepicker-popupgrid > .datepicker-mainbox {
-  margin: 0;
-  border: none;
-}
-
-.datepicker-gridlabel, .datepicker-weeklabel {
-  text-align: center;
-}
-
-.datepicker-gridlabel[today="true"] {
-  background-color: darkgrey;
-  color: white;
-}
-
-.datepicker-gridlabel[selected="true"] {
-  background-color: Highlight;
-  color: HighlightText;
-}
-
-.datepicker-button {
-  -moz-appearance: none;
-  min-width: 8px;
-  padding: 0;
-}
-
-.datepicker-previous,
-.datepicker-next:-moz-locale-dir(rtl) {
-  list-style-image: url("chrome://messenger/skin/icons/arrow/arrow-left.png");
-}
-
-.datepicker-next,
-.datepicker-previous:-moz-locale-dir(rtl) {
-  list-style-image: url("chrome://messenger/skin/icons/arrow/arrow-right.png");
-}
--- a/mail/themes/windows/jar.mn
+++ b/mail/themes/windows/jar.mn
@@ -17,17 +17,16 @@ classic.jar:
 * skin/classic/messenger/imRichlistbox.css                    (../../components/im/themes/imRichlistbox.css)
   skin/classic/messenger/founder.png                          (../../components/im/themes/founder.png)
   skin/classic/messenger/operator.png                         (../../components/im/themes/operator.png)
   skin/classic/messenger/half-operator.png                    (../../components/im/themes/half-operator.png)
   skin/classic/messenger/voice.png                            (../../components/im/themes/voice.png)
   skin/classic/messenger/browserRequest.css                   (mail/browserRequest.css)
   skin/classic/messenger/compacttheme.css                     (mail/compacttheme.css)
   skin/classic/messenger/customizeToolbar.css                 (mail/customizeToolbar.css)
-  skin/classic/messenger/datetimepicker.css                   (mail/datetimepicker.css)
   skin/classic/messenger/section_collapsed.png                (mail/section_collapsed.png)
   skin/classic/messenger/section_expanded.png                 (mail/section_expanded.png)
   skin/classic/messenger/menulist.css                         (mail/menulist.css)
   skin/classic/messenger/messageBody.css                      (mail/messageBody.css)
   skin/classic/messenger/messageHeader.css                    (mail/messageHeader.css)
   skin/classic/messenger/messageIcons.css                     (mail/messageIcons.css)
   skin/classic/messenger/messageQuotes.css                    (mail/messageQuotes.css)
   skin/classic/messenger/messenger.css                        (mail/messenger.css)
--- a/mail/themes/windows/mail/addrbook/cardDialog.css
+++ b/mail/themes/windows/mail/addrbook/cardDialog.css
@@ -19,16 +19,22 @@
 .PhoneEditWidth {
   width: 24ch;
 }
 
 .AddressCardEditWidth {
   width: 72ch;
 }
 
+#BirthMonth[value="-1"],
+#BirthDay[value="-1"],
+.placeholderOption {
+  color: GrayText;
+}
+
 .YearWidth {
   width: 8ch;
 }
 
 .stateZipSpacer {
   width: 6ch;
 }
 
deleted file mode 100644
--- a/mail/themes/windows/mail/datetimepicker.css
+++ /dev/null
@@ -1,103 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-/* ===== datetimepicker.css =============================================
-  == Styles used by the XUL datepicker and timepicker elements.
-  ======================================================================= */
-
-@namespace url("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul");
-@namespace html url("http://www.w3.org/1999/xhtml");
-
-datepicker, timepicker {
-  margin: 2px 4px;
-  padding: 0;
-  border: none;
-  background: none;
-  cursor: default;
-}
-
-panel > datepicker {
-  margin: 0;
-}
-
-.datetimepicker-input-box {
-  -moz-appearance: textfield;
-  cursor: text;
-  margin-inline-end: 2px;
-  padding: 2px 0 3px;
-  padding-inline-start: 4px;
-  padding-inline-end: 2px;
-  color: -moz-FieldText;
-}
-
-.datetimepicker-input-subbox {
-  width: 1.6em;
-}
-
-html|*.datetimepicker-input {
-  text-align: end;
-}
-
-.datetimepicker-separator {
-  margin: 0 !important;
-}
-
-.datetimepicker-year {
-  width: 3.2em;
-}
-
-datepicker[readonly="true"],
-timepicker[readonly="true"] {
-  background-color: -moz-Dialog;
-  color: -moz-DialogText;
-}
-
-datepicker[disabled="true"],
-timepicker[disabled="true"] {
-  cursor: default;
-  background-color: -moz-Dialog;
-  color: GrayText;
-}
-
-.datepicker-mainbox {
-  margin: 2px 4px;
-  border: 1px ThreeDShadow;
-  background-color: -moz-Field;
-  color: -moz-FieldText;
-}
-
-.datepicker-popupgrid > .datepicker-mainbox {
-  margin: 0;
-  border: none;
-}
-
-.datepicker-gridlabel, .datepicker-weeklabel {
-  text-align: center;
-}
-
-.datepicker-gridlabel[today="true"] {
-  background-color: darkgrey;
-  color: white;
-}
-
-.datepicker-gridlabel[selected="true"] {
-  background-color: Highlight;
-  color: HighlightText;
-}
-
-.datepicker-button {
-  -moz-appearance: none;
-  min-width: 8px;
-  padding: 0;
-}
-
-.datepicker-previous,
-.datepicker-next:-moz-locale-dir(rtl) {
-  list-style-image: url("chrome://messenger/skin/icons/arrow/arrow-left.png");
-}
-
-.datepicker-next,
-.datepicker-previous:-moz-locale-dir(rtl) {
-  list-style-image: url("chrome://messenger/skin/icons/arrow/arrow-right.png");
-}