The source code

    Ext.namespace('Ext.ux.form');

    /**
      * Ext.ux.form.DateTime Extension Class for Ext 2.x Library
      *
      * @author    Ing. Jozef Sakalos
      * @copyright (c) 2008, Ing. Jozef Sakalos
      * @version $Id: Ext.ux.form.DateTime.js 645 2008-01-27 21:53:01Z jozo $
      *
      * @class Ext.ux.form.DateTime
      * @extends Ext.form.Field
      *
      * @history
      * 2008-1-31 Jack Slocum
      * Updated for reformatting and code edits
      */
    Ext.ux.form.DateTime = Ext.extend(Ext.form.Field, {
    	defaultAutoCreate: {
    		tag: 'input',
    		type: 'hidden'
    	},
    	dateWidth: 135,
    	timeWidth: 100,
    	dtSeparator: ' ',
    	hiddenFormat: 'Y-m-d H:i:s',
    	otherToNow: true,
    	timePosition: 'right',

    	initComponent: function(){
    		// call parent initComponent
    		Ext.ux.form.DateTime.superclass.initComponent.call(this);

    		// create DateField
    		var dateConfig = Ext.apply({}, {
    			id: this.id + '-date',
    			format: this.dateFormat,
    			width: this.dateWidth,
    			listeners: {
    				blur: {
    					scope: this,
    					fn: this.onBlur
    				},
    				focus: {
    					scope: this,
    					fn: this.onFocus
    				}
    			}
    		}, this.dateConfig);
    		this.df = new Ext.form.DateField(dateConfig);
    		delete (this.dateFormat);

    		// create TimeField
    		var timeConfig = Ext.apply({}, {
    			id: this.id + '-time',
    			format: this.timeFormat,
    			width: this.timeWidth,
    			listeners: {
    				blur: {
    					scope: this,
    					fn: this.onBlur
    				},
    				focus: {
    					scope: this,
    					fn: this.onFocus
    				}
    			}
    		}, this.timeConfig);
    		this.tf = new Ext.form.TimeField(timeConfig);
    		delete (this.timeFormat);

    		// relay events
    		this.relayEvents(this.df, ['focus', 'specialkey', 'invalid', 'valid']);
    		this.relayEvents(this.tf, ['focus', 'specialkey', 'invalid', 'valid']);

    	},
    	onRender: function(ct, position){
    		if (this.isRendered) {
    			return;
    		}

    		// render underlying field
    		Ext.ux.form.DateTime.superclass.onRender.call(this, ct, position);

    		// render DateField and TimeField
    		// create bounding table
    		if ('below' === this.timePosition) {
    			var t = Ext.DomHelper.append(ct, {
    				tag: 'table',
    				style: 'border-collapse:collapse',
    				children: [{
    					tag: 'tr',
    					children: [{
    						tag: 'td',
    						style: 'padding-bottom:1px',
    						cls: 'ux-datetime-date'
    					}]
    				}, {
    					tag: 'tr',
    					children: [{
    						tag: 'td',
    						cls: 'ux-datetime-time'
    					}]
    				}]
    			}, true);
    		}
    		else {
    			var t = Ext.DomHelper.append(ct, {
    				tag: 'table',
    				style: 'border-collapse:collapse',
    				children: [{
    					tag: 'tr',
    					children: [{
    						tag: 'td',
    						style: 'padding-right:4px',
    						cls: 'ux-datetime-date'
    					}, {
    						tag: 'td',
    						cls: 'ux-datetime-time'
    					}]
    				}]
    			}, true);
    		}

    		this.tableEl = t;
    		this.wrap = t.wrap({
    			cls: 'x-form-field-wrap'
    		});
    		this.wrap.on("mousedown", this.onMouseDown, this, {
    			delay: 10
    		});

    		// render DateField & TimeField
    		this.df.render(t.child('td.ux-datetime-date'));
    		this.tf.render(t.child('td.ux-datetime-time'));

    		if (Ext.isIE && Ext.isStrict) {
    			t.select('input').applyStyles({
    				top: 0
    			});
    		}

    		this.on('specialkey', this.onSpecialKey, this);

    		this.df.el.swallowEvent(['keydown', 'keypress']);
    		this.tf.el.swallowEvent(['keydown', 'keypress']);

    		// create errorIcon for side invalid
    		if ('side' === this.msgTarget) {
    			var elp = this.el.findParent('.x-form-element', 10, true);
    			this.errorIcon = elp.createChild({
    				cls: 'x-form-invalid-icon'
    			});

    			this.df.errorIcon = this.errorIcon;
    			this.tf.errorIcon = this.errorIcon;
    		}

    		this.isRendered = true;

    	},
    	getPositionEl: function(){
    		return this.wrap;
    	},
    	getResizeEl: function(){
    		return this.wrap;
    	},

    	adjustSize: Ext.BoxComponent.prototype.adjustSize,

    	alignErrorIcon: function(){
    		this.errorIcon.alignTo(this.wrap, 'tl-tr', [2, 0]);
    	},

    	onSpecialKey: function(t, e){
    		if (e.getKey() == e.TAB) {
    			if (t === this.df && !e.shiftKey) {
    				e.stopEvent();
    				this.tf.focus();
    			}
    			if (t === this.tf && e.shiftKey) {
    				e.stopEvent();
    				this.df.focus();
    			}
    		}
    	},

    	setSize: function(w, h){
    		if (!w) {
    			return;
    		}
    		if ('below' == this.timePosition) {
    			this.df.setSize(w, h);
    			this.tf.setSize(w, h)
    			if (Ext.isIE) {
    				this.df.el.up('td').setWidth(w);
    				this.tf.el.up('td').setWidth(w);
    			}
    		}
    		else {
    			this.df.setSize(w - this.timeWidth - 4, h);
    			this.tf.setSize(this.timeWidth, h);

    			if (Ext.isIE) {
    				this.df.el.up('td').setWidth(w - this.timeWidth - 4);
    				this.tf.el.up('td').setWidth(this.timeWidth);
    			}
    		}

    	},

    	setValue: function(val){
    		if (!val) {
    			this.setDate('');
    			this.setTime('');
    			this.updateValue();
    			return;
    		}
    		// clear cross frame AIR nonsense
    		val = new Date(val.getTime());
    		var da, time;
    		if (Ext.isDate(val)) {
    			this.setDate(val);
    			this.setTime(val);
    			this.dateValue = new Date(val);
    		}
    		else {
    			da = val.split(this.dtSeparator);
    			this.setDate(da[0]);
    			if (da[1]) {
    				this.setTime(da[1]);
    			}
    		}
    		this.updateValue();
    	},

    	getValue: function(){
    		// create new instance of date
    		return this.dateValue ? new Date(this.dateValue) : '';
    	},

    	onMouseDown: function(e){
    		// just to prevent blur event when clicked in the middle of fields
    		this.wrapClick = 'td' === e.target.nodeName.toLowerCase();
    	},

    	onFocus: function(){
    		if (!this.hasFocus) {
    			this.hasFocus = true;
    			this.startValue = this.getValue();
    			this.fireEvent("focus", this);
    		}
    	},

    	onBlur: function(f){
    		// called by both DateField and TimeField blur events

    		// revert focus to previous field if clicked in between
    		if (this.wrapClick) {
    			f.focus();
    			this.wrapClick = false;
    		}

    		// update underlying value
    		if (f === this.df) {
    			this.updateDate();
    		}
    		else {
    			this.updateTime();
    		}
    		this.updateHidden();

    		// fire events later
    		(function(){
    			if (!this.df.hasFocus && !this.tf.hasFocus) {
    				var v = this.getValue();
    				if (String(v) !== String(this.startValue)) {
    					this.fireEvent("change", this, v, this.startValue);
    				}
    				this.hasFocus = false;
    				this.fireEvent('blur', this);
    			}
    		}).defer(100, this);

    	},
    	updateDate: function(){

    		var d = this.df.getValue();
    		if (d) {
    			if (!Ext.isDate(this.dateValue)) {
    				this.initDateValue();
    				if (!this.tf.getValue()) {
    					this.setTime(this.dateValue);
    				}
    			}
    			this.dateValue.setFullYear(d.getFullYear());
    			this.dateValue.setMonth(d.getMonth());
    			this.dateValue.setDate(d.getDate());
    		}
    		else {
    			this.dateValue = '';
    			this.setTime('');
    		}
    	},
    	updateTime: function(){
    		var t = this.tf.getValue();
    		if (t && !Ext.isDate(t)) {
    			t = Date.parseDate(t, this.tf.format);
    		}
    		if (t && !this.df.getValue()) {
    			this.initDateValue();
    			this.setDate(this.dateValue);
    		}
    		if (Ext.isDate(this.dateValue)) {
    			if (t) {
    				this.dateValue.setHours(t.getHours());
    				this.dateValue.setMinutes(t.getMinutes());
    				this.dateValue.setSeconds(t.getSeconds());
    			}
    			else {
    				this.dateValue.setHours(0);
    				this.dateValue.setMinutes(0);
    				this.dateValue.setSeconds(0);
    			}
    		}
    	},
    	initDateValue: function(){
    		this.dateValue = this.otherToNow ? new Date() : new Date(1970, 0, 1, 0, 0, 0);
    	},
    	updateHidden: function(){
    		if (this.isRendered) {
    			var value = Ext.isDate(this.dateValue) ? this.dateValue.format(this.hiddenFormat) : '';
    			this.el.dom.value = value;
    		}
    	},
    	updateValue: function(){

    		this.updateDate();
    		this.updateTime();
    		this.updateHidden();

    		return;

    	},
    	setDate: function(date){
    		this.df.setValue(date);
    	},
    	setTime: function(date){
    		this.tf.setValue(date);
    	},
    	isValid: function(){
    		return this.df.isValid() && this.tf.isValid();
    	},
    	validate: function(){
    		return this.df.validate() && this.tf.validate();
    	},
    	focus: function(){
    		this.df.focus();
    	},

    	onDisable : function(){
    		if(this.rendered){
    			this.df.disable();
    			this.tf.disable();
    		}
    	},

    	onEnable : function(){
    		if(this.rendered){
    			this.df.enable();
    			this.tf.enable();
    		}
    	}
    });

    // register xtype
    Ext.reg('xdatetime', Ext.ux.form.DateTime);