Index: trunk/src/VBox/ValidationKit/testmanager/core/base.py
===================================================================
--- trunk/src/VBox/ValidationKit/testmanager/core/base.py	(revision 84097)
+++ trunk/src/VBox/ValidationKit/testmanager/core/base.py	(revision 84100)
@@ -606,4 +606,13 @@
         return (lValue, None);
 
+    kdTimestampRegex = {
+        len('2012-10-08 01:54:06'):           r'(\d{4})-([01]\d)-([0123]\d)[ Tt]([012]\d):[0-5]\d:([0-6]\d)$',
+        len('2012-10-08 01:54:06.00'):        r'(\d{4})-([01]\d)-([0123]\d)[ Tt]([012]\d):[0-5]\d:([0-6]\d).\d{2}$',
+        len('2012-10-08 01:54:06.000'):       r'(\d{4})-([01]\d)-([0123]\d)[ Tt]([012]\d):[0-5]\d:([0-6]\d).\d{3}$',
+        len('999999-12-31 00:00:00.00'):      r'(\d{6})-([01]\d)-([0123]\d)[ Tt]([012]\d):[0-5]\d:([0-6]\d).\d{2}$',
+        len('9999-12-31 23:59:59.999999'):    r'(\d{4})-([01]\d)-([0123]\d)[ Tt]([012]\d):[0-5]\d:([0-6]\d).\d{6}$',
+        len('9999-12-31T23:59:59.999999999'): r'(\d{4})-([01]\d)-([0123]\d)[ Tt]([012]\d):[0-5]\d:([0-6]\d).\d{9}$',
+    };
+
     @staticmethod
     def validateTs(sValue, aoNilValues = tuple([None, '']), fAllowNull = True):
@@ -614,50 +623,48 @@
             return (sValue, None);
 
+        # Validate and strip off the timezone stuff.
+        if sValue[-1] in 'Zz':
+            sStripped = sValue[:-1];
+            sValue = sStripped + 'Z';
+        elif len(sValue) >= 19 + 3:
+            oRes = re.match(r'^.*[+-](\d\d):(\d\d)$', sValue);
+            if oRes is not None:
+                if int(oRes.group(6)) > 12 or int(oRes.group(7)) >= 60:
+                    return (sValue, 'Invalid timezone offset.');
+                sStripped = sValue[:-6];
+            else:
+                sStripped = sValue;
+        else:
+            sStripped = sValue;
+
+        # Used the stripped value length to find regular expression for validating and parsing the timestamp.
         sError = None;
-        if len(sValue) == len('2012-10-08 01:54:06.364207+02:00'):
-            oRes = re.match(r'(\d{4})-([01]\d)-([0123])\d ([012]\d):[0-5]\d:([0-6]\d).\d{6}[+-](\d\d):(\d\d)', sValue);
-            if    oRes is not None \
-              and (   int(oRes.group(6)) >  12 \
-                   or int(oRes.group(7)) >= 60):
-                sError = 'Invalid timezone offset.';
-        elif len(sValue) == len('2012-10-08 01:54:06.00'):
-            oRes = re.match(r'(\d{4})-([01]\d)-([0123])\d[ Tt]([012]\d):[0-5]\d:([0-6]\d).\d{2}', sValue);
-        elif len(sValue) == len('2012-10-08 01:54:06.00Z'):
-            oRes = re.match(r'(\d{4})-([01]\d)-([0123])\d[ Tt]([012]\d):[0-5]\d:([0-6]\d).\d{2}[Zz]', sValue);
-        elif len(sValue) == len('9999-12-31 23:59:59.999999'):
-            oRes = re.match(r'(\d{4})-([01]\d)-([0123])\d[ Tt]([012]\d):[0-5]\d:([0-6]\d).\d{6}', sValue);
-        elif len(sValue) == len('9999-12-31 23:59:59.999999Z'):
-            oRes = re.match(r'(\d{4})-([01]\d)-([0123])\d[ Tt]([012]\d):[0-5]\d:([0-6]\d).\d{6}[Zz]', sValue);
-        elif len(sValue) == len('999999-12-31 00:00:00.00'):
-            oRes = re.match(r'(\d{6})-([01]\d)-([0123])\d[ Tt]([012]\d):[0-5]\d:([0-6]\d).\d{2}', sValue);
-        elif len(sValue) == len('9999-12-31T23:59:59.999999Z'):
-            oRes = re.match(r'(\d{4})-([01]\d)-([0123])\d[Tt]([012]\d):[0-5]\d:([0-6]\d).\d{6}[Zz]', sValue);
-        elif len(sValue) == len('9999-12-31T23:59:59.999999999Z'):
-            oRes = re.match(r'(\d{4})-([01]\d)-([0123])\d[Tt]([012]\d):[0-5]\d:([0-6]\d).\d{9}[Zz]', sValue);
+        sRegExp = ModelDataBase.kdTimestampRegex.get(len(sStripped), None);
+        if sRegExp:
+            oRes = re.match(sRegExp, sStripped);
+            if oRes is not None:
+                iYear  = int(oRes.group(1));
+                if iYear % 4 == 0 and (iYear % 100 != 0  or iYear % 400 == 0):
+                    acDaysOfMonth = [31, 29, 31,  30, 31, 30,  31, 31, 30,  31, 30, 31];
+                else:
+                    acDaysOfMonth = [31, 28, 31,  30, 31, 30,  31, 31, 30,  31, 30, 31];
+                iMonth = int(oRes.group(2));
+                iDay   = int(oRes.group(3));
+                iHour  = int(oRes.group(4));
+                iSec   = int(oRes.group(5));
+                if iMonth > 12 or iMonth <= 0:
+                    sError = 'Invalid timestamp month.';
+                elif iDay > acDaysOfMonth[iMonth - 1]:
+                    sError = 'Invalid timestamp day-of-month (%02d has %d days).' % (iMonth, acDaysOfMonth[iMonth - 1]);
+                elif iHour > 23:
+                    sError = 'Invalid timestamp hour.'
+                elif iSec >= 61:
+                    sError = 'Invalid timestamp second.'
+                elif iSec >= 60:
+                    sError = 'Invalid timestamp: no leap seconds, please.'
+            else:
+                sError = 'Invalid timestamp (validation regexp: %s).' % (sRegExp,);
         else:
-            return (sValue, 'Invalid timestamp length.');
-
-        if oRes is None:
-            sError = 'Invalid timestamp (format: 2012-10-08 01:54:06.364207+02:00).';
-        else:
-            iYear  = int(oRes.group(1));
-            if iYear % 4 == 0 and (iYear % 100 != 0  or iYear % 400 == 0):
-                acDaysOfMonth = [31, 29, 31,  30, 31, 30,  31, 31, 30,  31, 30, 31];
-            else:
-                acDaysOfMonth = [31, 28, 31,  30, 31, 30,  31, 31, 30,  31, 30, 31];
-            iMonth = int(oRes.group(2));
-            iDay   = int(oRes.group(3));
-            iHour  = int(oRes.group(4));
-            iSec   = int(oRes.group(5));
-            if iMonth > 12:
-                sError = 'Invalid timestamp month.';
-            elif iDay > acDaysOfMonth[iMonth - 1]:
-                sError = 'Invalid timestamp day-of-month (%02d has %d days).' % (iMonth, acDaysOfMonth[iMonth - 1]);
-            elif iHour > 23:
-                sError = 'Invalid timestamp hour.'
-            elif iSec >= 61:
-                sError = 'Invalid timestamp second.'
-            elif iSec >= 60:
-                sError = 'Invalid timestamp: no leap seconds, please.'
+            sError = 'Invalid timestamp length.';
         return (sValue, sError);
 
