← Back to team overview

zorba-coders team mailing list archive

[Merge] lp:~zorba-coders/zorba/bug-1053113 into lp:zorba

 

Paul J. Lucas has proposed merging lp:~zorba-coders/zorba/bug-1053113 into lp:zorba.

Commit message:
Moved dateTime module into the core and added parse-date(), parse-time(), parse-dateTime(), and utc-offset().

Requested reviews:
  Paul J. Lucas (paul-lucas)
Related bugs:
  Bug #1053113 in Zorba: "parse-date and parse-dateTime functionality"
  https://bugs.launchpad.net/zorba/+bug/1053113

For more details, see:
https://code.launchpad.net/~zorba-coders/zorba/bug-1053113/+merge/141618

Moved dateTime module into the core and added parse-date(), parse-time(), parse-dateTime(), and utc-offset().
-- 
https://code.launchpad.net/~zorba-coders/zorba/bug-1053113/+merge/141618
Your team Zorba Coders is subscribed to branch lp:zorba.
=== modified file 'CMakeLists.txt'
--- CMakeLists.txt	2012-10-08 12:09:36 +0000
+++ CMakeLists.txt	2013-01-02 14:49:24 +0000
@@ -76,25 +76,28 @@
 ###############################################################################
 # Check for system include files, features, etc.
 ###############################################################################
+INCLUDE(CheckCXXSourceCompiles)
+INCLUDE(CheckFunctionExists)
+INCLUDE(CheckIncludeFileCXX)
 INCLUDE(CheckIncludeFiles)
+INCLUDE(CheckLibraryExists)
+INCLUDE(CheckStructHasMember)
 INCLUDE(CheckSymbolExists)
-INCLUDE(CheckFunctionExists)
-INCLUDE(CheckLibraryExists)
+INCLUDE(CheckTypeSize)
 INCLUDE(CheckVariableExists)
-INCLUDE(CheckIncludeFileCXX)
-INCLUDE(CheckTypeSize)
-INCLUDE(CheckCXXSourceCompiles)
 
-CHECK_INCLUDE_FILES ("sys/param.h;sys/mount.h"      ZORBA_HAVE_SYS_MOUNT_H)
-CHECK_INCLUDE_FILES ("unicode/utypes.h"             ZORBA_HAVE_UTYPES_H)
 CHECK_INCLUDE_FILES ("unicode/coll.h"               ZORBA_HAVE_COLL_H)
-CHECK_INCLUDE_FILES ("unicode/ustring.h"            ZORBA_HAVE_USTRING_H)
+CHECK_INCLUDE_FILES ("iconv.h"                      ZORBA_HAVE_ICONV_H)
 CHECK_INCLUDE_FILES ("inttypes.h"                   ZORBA_HAVE_INTTYPES_H)
+CHECK_INCLUDE_FILES ("limits.h"                     ZORBA_HAVE_LIMITS_H)
 CHECK_INCLUDE_FILES ("stdint.h"                     ZORBA_HAVE_STDINT_H)
 CHECK_INCLUDE_FILES ("stdlib.h"                     ZORBA_HAVE_STDLIB_H)
-CHECK_INCLUDE_FILES ("limits.h"                     ZORBA_HAVE_LIMITS_H)
+CHECK_INCLUDE_FILES ("sys/param.h;sys/mount.h"      ZORBA_HAVE_SYS_MOUNT_H)
 CHECK_INCLUDE_FILES ("sys/types.h"                  ZORBA_HAVE_SYS_TYPES_H)
-CHECK_INCLUDE_FILES ("iconv.h"                      ZORBA_HAVE_ICONV_H)
+CHECK_INCLUDE_FILES ("tzfile.h"                     ZORBA_HAVE_TZFILE_H)
+CHECK_INCLUDE_FILES ("unicode/ustring.h"            ZORBA_HAVE_USTRING_H)
+CHECK_INCLUDE_FILES ("unicode/utypes.h"             ZORBA_HAVE_UTYPES_H)
+
 IF (NOT APPLE OR ${CMAKE_SYSTEM_VERSION} VERSION_GREATER "10.4")
   # execinfo is found by this macro when cross compiling for Mac OS X 10.4
   # although it shouldn't be found for this platform
@@ -124,6 +127,9 @@
 CHECK_TYPE_SIZE("__int32" ZORBA_HAVE_MS_INT32) 
 CHECK_TYPE_SIZE("int64_t" ZORBA_HAVE_INT64_T) 
 
+CHECK_STRUCT_HAS_MEMBER("struct tm" tm_gmtoff time.h 	ZORBA_HAVE_STRUCT_TM_TM_GMTOFF)
+CHECK_STRUCT_HAS_MEMBER("struct tm" __tm_gmtoff time.h 	ZORBA_HAVE_STRUCT_TM___TM_GMTOFF)
+
 # C++ built-in type sizes
 CHECK_TYPE_SIZE("double" ZORBA_SIZEOF_DOUBLE BUILTIN_TYPES_ONLY) 
 CHECK_TYPE_SIZE("float" ZORBA_SIZEOF_FLOAT BUILTIN_TYPES_ONLY) 

=== modified file 'ChangeLog'
--- ChangeLog	2013-01-02 02:33:53 +0000
+++ ChangeLog	2013-01-02 14:49:24 +0000
@@ -9,8 +9,13 @@
 	when resolving URIs.
   * Can now specify jsoniq-strip-top-level-array option to parse-json() to
     strip the top-level array from JSON streams.
+<<<<<<< TREE
   * New info-extraction module for querying concepts and entities in
 	natural language text.
+=======
+  * In the datetime module, added parse-date(), parse-dateTime(), parse-time(),
+    and utc-offset().
+>>>>>>> MERGE-SOURCE
   * Extended cast and castable expression to allow any simple target type
     (as specified by XQuery 3.0)
 

=== modified file 'include/zorba/config.h.cmake'
--- include/zorba/config.h.cmake	2012-12-12 19:34:45 +0000
+++ include/zorba/config.h.cmake	2013-01-02 14:49:24 +0000
@@ -50,6 +50,7 @@
 #cmakedefine ZORBA_HAVE_STDLIB_H
 #cmakedefine ZORBA_HAVE_SYS_MOUNT_H
 #cmakedefine ZORBA_HAVE_SYS_TYPES_H
+#cmakedefine ZORBA_HAVE_TZFILE_H
 #cmakedefine ZORBA_HAVE_USTRING_H
 #cmakedefine ZORBA_HAVE_UTYPES_H
 #cmakedefine ZORBA_HAVE_UUID_H
@@ -69,6 +70,10 @@
 #cmakedefine ZORBA_HAVE_MS_INT32
 #cmakedefine ZORBA_HAVE_MS_UINT32
 #cmakedefine ZORBA_HAVE_UINT32_T
+#cmakedefine ZORBA_HAVE_STRUCT_TM_TM_GMTOFF
+#cmakedefine ZORBA_HAVE_STRUCT_TM___TM_GMTOFF
+
+// Platform type sizes
 #cmakedefine ZORBA_SIZEOF_DOUBLE        @ZORBA_SIZEOF_DOUBLE@
 #cmakedefine ZORBA_SIZEOF_FLOAT         @ZORBA_SIZEOF_FLOAT@
 #cmakedefine ZORBA_SIZEOF_INT           @ZORBA_SIZEOF_INT@

=== modified file 'include/zorba/diagnostic.h'
--- include/zorba/diagnostic.h	2012-09-19 21:16:15 +0000
+++ include/zorba/diagnostic.h	2013-01-02 14:49:24 +0000
@@ -246,8 +246,10 @@
 
 # ifdef ZORBA_WITH_JSON
   JSONIQ_CORE,
-  JSONIQ_UPDATE
-# endif
+  JSONIQ_UPDATE,
+# endif /* ZORBA_WITH_JSON */
+
+  ZORBA_CORE_MODULE                     // Zorba Core Module
 };
 
 /**

=== modified file 'include/zorba/pregenerated/diagnostic_list.h'
--- include/zorba/pregenerated/diagnostic_list.h	2012-12-21 22:05:39 +0000
+++ include/zorba/pregenerated/diagnostic_list.h	2013-01-02 14:49:24 +0000
@@ -796,6 +796,16 @@
 
 extern ZORBA_DLL_PUBLIC ZorbaErrorCode XSST0010;
 
+extern ZORBA_DLL_PUBLIC ZorbaErrorCode ZDTP0001_INVALID_SPECIFICATION;
+
+extern ZORBA_DLL_PUBLIC ZorbaErrorCode ZDTP0002_INSUFFICIENT_BUFFER;
+
+extern ZORBA_DLL_PUBLIC ZorbaErrorCode ZDTP0003_INVALID_VALUE;
+
+extern ZORBA_DLL_PUBLIC ZorbaErrorCode ZDTP0004_LITERAL_MISMATCH;
+
+extern ZORBA_DLL_PUBLIC ZorbaErrorCode ZDTP0005_INCOMPLETE_DATE_OR_TIME;
+
 extern ZORBA_DLL_PUBLIC ZorbaErrorCode ZJPE0001_ILLEGAL_CHARACTER;
 
 extern ZORBA_DLL_PUBLIC ZorbaErrorCode ZJPE0002_ILLEGAL_CODEPOINT;

=== modified file 'modules/com/zorba-xquery/www/modules/datetime.xq'
--- modules/com/zorba-xquery/www/modules/datetime.xq	2012-09-19 21:16:15 +0000
+++ modules/com/zorba-xquery/www/modules/datetime.xq	2013-01-02 14:49:24 +0000
@@ -17,51 +17,155 @@
 :)
 
 (:~
- : This module provides functions to retrieve the current dateTime.
+ : This module provides functions to retrieve the current dateTime and to
+ : parse dates and times.
+ :
  : In contrast to the current-dateTime functions specified in
- : "XQuery Functions and Operators" the functions in this module are nondeterministic.
- : That is, they do not return the current-dateTime from the dynamic context but return the actual value.
+ : <a href="http://www.w3.org/TR/xpath-functions-30/";>XQuery Functions and
+ : Operators</a>, the functions in this module are nondeterministic, that is,
+ : they do not return the current dateTime from the dynamic context, but return
+ : the actual value.
+ :
+ : Dates and times are parsed according to the format given by
+ : <a href="http://pubs.opengroup.org/onlinepubs/007904975/functions/strptime.html";>strptime</a>.
+ : However, date and time values must be "complete."
+ : For a date, the year and either month and day or day of the year must have
+ : been parsed.
+ : For a time, the hour must have been parsed.
+ : (If either the minute, second, or timezone has not been parsed, they default
+ : to 0.)
+ : For a dateTime, the parsing requirements of both date and time must be met.
  :
  : @author Matthias Brantner
+ : @author Paul J. Lucas
  : @see http://www.w3.org/TR/xpath-functions/#context
  : @project XDM/atomic
  :
  :)
 module namespace datetime = "http://www.zorba-xquery.com/modules/datetime";;
+
 declare namespace an = "http://www.zorba-xquery.com/annotations";;
+declare namespace zerr = "http://www.zorba-xquery.com/errors";;
+
 declare namespace ver = "http://www.zorba-xquery.com/options/versioning";;
 declare option ver:module-version "2.0";
 
 (:~
- : Return the current dateTime value.
- : Please note, that this function is not stable. It returns the
- : dateTime value of the date and time the function has actually been invoked.
+ : Gets the current date value in Universal time.
+ : Note that this function is not stable: it returns the value of the date when
+ : the function is invoked.
+ :
+ : @return the non-stable date value
+ :)
+declare %an:nondeterministic function datetime:current-date()
+  as xs:date external;
+
+(:~
+ : Gets the current dateTime value in Universal time.
+ : Note that this function is not stable: it returns the value of the date and
+ : time when the function is invoked.
  :
  : @return the non-stable datetime value
  :)
-declare %an:nondeterministic function datetime:current-dateTime ( ) as xs:dateTime external;
+declare %an:nondeterministic function datetime:current-dateTime()
+  as xs:dateTime external;
 
 (:~
- : Return the current time value.
- : Please note, that this function is not stable. It returns the
- : time value of the date and time the function has actually been invoked.
+ : Return the current time value in Universal time.
+ : Note that this function is not stable: it returns the value of the time when
+ : the function is invoked.
  :
  : @return the non-stable time value
  :)
-declare %an:nondeterministic function datetime:current-time ( ) as xs:time external;
-
-(:~
- : Return the current date value.
- : Please note, that this function is not stable. It returns the
- : dat value of the date the function has been actually invoked.
- :
- : @return the non-stable date value
- :)
-declare %an:nondeterministic function datetime:current-date ( ) as xs:date external;
-
-(:~
- : Return the the number of milliseconds since the Epoch.
+declare %an:nondeterministic function datetime:current-time()
+  as xs:time external;
+
+(:~
+ : Parses a date from a string.
+ :
+ : @param $input The string to parse.
+ : @param $format The format string containing zero or more conversion
+ : specifications and ordinary characters.  All ordinary characters are matched
+ : exactly with the buffer; all whitespace characters match any amount of
+ : whitespace in the buffer.
+ : @return Returns an xs:date.
+ : @error zerr:ZDTP0001 if $format contains an invalid conversion specification.
+ : @error zerr:ZDTP0002 if $input is insufficient for $format.
+ : @error zerr:ZDTP0003 if $input contains an invalid value for a conversion
+ : specification.
+ : @error zerr:ZDTP0004 if there is a literal characer mismatch between $input
+ : and $format.
+ : @error zerr:ZDTP0005 if the date is incomplete.
+ : @example test/rbkt/Queries/zorba/datetime/datetime-parse-date-uD-1.xq
+ : @example test/rbkt/Queries/zorba/datetime/datetime-parse-date-uF-1.xq
+ :)
+declare function datetime:parse-date(
+  $input as xs:string,
+  $format as xs:string
+) as xs:date external;
+
+(:~
+ : Parses a dateTime from a string.
+ :
+ : @param $input The string to parse.
+ : @param $format The format string containing zero or more conversion
+ : specifications and ordinary characters.  All ordinary characters are matched
+ : exactly with the buffer; all whitespace characters match any amount of
+ : whitespace in the buffer.
+ : @return Returns an xs:dateTime.
+ : @error zerr:ZDTP0001 if $format contains an invalid conversion specification.
+ : @error zerr:ZDTP0002 if $input is insufficient for $format.
+ : @error zerr:ZDTP0003 if $input contains an invalid value for a conversion
+ : specification.
+ : @error zerr:ZDTP0004 if there is a literal characer mismatch between $input
+ : and $format.
+ : @error zerr:ZDTP0005 if either the date or time is incomplete.
+ : @example test/rbkt/Queries/zorba/datetime/datetime-parse-dateTime-uFTZ-1.xq
+ :)
+declare function datetime:parse-dateTime(
+  $input as xs:string,
+  $format as xs:string
+) as xs:dateTime external;
+
+(:~
+ : Parses a time from a string.
+ :
+ : @param $input The string to parse.
+ : @param $format The format string containing zero or more conversion
+ : specifications and ordinary characters.  All ordinary characters are matched
+ : exactly with the buffer; all whitespace characters match any amount of
+ : whitespace in the buffer.
+ : @return Returns an xs:time.
+ : @error zerr:ZDTP0001 if $format contains an invalid conversion specification.
+ : @error zerr:ZDTP0002 if $input is insufficient for $format.
+ : @error zerr:ZDTP0003 if $input contains an invalid value for a conversion
+ : specification.
+ : @error zerr:ZDTP0004 if there is a literal characer mismatch between $input
+ : and $format.
+ : @error zerr:ZDTP0005 if the hour has not been parsed.
+ : @example test/rbkt/Queries/zorba/datetime/datetime-parse-time-uH-1.xq
+ : @example test/rbkt/Queries/zorba/datetime/datetime-parse-time-uIMS-1.xq
+ :)
+declare function datetime:parse-time(
+  $input as xs:string,
+  $format as xs:string
+) as xs:time external;
+
+(:~
+ : Gets the the number of milliseconds since epoch.
  :
  : @return the said number of milliseconds.
  :)
-declare %an:nondeterministic function datetime:timestamp ( ) as xs:long external;
+declare %an:nondeterministic function datetime:timestamp()
+  as xs:long external;
+
+(:~
+ : Gets the offset of the current timezone from Universal time.
+ :
+ : @return the offset in seconds with positive values being east of the prime
+ : meridian.
+ :)
+declare %an:nondeterministic function datetime:utc-offset()
+  as xs:long external;
+
+(: vim:set et sw=2 ts=2: :)

=== removed directory 'modules/com/zorba-xquery/www/modules/datetime.xq.src'
=== removed file 'modules/com/zorba-xquery/www/modules/datetime.xq.src/datetime.cpp'
--- modules/com/zorba-xquery/www/modules/datetime.xq.src/datetime.cpp	2012-09-19 21:16:15 +0000
+++ modules/com/zorba-xquery/www/modules/datetime.xq.src/datetime.cpp	1970-01-01 00:00:00 +0000
@@ -1,209 +0,0 @@
-/*
- * Copyright 2006-2010 The FLWOR Foundation.
- * 
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- * 
- * http://www.apache.org/licenses/LICENSE-2.0
- * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-#include "datetime.h"
-
-#include <zorba/item_factory.h>
-#include <zorba/singleton_item_sequence.h>
-
-#include <time.h>
-#include <sys/timeb.h>
-#ifdef UNIX
-#include <sys/time.h>
-#endif
-
-namespace zorba { namespace datetimemodule {
-
-void
-compute_date_time(
-    struct ::tm&    gmtm,
-    long&           timezone,
-    unsigned short& millitm)
-{
-  int lSummerTimeShift = 0;
-#if defined (WIN32)
-  struct _timeb timebuffer;
-  _ftime_s( &timebuffer );
-  localtime_s(&gmtm, &timebuffer.time); //thread safe localtime on Windows
-  lSummerTimeShift = -timebuffer.timezone * 60;
-  if (gmtm.tm_isdst != 0)
-    lSummerTimeShift += 3600;
-#else
-  struct timeb timebuffer;
-  ftime( &timebuffer );
-  localtime_r(&timebuffer.time, &gmtm); //thread safe localtime on Linux
-  localtime_r(&timebuffer.time, &gmtm); //thread safe localtime on Linux
-  lSummerTimeShift = gmtm.tm_gmtoff;
-#endif
-
-  timezone = lSummerTimeShift; // in seconds
-  millitm = timebuffer.millitm;
-}
-
-/******************************************************************************
- *****************************************************************************/
-zorba::ItemSequence_t
-CurrentDateTimeFunction::evaluate(
-  const Arguments_t& aArgs,
-  const zorba::StaticContext* aSctx,
-  const zorba::DynamicContext* aDctx) const
-{
-  struct ::tm    gmtm;
-  long           lTimezone;
-  unsigned short lMilliTm;
-
-  compute_date_time(gmtm, lTimezone, lMilliTm);
-
-  zorba::Item lDateTime = 
-    Zorba::getInstance(0)->getItemFactory()->createDateTime(
-      static_cast<short>(gmtm.tm_year + 1900),
-      static_cast<short>(gmtm.tm_mon + 1),
-      static_cast<short>(gmtm.tm_mday),
-      static_cast<short>(gmtm.tm_hour),
-      static_cast<short>(gmtm.tm_min),
-      gmtm.tm_sec + lMilliTm/1000.0,
-      static_cast<short>(lTimezone/3600)
-    );
-
-  return zorba::ItemSequence_t(new zorba::SingletonItemSequence(lDateTime));
-}
-
-/******************************************************************************
- *****************************************************************************/
-zorba::ItemSequence_t
-CurrentDateFunction::evaluate(
-  const Arguments_t& aArgs,
-  const zorba::StaticContext* aSctx,
-  const zorba::DynamicContext* aDctx) const
-{
-  struct ::tm    gmtm;
-  long           lTimezone;
-  unsigned short lMilliTm;
-
-  compute_date_time(gmtm, lTimezone, lMilliTm);
-
-  zorba::Item lDateTime = 
-    Zorba::getInstance(0)->getItemFactory()->createDate(
-      static_cast<short>(gmtm.tm_year + 1900),
-      static_cast<short>(gmtm.tm_mon + 1),
-      static_cast<short>(gmtm.tm_mday)
-    );
-
-  return zorba::ItemSequence_t(new zorba::SingletonItemSequence(lDateTime));
-}
-
-/******************************************************************************
- *****************************************************************************/
-zorba::ItemSequence_t
-CurrentTimeFunction::evaluate(
-  const Arguments_t& aArgs,
-  const zorba::StaticContext* aSctx,
-  const zorba::DynamicContext* aDctx) const
-{
-  struct ::tm    gmtm;
-  long           lTimezone;
-  unsigned short lMilliTm;
-
-  compute_date_time(gmtm, lTimezone, lMilliTm);
-
-  zorba::Item lDateTime = 
-    Zorba::getInstance(0)->getItemFactory()->createTime(
-      static_cast<short>(gmtm.tm_hour),
-      static_cast<short>(gmtm.tm_min),
-      gmtm.tm_sec + lMilliTm/1000.0,
-      static_cast<short>(lTimezone/3600)
-    );
-
-  return zorba::ItemSequence_t(new zorba::SingletonItemSequence(lDateTime));
-}
-
-/******************************************************************************
- *****************************************************************************/
-
-zorba::ItemSequence_t
-TimestampFunction::evaluate(
-  const Arguments_t& aArgs,
-  const zorba::StaticContext* aSctx,
-  const zorba::DynamicContext* aDctx) const
-{
-  zorba::Item lMillis;
-#if WIN32
-  time_t t0;
-  time(&t0);
-  lMillis = Zorba::getInstance(0)->getItemFactory()->createLong(t0*1000);
-#else
-  timeval tv;
-  gettimeofday(&tv, 0);
-  long long millis = tv.tv_sec;
-  millis = millis * 1000 + tv.tv_usec/1000;
-  lMillis = Zorba::getInstance(0)->getItemFactory()->createLong(millis);
-#endif
-
-  return zorba::ItemSequence_t(new zorba::SingletonItemSequence(lMillis));
-}
-
-/******************************************************************************
- *****************************************************************************/
-zorba::ExternalFunction*
-DateTimeModule::getExternalFunction(const zorba::String& aLocalname)
-{
-  zorba::ExternalFunction*& lFunc = theFunctions[aLocalname];
-  if (!lFunc) {
-    if (aLocalname == "current-dateTime") {
-      lFunc = new CurrentDateTimeFunction(this);
-    } else if (aLocalname == "current-date") {
-      lFunc = new CurrentDateFunction(this);
-    } else if (aLocalname == "current-time") {
-      lFunc = new CurrentTimeFunction(this);
-    } else if (aLocalname == "timestamp") {
-      lFunc = new TimestampFunction(this);
-    }
-  }
-  return lFunc;
-}
-
-/******************************************************************************
- *****************************************************************************/
-DateTimeModule::~DateTimeModule()
-{
-  for (FuncMap_t::const_iterator lIter = theFunctions.begin();
-       lIter != theFunctions.end(); ++lIter) {
-    delete lIter->second;
-  }
-  theFunctions.clear();
-}
-
-/******************************************************************************
- *****************************************************************************/
-void
-DateTimeModule::destroy()
-{
-  if (!dynamic_cast<DateTimeModule*>(this)) {
-    return;
-  }
-  delete this;
-}
-
-} /* namespace datetimemodule */ } /* namespace zorba */
-
-#ifdef WIN32
-#  define DLL_EXPORT __declspec(dllexport)
-#else
-#  define DLL_EXPORT __attribute__ ((visibility("default")))
-#endif
-
-extern "C" DLL_EXPORT zorba::ExternalModule* createModule() {
-  return new zorba::datetimemodule::DateTimeModule();
-}

=== removed file 'modules/com/zorba-xquery/www/modules/datetime.xq.src/datetime.h'
--- modules/com/zorba-xquery/www/modules/datetime.xq.src/datetime.h	2012-09-19 21:16:15 +0000
+++ modules/com/zorba-xquery/www/modules/datetime.xq.src/datetime.h	1970-01-01 00:00:00 +0000
@@ -1,161 +0,0 @@
-/*
- * Copyright 2006-2010 The FLWOR Foundation.
- * 
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- * 
- * http://www.apache.org/licenses/LICENSE-2.0
- * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-#ifndef ZORBA_FILEMODULE_FILE_H
-#define ZORBA_FILEMODULE_FILE_H
-
-#include <map>
-#include <zorba/zorba.h>
-#include <zorba/external_module.h>
-#include <zorba/function.h>
-
-namespace zorba { namespace datetimemodule {
-
-/******************************************************************************
- *****************************************************************************/
-class DateTimeModule : public ExternalModule
-{
-protected:
-  class ltstr
-  {
-  public:
-    bool operator()(const String& s1, const String& s2) const
-    {
-      return s1.compare(s2) < 0;
-    }
-  };
-  
-  typedef std::map<String, ExternalFunction*, ltstr> FuncMap_t;
-
-  FuncMap_t theFunctions;
-
-public:
-  virtual zorba::String
-  getURI() const { return "http://www.zorba-xquery.com/modules/datetime";; }
-
-  virtual zorba::ExternalFunction*
-  getExternalFunction(const zorba::String& aLocalname);
-
-  virtual void
-  destroy();
-
-  virtual
-  ~DateTimeModule();
-};
-
-
-/******************************************************************************
- *****************************************************************************/
-class CurrentDateTimeFunction : public ContextualExternalFunction
-{
-public:
-  CurrentDateTimeFunction(const DateTimeModule* aModule)
-    : theModule(aModule) {}
-
-  virtual ~CurrentDateTimeFunction() {}
-
-  virtual zorba::String
-  getLocalName() const { return "current-dateTime"; }
-
-  virtual zorba::ItemSequence_t
-  evaluate(const Arguments_t&,
-           const zorba::StaticContext*,
-           const zorba::DynamicContext*) const;
-
-  virtual String
-  getURI() const { return theModule->getURI(); }
-
-protected:
-  const DateTimeModule* theModule;
-};
-
-/******************************************************************************
- *****************************************************************************/
-class CurrentDateFunction : public ContextualExternalFunction
-{
-public:
-  CurrentDateFunction(const DateTimeModule* aModule)
-    : theModule(aModule) {}
-
-  virtual ~CurrentDateFunction() {}
-
-  virtual zorba::String
-  getLocalName() const { return "current-date"; }
-
-  virtual zorba::ItemSequence_t
-  evaluate(const Arguments_t&,
-           const zorba::StaticContext*,
-           const zorba::DynamicContext*) const;
-
-  virtual String
-  getURI() const { return theModule->getURI(); }
-
-protected:
-  const DateTimeModule* theModule;
-};
-
-/******************************************************************************
- *****************************************************************************/
-class CurrentTimeFunction : public ContextualExternalFunction
-{
-public:
-  CurrentTimeFunction(const DateTimeModule* aModule)
-    : theModule(aModule) {}
-
-  virtual ~CurrentTimeFunction() {}
-
-  virtual zorba::String
-  getLocalName() const { return "current-time"; }
-
-  virtual zorba::ItemSequence_t
-  evaluate(const Arguments_t&,
-           const zorba::StaticContext*,
-           const zorba::DynamicContext*) const;
-
-  virtual String
-  getURI() const { return theModule->getURI(); }
-
-protected:
-  const DateTimeModule* theModule;
-};
-
-/******************************************************************************
- *****************************************************************************/
-class TimestampFunction : public ContextualExternalFunction
-{
-public:
-  TimestampFunction(const DateTimeModule* aModule)
-    : theModule(aModule) {}
-
-  virtual ~TimestampFunction() {}
-
-  virtual zorba::String
-  getLocalName() const { return "timestamp"; }
-
-  virtual zorba::ItemSequence_t
-  evaluate(const Arguments_t&,
-           const zorba::StaticContext*,
-           const zorba::DynamicContext*) const;
-
-  virtual String
-  getURI() const { return theModule->getURI(); }
-
-protected:
-  const DateTimeModule* theModule;
-};
-
-} /* namespace datetimemodule */ } /* namespace zorba */
-
-#endif

=== modified file 'modules/com/zorba-xquery/www/modules/pregenerated/errors.xq'
--- modules/com/zorba-xquery/www/modules/pregenerated/errors.xq	2012-12-10 15:12:58 +0000
+++ modules/com/zorba-xquery/www/modules/pregenerated/errors.xq	2013-01-02 14:49:24 +0000
@@ -865,6 +865,26 @@
 
 (:~
 :)
+declare variable $zerr:ZDTP0001 as xs:QName := fn:QName($zerr:NS, "zerr:ZDTP0001");
+
+(:~
+:)
+declare variable $zerr:ZDTP0002 as xs:QName := fn:QName($zerr:NS, "zerr:ZDTP0002");
+
+(:~
+:)
+declare variable $zerr:ZDTP0003 as xs:QName := fn:QName($zerr:NS, "zerr:ZDTP0003");
+
+(:~
+:)
+declare variable $zerr:ZDTP0004 as xs:QName := fn:QName($zerr:NS, "zerr:ZDTP0004");
+
+(:~
+:)
+declare variable $zerr:ZDTP0005 as xs:QName := fn:QName($zerr:NS, "zerr:ZDTP0005");
+
+(:~
+:)
 declare variable $zerr:ZJPE0001 as xs:QName := fn:QName($zerr:NS, "zerr:ZJPE0001");
 
 (:~

=== modified file 'src/context/static_context.cpp'
--- src/context/static_context.cpp	2012-12-11 20:27:40 +0000
+++ src/context/static_context.cpp	2013-01-02 14:49:24 +0000
@@ -461,6 +461,10 @@
 #endif /* ZORBA_NO_FULL_TEXT */
 
 const char*
+static_context::ZORBA_DATETIME_FN_NS =
+"http://www.zorba-xquery.com/modules/datetime";;
+
+const char*
 static_context::ZORBA_XML_FN_OPTIONS_NS =
 "http://www.zorba-xquery.com/modules/xml-options";;
 
@@ -542,6 +546,7 @@
 #ifndef ZORBA_NO_FULL_TEXT
             ns == ZORBA_FULL_TEXT_FN_NS ||
 #endif /* ZORBA_NO_FULL_TEXT */
+            ns == ZORBA_DATETIME_FN_NS ||
 #ifdef ZORBA_WITH_JSON
             ns == JSONIQ_FN_NS ||
 #endif /* ZORBA_WITH_JSON */

=== modified file 'src/context/static_context.h'
--- src/context/static_context.h	2012-12-06 01:17:18 +0000
+++ src/context/static_context.h	2013-01-02 14:49:24 +0000
@@ -546,6 +546,7 @@
 #ifndef ZORBA_NO_FULL_TEXT
   static const char* ZORBA_FULL_TEXT_FN_NS;
 #endif /* ZORBA_NO_FULL_TEXT */
+  static const char* ZORBA_DATETIME_FN_NS;
   static const char* ZORBA_XML_FN_OPTIONS_NS;
 
   // Namespaces of virtual modules declaring zorba builtin functions

=== modified file 'src/diagnostics/diagnostic.cpp'
--- src/diagnostics/diagnostic.cpp	2012-09-19 21:16:15 +0000
+++ src/diagnostics/diagnostic.cpp	2013-01-02 14:49:24 +0000
@@ -127,6 +127,7 @@
     case XQUERY_USER_DEFINED : o << "user-defined"          ; break;
 
     case ZORBA_API           : o << "Zorba API"             ; break;
+    case ZORBA_CORE_MODULE   : o << "Zorba core module"     ; break;
     case ZORBA_DDF           : o << "Zorba data-definition" ; break;
     case ZORBA_DEBUGGER      : o << "Zorba debugger"        ; break;
     case ZORBA_OS            : o << "operating system"      ; break;

=== modified file 'src/diagnostics/diagnostic_en.xml'
--- src/diagnostics/diagnostic_en.xml	2012-12-29 06:48:09 +0000
+++ src/diagnostics/diagnostic_en.xml	2013-01-02 14:49:24 +0000
@@ -2609,6 +2609,28 @@
       <value>"continue loop" statement not inside while statement</value>
     </diagnostic>
 
+   <!--////////// dateTime ParseErrors /////////////////////////////////////-->
+
+    <diagnostic code="ZDTP0001" name="INVALID_SPECIFICATION">
+      <value>'$1': invalid % conversion specification</value>
+    </diagnostic>
+
+    <diagnostic code="ZDTP0002" name="INSUFFICIENT_BUFFER">
+      <value>"$1": insufficient value to parse for "$2"</value>
+    </diagnostic>
+
+    <diagnostic code="ZDTP0003" name="INVALID_VALUE">
+      <value>"$1": invalid value for conversion specification(s) %$2</value>
+    </diagnostic>
+
+    <diagnostic code="ZDTP0004" name="LITERAL_MISMATCH">
+      <value>'$1': literal character mismatched '$2'</value>
+    </diagnostic>
+
+    <diagnostic code="ZDTP0005" name="INCOMPLETE_DATE_OR_TIME">
+      <value>'$1': incomplete date, time, or dateTime format</value>
+    </diagnostic>
+
    <!--////////// JSON Parse Errors ////////////////////////////////////////-->
 
     <diagnostic code="ZJPE0001" name="ILLEGAL_CHARACTER">
@@ -3834,6 +3856,10 @@
       <value>Zorba API error</value>
     </entry>
 
+    <entry key="Zorba core module error">
+      <value>Zorba core module error</value>
+    </entry>
+
     <entry key="Zorba data-definition error">
       <value>Zorba data-definition error</value>
     </entry>

=== modified file 'src/diagnostics/pregenerated/diagnostic_list.cpp'
--- src/diagnostics/pregenerated/diagnostic_list.cpp	2012-12-21 22:05:39 +0000
+++ src/diagnostics/pregenerated/diagnostic_list.cpp	2013-01-02 14:49:24 +0000
@@ -1172,6 +1172,21 @@
 ZorbaErrorCode XSST0010( "XSST0010" );
 
 
+ZorbaErrorCode ZDTP0001_INVALID_SPECIFICATION( "ZDTP0001" );
+
+
+ZorbaErrorCode ZDTP0002_INSUFFICIENT_BUFFER( "ZDTP0002" );
+
+
+ZorbaErrorCode ZDTP0003_INVALID_VALUE( "ZDTP0003" );
+
+
+ZorbaErrorCode ZDTP0004_LITERAL_MISMATCH( "ZDTP0004" );
+
+
+ZorbaErrorCode ZDTP0005_INCOMPLETE_DATE_OR_TIME( "ZDTP0005" );
+
+
 ZorbaErrorCode ZJPE0001_ILLEGAL_CHARACTER( "ZJPE0001" );
 
 

=== modified file 'src/diagnostics/pregenerated/dict_en.cpp'
--- src/diagnostics/pregenerated/dict_en.cpp	2012-12-29 06:48:09 +0000
+++ src/diagnostics/pregenerated/dict_en.cpp	2013-01-02 14:49:24 +0000
@@ -410,6 +410,11 @@
   { "ZDST0044", "\"$1\": integrity constraint declaration not allowed in main module" },
   { "ZDST0048", "\"$1\": integrity constraint declaration in foreign module" },
   { "ZDST0060", "\"$1\": feature not supported; $2" },
+  { "ZDTP0001", "'$1': invalid % conversion specification" },
+  { "ZDTP0002", "\"$1\": insufficient value to parse for \"$2\"" },
+  { "ZDTP0003", "\"$1\": invalid value for conversion specification(s) %$2" },
+  { "ZDTP0004", "'$1': literal character mismatched '$2'" },
+  { "ZDTP0005", "'$1': incomplete date, time, or dateTime format" },
   { "ZDTY0001", "\"$1\": invalid item type in collection \"$2\"" },
   { "ZDTY0010", "non-node item in domain expression of index $1" },
   { "ZDTY0011", "item type \"$1\" does not match declared type \"$2\" for key expression of index $3" },
@@ -923,6 +928,7 @@
   { "~ZXQP0025_RESOURCE_NOT_FOUND", "resource not found" },
   { "~ZeroLenURI", "zero-length URI (and no base URI given)" },
   { "~Zorba API error", "Zorba API error" },
+  { "~Zorba core module error", "Zorba core module error" },
   { "~Zorba data-definition error", "Zorba data-definition error" },
   { "~Zorba dynamic error", "Zorba dynamic error" },
   { "~Zorba dynamic warning", "Zorba dynamic warning" },

=== modified file 'src/diagnostics/qname.cpp'
--- src/diagnostics/qname.cpp	2012-09-19 21:16:15 +0000
+++ src/diagnostics/qname.cpp	2013-01-02 14:49:24 +0000
@@ -112,7 +112,10 @@
   switch ( name[1] ) {
     case 'A': return ZORBA_API;
     case 'C': return ZORBA_SERIALIZATION;
-    case 'D': return ZORBA_DDF;
+    case 'D': switch ( name[3] ) {
+                case 'P': return ZORBA_CORE_MODULE;
+                default : return ZORBA_DDF;
+              }
     case 'G': return ZORBA_DEBUGGER;
     case 'J': switch ( name[2] ) {
                 case 'P': return JSON_PARSER;

=== modified file 'src/functions/library.cpp'
--- src/functions/library.cpp	2012-09-19 21:16:15 +0000
+++ src/functions/library.cpp	2013-01-02 14:49:24 +0000
@@ -27,33 +27,41 @@
 #include "functions/func_accessors.h"
 #include "functions/func_accessors_impl.h"
 #include "functions/func_any_uri.h"
+#include "functions/func_apply.h"
 #include "functions/func_arithmetic.h"
 #include "functions/func_base64.h"
 #include "functions/func_booleans.h"
 #include "functions/func_booleans_impl.h"
 #include "functions/func_collections.h"
 #include "functions/func_context.h"
-#include "functions/func_other_diagnostics.h"
+#include "functions/func_datetime.h"
+#include "functions/func_documents.h"
 #include "functions/func_durations_dates_times.h"
 #include "functions/func_durations_dates_times_impl.h"
 #include "functions/func_enclosed.h"
 #include "functions/func_errors_and_diagnostics.h"
+#include "functions/func_eval.h"
+#include "functions/func_fetch.h"
 #include "functions/func_fnput.h"
 #include "functions/func_hoist.h"
+#include "functions/func_ic_ddl.h"
 #include "functions/func_index_ddl.h"
 #include "functions/func_index_func.h"
-#include "functions/func_ic_ddl.h"
+#include "functions/func_json.h"
+#include "functions/func_maps.h"
 #include "functions/func_maths.h"
-#include "functions/func_nodes.h"
 #include "functions/func_node_position.h"
 #include "functions/func_node_sort_distinct.h"
+#include "functions/func_nodes.h"
 #include "functions/func_numerics.h"
 #include "functions/func_numerics_impl.h"
-#include "functions/func_parsing_and_serializing.h"
+#include "functions/func_other_diagnostics.h"
 #include "functions/func_parse_fragment.h"
 #include "functions/func_parse_fragment_impl.h"
+#include "functions/func_parsing_and_serializing.h"
 #include "functions/func_qnames.h"
 #include "functions/func_random.h"
+#include "functions/func_reflection.h"
 #include "functions/func_schema.h"
 #include "functions/func_sctx.h"
 #include "functions/func_sequences.h"
@@ -61,15 +69,8 @@
 #include "functions/func_strings.h"
 #include "functions/func_strings_impl.h"
 #include "functions/func_uris.h"
-#include "functions/func_json.h"
 #include "functions/func_var_decl.h"
 #include "functions/func_xqdoc.h"
-#include "functions/func_documents.h"
-#include "functions/func_maps.h"
-#include "functions/func_eval.h"
-#include "functions/func_reflection.h"
-#include "functions/func_apply.h"
-#include "functions/func_fetch.h"
 #ifndef ZORBA_NO_FULL_TEXT
 #include "functions/func_ft_module.h"
 #include "runtime/full_text/ft_module_impl.h"
@@ -118,6 +119,7 @@
   populate_context_booleans_impl(sctx);
   populate_context_collections(sctx);
   populate_context_context(sctx);
+  populate_context_datetime(sctx);
   populate_context_durations_dates_times(sctx);
   populate_context_durations_dates_times_impl(sctx);
   populate_context_errors_and_diagnostics(sctx);

=== added file 'src/functions/pregenerated/func_datetime.cpp'
--- src/functions/pregenerated/func_datetime.cpp	1970-01-01 00:00:00 +0000
+++ src/functions/pregenerated/func_datetime.cpp	2013-01-02 14:49:24 +0000
@@ -0,0 +1,215 @@
+/*
+ * Copyright 2006-2012 The FLWOR Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ 
+// ******************************************
+// *                                        *
+// * THIS IS A GENERATED FILE. DO NOT EDIT! *
+// * SEE .xml FILE WITH SAME NAME           *
+// *                                        *
+// ******************************************
+
+
+#include "stdafx.h"
+#include "runtime/datetime/datetime.h"
+#include "functions/func_datetime.h"
+
+
+namespace zorba{
+
+
+
+PlanIter_t fn_zorba_dateTime_current_date::codegen(
+  CompilerCB*,
+  static_context* sctx,
+  const QueryLoc& loc,
+  std::vector<PlanIter_t>& argv,
+  expr& ann) const
+{
+  return new CurrentDate(sctx, loc, argv);
+}
+
+PlanIter_t fn_zorba_dateTime_current_dateTime::codegen(
+  CompilerCB*,
+  static_context* sctx,
+  const QueryLoc& loc,
+  std::vector<PlanIter_t>& argv,
+  expr& ann) const
+{
+  return new CurrentDateTime(sctx, loc, argv);
+}
+
+PlanIter_t fn_zorba_dateTime_current_time::codegen(
+  CompilerCB*,
+  static_context* sctx,
+  const QueryLoc& loc,
+  std::vector<PlanIter_t>& argv,
+  expr& ann) const
+{
+  return new CurrentTime(sctx, loc, argv);
+}
+
+PlanIter_t fn_zorba_dateTime_parse_date::codegen(
+  CompilerCB*,
+  static_context* sctx,
+  const QueryLoc& loc,
+  std::vector<PlanIter_t>& argv,
+  expr& ann) const
+{
+  return new ParseDate(sctx, loc, argv);
+}
+
+PlanIter_t fn_zorba_dateTime_parse_dateTime::codegen(
+  CompilerCB*,
+  static_context* sctx,
+  const QueryLoc& loc,
+  std::vector<PlanIter_t>& argv,
+  expr& ann) const
+{
+  return new ParseDateTime(sctx, loc, argv);
+}
+
+PlanIter_t fn_zorba_dateTime_parse_time::codegen(
+  CompilerCB*,
+  static_context* sctx,
+  const QueryLoc& loc,
+  std::vector<PlanIter_t>& argv,
+  expr& ann) const
+{
+  return new ParseTime(sctx, loc, argv);
+}
+
+PlanIter_t fn_zorba_dateTime_timestamp::codegen(
+  CompilerCB*,
+  static_context* sctx,
+  const QueryLoc& loc,
+  std::vector<PlanIter_t>& argv,
+  expr& ann) const
+{
+  return new Timestamp(sctx, loc, argv);
+}
+
+PlanIter_t fn_zorba_dateTime_utc_offset::codegen(
+  CompilerCB*,
+  static_context* sctx,
+  const QueryLoc& loc,
+  std::vector<PlanIter_t>& argv,
+  expr& ann) const
+{
+  return new UTCOffset(sctx, loc, argv);
+}
+
+void populate_context_datetime(static_context* sctx)
+{
+
+
+      {
+    DECL_WITH_KIND(sctx, fn_zorba_dateTime_current_date,
+        (createQName("http://www.zorba-xquery.com/modules/datetime","","current-date";), 
+        GENV_TYPESYSTEM.DATE_TYPE_ONE),
+        FunctionConsts::FN_ZORBA_DATETIME_CURRENT_DATE_0);
+
+  }
+
+
+
+
+      {
+    DECL_WITH_KIND(sctx, fn_zorba_dateTime_current_dateTime,
+        (createQName("http://www.zorba-xquery.com/modules/datetime","","current-dateTime";), 
+        GENV_TYPESYSTEM.DATETIME_TYPE_ONE),
+        FunctionConsts::FN_ZORBA_DATETIME_CURRENT_DATETIME_0);
+
+  }
+
+
+
+
+      {
+    DECL_WITH_KIND(sctx, fn_zorba_dateTime_current_time,
+        (createQName("http://www.zorba-xquery.com/modules/datetime","","current-time";), 
+        GENV_TYPESYSTEM.TIME_TYPE_ONE),
+        FunctionConsts::FN_ZORBA_DATETIME_CURRENT_TIME_0);
+
+  }
+
+
+
+
+      {
+    DECL_WITH_KIND(sctx, fn_zorba_dateTime_parse_date,
+        (createQName("http://www.zorba-xquery.com/modules/datetime","","parse-date";), 
+        GENV_TYPESYSTEM.STRING_TYPE_ONE, 
+        GENV_TYPESYSTEM.STRING_TYPE_ONE, 
+        GENV_TYPESYSTEM.DATE_TYPE_ONE),
+        FunctionConsts::FN_ZORBA_DATETIME_PARSE_DATE_2);
+
+  }
+
+
+
+
+      {
+    DECL_WITH_KIND(sctx, fn_zorba_dateTime_parse_dateTime,
+        (createQName("http://www.zorba-xquery.com/modules/datetime","","parse-dateTime";), 
+        GENV_TYPESYSTEM.STRING_TYPE_ONE, 
+        GENV_TYPESYSTEM.STRING_TYPE_ONE, 
+        GENV_TYPESYSTEM.DATETIME_TYPE_ONE),
+        FunctionConsts::FN_ZORBA_DATETIME_PARSE_DATETIME_2);
+
+  }
+
+
+
+
+      {
+    DECL_WITH_KIND(sctx, fn_zorba_dateTime_parse_time,
+        (createQName("http://www.zorba-xquery.com/modules/datetime","","parse-time";), 
+        GENV_TYPESYSTEM.STRING_TYPE_ONE, 
+        GENV_TYPESYSTEM.STRING_TYPE_ONE, 
+        GENV_TYPESYSTEM.TIME_TYPE_ONE),
+        FunctionConsts::FN_ZORBA_DATETIME_PARSE_TIME_2);
+
+  }
+
+
+
+
+      {
+    DECL_WITH_KIND(sctx, fn_zorba_dateTime_timestamp,
+        (createQName("http://www.zorba-xquery.com/modules/datetime","","timestamp";), 
+        GENV_TYPESYSTEM.LONG_TYPE_ONE),
+        FunctionConsts::FN_ZORBA_DATETIME_TIMESTAMP_0);
+
+  }
+
+
+
+
+      {
+    DECL_WITH_KIND(sctx, fn_zorba_dateTime_utc_offset,
+        (createQName("http://www.zorba-xquery.com/modules/datetime","","utc-offset";), 
+        GENV_TYPESYSTEM.LONG_TYPE_ONE),
+        FunctionConsts::FN_ZORBA_DATETIME_UTC_OFFSET_0);
+
+  }
+
+}
+
+
+}
+
+
+

=== added file 'src/functions/pregenerated/func_datetime.h'
--- src/functions/pregenerated/func_datetime.h	1970-01-01 00:00:00 +0000
+++ src/functions/pregenerated/func_datetime.h	2013-01-02 14:49:24 +0000
@@ -0,0 +1,169 @@
+/*
+ * Copyright 2006-2012 The FLWOR Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ 
+// ******************************************
+// *                                        *
+// * THIS IS A GENERATED FILE. DO NOT EDIT! *
+// * SEE .xml FILE WITH SAME NAME           *
+// *                                        *
+// ******************************************
+
+
+#ifndef ZORBA_FUNCTIONS_DATETIME_H
+#define ZORBA_FUNCTIONS_DATETIME_H
+
+
+#include "common/shared_types.h"
+#include "functions/function_impl.h"
+
+
+namespace zorba {
+
+
+void populate_context_datetime(static_context* sctx);
+
+
+
+
+//fn-zorba-dateTime:current-date
+class fn_zorba_dateTime_current_date : public function
+{
+public:
+  fn_zorba_dateTime_current_date(const signature& sig, FunctionConsts::FunctionKind kind)
+    : 
+    function(sig, kind)
+  {
+
+  }
+
+  CODEGEN_DECL();
+};
+
+
+//fn-zorba-dateTime:current-dateTime
+class fn_zorba_dateTime_current_dateTime : public function
+{
+public:
+  fn_zorba_dateTime_current_dateTime(const signature& sig, FunctionConsts::FunctionKind kind)
+    : 
+    function(sig, kind)
+  {
+
+  }
+
+  CODEGEN_DECL();
+};
+
+
+//fn-zorba-dateTime:current-time
+class fn_zorba_dateTime_current_time : public function
+{
+public:
+  fn_zorba_dateTime_current_time(const signature& sig, FunctionConsts::FunctionKind kind)
+    : 
+    function(sig, kind)
+  {
+
+  }
+
+  CODEGEN_DECL();
+};
+
+
+//fn-zorba-dateTime:parse-date
+class fn_zorba_dateTime_parse_date : public function
+{
+public:
+  fn_zorba_dateTime_parse_date(const signature& sig, FunctionConsts::FunctionKind kind)
+    : 
+    function(sig, kind)
+  {
+
+  }
+
+  CODEGEN_DECL();
+};
+
+
+//fn-zorba-dateTime:parse-dateTime
+class fn_zorba_dateTime_parse_dateTime : public function
+{
+public:
+  fn_zorba_dateTime_parse_dateTime(const signature& sig, FunctionConsts::FunctionKind kind)
+    : 
+    function(sig, kind)
+  {
+
+  }
+
+  CODEGEN_DECL();
+};
+
+
+//fn-zorba-dateTime:parse-time
+class fn_zorba_dateTime_parse_time : public function
+{
+public:
+  fn_zorba_dateTime_parse_time(const signature& sig, FunctionConsts::FunctionKind kind)
+    : 
+    function(sig, kind)
+  {
+
+  }
+
+  CODEGEN_DECL();
+};
+
+
+//fn-zorba-dateTime:timestamp
+class fn_zorba_dateTime_timestamp : public function
+{
+public:
+  fn_zorba_dateTime_timestamp(const signature& sig, FunctionConsts::FunctionKind kind)
+    : 
+    function(sig, kind)
+  {
+
+  }
+
+  CODEGEN_DECL();
+};
+
+
+//fn-zorba-dateTime:utc-offset
+class fn_zorba_dateTime_utc_offset : public function
+{
+public:
+  fn_zorba_dateTime_utc_offset(const signature& sig, FunctionConsts::FunctionKind kind)
+    : 
+    function(sig, kind)
+  {
+
+  }
+
+  CODEGEN_DECL();
+};
+
+
+} //namespace zorba
+
+
+#endif
+/*
+ * Local variables:
+ * mode: c++
+ * End:
+ */ 

=== modified file 'src/functions/pregenerated/function_enum.h'
--- src/functions/pregenerated/function_enum.h	2012-12-10 16:02:05 +0000
+++ src/functions/pregenerated/function_enum.h	2013-01-02 14:49:24 +0000
@@ -143,6 +143,14 @@
   FN_POSITION_0,
   FN_LAST_0,
   FN_STATIC_BASE_URI_0,
+  FN_ZORBA_DATETIME_CURRENT_DATE_0,
+  FN_ZORBA_DATETIME_CURRENT_DATETIME_0,
+  FN_ZORBA_DATETIME_CURRENT_TIME_0,
+  FN_ZORBA_DATETIME_PARSE_DATE_2,
+  FN_ZORBA_DATETIME_PARSE_DATETIME_2,
+  FN_ZORBA_DATETIME_PARSE_TIME_2,
+  FN_ZORBA_DATETIME_TIMESTAMP_0,
+  FN_ZORBA_DATETIME_UTC_OFFSET_0,
   FN_YEARS_FROM_DURATION_1,
   FN_MONTHS_FROM_DURATION_1,
   FN_DAYS_FROM_DURATION_1,

=== added directory 'src/runtime/datetime'
=== added file 'src/runtime/datetime/datetime_impl.cpp'
--- src/runtime/datetime/datetime_impl.cpp	1970-01-01 00:00:00 +0000
+++ src/runtime/datetime/datetime_impl.cpp	2013-01-02 14:49:24 +0000
@@ -0,0 +1,303 @@
+/*
+ * Copyright 2006-2011 The FLWOR Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "stdafx.h"
+
+#include <cstring>
+
+#include <zorba/diagnostic_list.h>
+
+#include "diagnostics/xquery_exception.h"
+#include "runtime/datetime/datetime.h"
+#include "store/api/item_factory.h"
+#include "system/globalenv.h"
+#include "util/ascii_util.h"
+#include "util/strptime.h"
+#include "util/time_util.h"
+
+using namespace std;
+
+namespace zorba {
+
+enum parse_type {
+  parse_date,
+  parse_time,
+  parse_dateTime
+};
+
+///////////////////////////////////////////////////////////////////////////////
+
+static void strptime( zstring const &buf, zstring const &fmt,
+                      parse_type parse_what, time::ztm *tm,
+                      QueryLoc const &loc ) {
+  try {
+    unsigned set_fields;
+    ::memset( tm, 0, sizeof( *tm ) );
+    time::strptime( buf, fmt, tm, &set_fields );
+
+    bool       set_mday = set_fields & time::set_mday;
+    bool       set_mon  = set_fields & time::set_mon;
+    bool const set_yday = set_fields & time::set_yday;
+    bool const set_year = set_fields & time::set_year;
+
+    if ( set_yday && set_year && (!set_mday || !set_mon) ) {
+      //
+      // Given yday and year, "back fill" mday and/or mon.
+      //
+      time::calc_mday_mon(
+        tm->tm_yday, 
+        set_mday ? nullptr : reinterpret_cast<unsigned*>( &tm->tm_mday ),
+        set_mon  ? nullptr : reinterpret_cast<unsigned*>( &tm->tm_mon ),
+        tm->tm_year
+      );
+      set_mday = set_mon = true;
+    }
+
+    switch ( parse_what ) {
+      case parse_date:
+        if ( set_mday && set_mon && set_year )
+          return;
+        break;
+      case parse_dateTime:
+        if ( !(set_mday && set_mon && set_year) )
+          break;
+        // no break;
+      case parse_time:
+        if ( !(set_fields & time::set_hour) )
+          break;
+        if ( !(set_fields & time::set_min) )
+          tm->tm_min = 0;
+        if ( !(set_fields & time::set_sec) )
+          tm->tm_sec = 0;
+        if ( !(set_fields & time::set_gmtoff) )
+          tm->ZTM_GMTOFF = 0;
+        return;
+    }
+
+    throw XQUERY_EXCEPTION(
+      zerr::ZDTP0005_INCOMPLETE_DATE_OR_TIME,
+      ERROR_PARAMS( fmt ),
+      ERROR_LOC( loc )
+    );
+  }
+  catch ( time::insufficient_buffer const& ) {
+    throw XQUERY_EXCEPTION(
+      zerr::ZDTP0002_INSUFFICIENT_BUFFER,
+      ERROR_PARAMS( buf, fmt ),
+      ERROR_LOC( loc )
+    );
+  }
+  catch ( time::invalid_specification const &e ) {
+    throw XQUERY_EXCEPTION(
+      zerr::ZDTP0001_INVALID_SPECIFICATION,
+      ERROR_PARAMS( ascii::printable_char( e.get_spec() ) ),
+      ERROR_LOC( loc )
+    );
+  }
+  catch ( time::invalid_value const &e ) {
+    throw XQUERY_EXCEPTION(
+      zerr::ZDTP0003_INVALID_VALUE,
+      ERROR_PARAMS( e.get_value(), e.get_specs() ),
+      ERROR_LOC( loc )
+    );
+  }
+  catch ( time::literal_mismatch const &e ) {
+    throw XQUERY_EXCEPTION(
+      zerr::ZDTP0004_LITERAL_MISMATCH,
+      ERROR_PARAMS(
+        ascii::printable_char( e.get_got() ),
+        ascii::printable_char( e.get_expected() )
+      ),
+      ERROR_LOC( loc )
+    );
+  }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+bool CurrentDate::nextImpl( store::Item_t& result,
+                            PlanState &plan_state ) const {
+  time::ztm tm;
+  time::get_gmtime( &tm );
+
+  PlanIteratorState *state;
+  DEFAULT_STACK_INIT( PlanIteratorState, state, plan_state );
+
+  GENV_ITEMFACTORY->createDate(
+    result,
+    static_cast<short>( tm.tm_year + TM_YEAR_BASE ),
+    static_cast<short>( tm.tm_mon + 1 ),
+    static_cast<short>( tm.tm_mday )
+  );
+
+  STACK_PUSH( true, state );
+  STACK_END( state );
+}
+
+bool CurrentDateTime::nextImpl( store::Item_t& result,
+                                PlanState &plan_state ) const {
+  time_t sec;
+  time::usec_type usec;
+  time::get_epoch( &sec, &usec );
+  time::ztm tm;
+  time::get_gmtime( &tm, sec );
+
+  PlanIteratorState *state;
+  DEFAULT_STACK_INIT( PlanIteratorState, state, plan_state );
+
+  GENV_ITEMFACTORY->createDateTime(
+    result,
+    static_cast<short>( tm.tm_year + TM_YEAR_BASE ),
+    static_cast<short>( tm.tm_mon + 1 ),
+    static_cast<short>( tm.tm_mday ),
+    static_cast<short>( tm.tm_hour ),
+    static_cast<short>( tm.tm_min ),
+    tm.tm_sec + usec / 1000000.0,
+    static_cast<short>( tm.ZTM_GMTOFF / 3600 )
+  );
+
+  STACK_PUSH( true, state );
+  STACK_END( state );
+}
+
+bool CurrentTime::nextImpl( store::Item_t& result,
+                            PlanState &plan_state ) const {
+  time_t sec;
+  time::usec_type usec;
+  time::get_epoch( &sec, &usec );
+  time::ztm tm;
+  time::get_gmtime( &tm, sec );
+
+  PlanIteratorState *state;
+  DEFAULT_STACK_INIT( PlanIteratorState, state, plan_state );
+
+  GENV_ITEMFACTORY->createTime(
+    result,
+    static_cast<short>( tm.tm_hour ),
+    static_cast<short>( tm.tm_min ),
+    tm.tm_sec + usec / 1000000.0,
+    static_cast<short>( tm.ZTM_GMTOFF / 3600 )
+  );
+
+  STACK_PUSH( true, state );
+  STACK_END( state );
+}
+
+bool ParseDate::nextImpl( store::Item_t& result, PlanState &plan_state ) const {
+  store::Item_t item;
+  time::ztm tm;
+  zstring buf, fmt;
+
+  PlanIteratorState *state;
+  DEFAULT_STACK_INIT( PlanIteratorState, state, plan_state );
+
+  consumeNext( item, theChildren[0], plan_state );
+  item->getStringValue2( buf );
+  consumeNext( item, theChildren[1], plan_state );
+  item->getStringValue2( fmt );
+
+  strptime( buf, fmt, parse_date, &tm, loc );
+  GENV_ITEMFACTORY->createDate(
+    result,
+    static_cast<short>( tm.tm_year + TM_YEAR_BASE ),
+    static_cast<short>( tm.tm_mon + 1 ),
+    static_cast<short>( tm.tm_mday )
+  );
+
+  STACK_PUSH( true, state );
+  STACK_END( state );
+}
+
+bool ParseDateTime::nextImpl( store::Item_t& result,
+                              PlanState &plan_state ) const {
+  store::Item_t item;
+  zstring buf, fmt;
+  time::ztm tm;
+
+  PlanIteratorState *state;
+  DEFAULT_STACK_INIT( PlanIteratorState, state, plan_state );
+
+  consumeNext( item, theChildren[0], plan_state );
+  item->getStringValue2( buf );
+  consumeNext( item, theChildren[1], plan_state );
+  item->getStringValue2( fmt );
+
+  strptime( buf, fmt, parse_dateTime, &tm, loc );
+  GENV_ITEMFACTORY->createDateTime(
+    result,
+    static_cast<short>( tm.tm_year + TM_YEAR_BASE ),
+    static_cast<short>( tm.tm_mon + 1 ),
+    static_cast<short>( tm.tm_mday ),
+    static_cast<short>( tm.tm_hour ),
+    static_cast<short>( tm.tm_min ),
+    tm.tm_sec,
+    static_cast<short>( tm.ZTM_GMTOFF / 3600 )
+  );
+
+  STACK_PUSH( true, state );
+  STACK_END( state );
+}
+
+bool ParseTime::nextImpl( store::Item_t& result, PlanState &plan_state ) const {
+  store::Item_t item;
+  time::ztm tm;
+  zstring buf, fmt;
+
+  PlanIteratorState *state;
+  DEFAULT_STACK_INIT( PlanIteratorState, state, plan_state );
+
+  consumeNext( item, theChildren[0], plan_state );
+  item->getStringValue2( buf );
+  consumeNext( item, theChildren[1], plan_state );
+  item->getStringValue2( fmt );
+
+  strptime( buf, fmt, parse_time, &tm, loc );
+  GENV_ITEMFACTORY->createTime(
+    result,
+    static_cast<short>( tm.tm_hour ),
+    static_cast<short>( tm.tm_min ),
+    tm.tm_sec,
+    static_cast<short>( tm.ZTM_GMTOFF / 3600 )
+  );
+
+  STACK_PUSH( true, state );
+  STACK_END( state );
+}
+
+bool Timestamp::nextImpl( store::Item_t& result,
+                          PlanState &plan_state ) const {
+  time_t sec;
+  time::get_epoch( &sec );
+
+  PlanIteratorState *state;
+  DEFAULT_STACK_INIT( PlanIteratorState, state, plan_state );
+  GENV_ITEMFACTORY->createLong( result, sec );
+  STACK_PUSH( true, state );
+  STACK_END( state );
+}
+
+bool UTCOffset::nextImpl( store::Item_t& result,
+                          PlanState &plan_state ) const {
+  PlanIteratorState *state;
+  DEFAULT_STACK_INIT( PlanIteratorState, state, plan_state );
+  GENV_ITEMFACTORY->createLong( result, time::get_gmt_offset() );
+  STACK_PUSH( true, state );
+  STACK_END( state );
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+} // namespace zorba
+/* vim:set et sw=2 ts=2: */

=== added directory 'src/runtime/datetime/pregenerated'
=== added file 'src/runtime/datetime/pregenerated/datetime.cpp'
--- src/runtime/datetime/pregenerated/datetime.cpp	1970-01-01 00:00:00 +0000
+++ src/runtime/datetime/pregenerated/datetime.cpp	2013-01-02 14:49:24 +0000
@@ -0,0 +1,262 @@
+/*
+ * Copyright 2006-2012 The FLWOR Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ 
+// ******************************************
+// *                                        *
+// * THIS IS A GENERATED FILE. DO NOT EDIT! *
+// * SEE .xml FILE WITH SAME NAME           *
+// *                                        *
+// ******************************************
+
+#include "stdafx.h"
+#include "zorbatypes/rchandle.h"
+#include "zorbatypes/zstring.h"
+#include "runtime/visitors/planiter_visitor.h"
+#include "runtime/datetime/datetime.h"
+#include "system/globalenv.h"
+
+
+
+namespace zorba {
+
+// <CurrentDate>
+SERIALIZABLE_CLASS_VERSIONS(CurrentDate)
+
+void CurrentDate::serialize(::zorba::serialization::Archiver& ar)
+{
+  serialize_baseclass(ar,
+  (NaryBaseIterator<CurrentDate, PlanIteratorState>*)this);
+}
+
+
+void CurrentDate::accept(PlanIterVisitor& v) const
+{
+  v.beginVisit(*this);
+
+  std::vector<PlanIter_t>::const_iterator lIter = theChildren.begin();
+  std::vector<PlanIter_t>::const_iterator lEnd = theChildren.end();
+  for ( ; lIter != lEnd; ++lIter ){
+    (*lIter)->accept(v);
+  }
+
+  v.endVisit(*this);
+}
+
+CurrentDate::~CurrentDate() {}
+
+// </CurrentDate>
+
+
+// <CurrentDateTime>
+SERIALIZABLE_CLASS_VERSIONS(CurrentDateTime)
+
+void CurrentDateTime::serialize(::zorba::serialization::Archiver& ar)
+{
+  serialize_baseclass(ar,
+  (NaryBaseIterator<CurrentDateTime, PlanIteratorState>*)this);
+}
+
+
+void CurrentDateTime::accept(PlanIterVisitor& v) const
+{
+  v.beginVisit(*this);
+
+  std::vector<PlanIter_t>::const_iterator lIter = theChildren.begin();
+  std::vector<PlanIter_t>::const_iterator lEnd = theChildren.end();
+  for ( ; lIter != lEnd; ++lIter ){
+    (*lIter)->accept(v);
+  }
+
+  v.endVisit(*this);
+}
+
+CurrentDateTime::~CurrentDateTime() {}
+
+// </CurrentDateTime>
+
+
+// <CurrentTime>
+SERIALIZABLE_CLASS_VERSIONS(CurrentTime)
+
+void CurrentTime::serialize(::zorba::serialization::Archiver& ar)
+{
+  serialize_baseclass(ar,
+  (NaryBaseIterator<CurrentTime, PlanIteratorState>*)this);
+}
+
+
+void CurrentTime::accept(PlanIterVisitor& v) const
+{
+  v.beginVisit(*this);
+
+  std::vector<PlanIter_t>::const_iterator lIter = theChildren.begin();
+  std::vector<PlanIter_t>::const_iterator lEnd = theChildren.end();
+  for ( ; lIter != lEnd; ++lIter ){
+    (*lIter)->accept(v);
+  }
+
+  v.endVisit(*this);
+}
+
+CurrentTime::~CurrentTime() {}
+
+// </CurrentTime>
+
+
+// <ParseDate>
+SERIALIZABLE_CLASS_VERSIONS(ParseDate)
+
+void ParseDate::serialize(::zorba::serialization::Archiver& ar)
+{
+  serialize_baseclass(ar,
+  (NaryBaseIterator<ParseDate, PlanIteratorState>*)this);
+}
+
+
+void ParseDate::accept(PlanIterVisitor& v) const
+{
+  v.beginVisit(*this);
+
+  std::vector<PlanIter_t>::const_iterator lIter = theChildren.begin();
+  std::vector<PlanIter_t>::const_iterator lEnd = theChildren.end();
+  for ( ; lIter != lEnd; ++lIter ){
+    (*lIter)->accept(v);
+  }
+
+  v.endVisit(*this);
+}
+
+ParseDate::~ParseDate() {}
+
+// </ParseDate>
+
+
+// <ParseDateTime>
+SERIALIZABLE_CLASS_VERSIONS(ParseDateTime)
+
+void ParseDateTime::serialize(::zorba::serialization::Archiver& ar)
+{
+  serialize_baseclass(ar,
+  (NaryBaseIterator<ParseDateTime, PlanIteratorState>*)this);
+}
+
+
+void ParseDateTime::accept(PlanIterVisitor& v) const
+{
+  v.beginVisit(*this);
+
+  std::vector<PlanIter_t>::const_iterator lIter = theChildren.begin();
+  std::vector<PlanIter_t>::const_iterator lEnd = theChildren.end();
+  for ( ; lIter != lEnd; ++lIter ){
+    (*lIter)->accept(v);
+  }
+
+  v.endVisit(*this);
+}
+
+ParseDateTime::~ParseDateTime() {}
+
+// </ParseDateTime>
+
+
+// <ParseTime>
+SERIALIZABLE_CLASS_VERSIONS(ParseTime)
+
+void ParseTime::serialize(::zorba::serialization::Archiver& ar)
+{
+  serialize_baseclass(ar,
+  (NaryBaseIterator<ParseTime, PlanIteratorState>*)this);
+}
+
+
+void ParseTime::accept(PlanIterVisitor& v) const
+{
+  v.beginVisit(*this);
+
+  std::vector<PlanIter_t>::const_iterator lIter = theChildren.begin();
+  std::vector<PlanIter_t>::const_iterator lEnd = theChildren.end();
+  for ( ; lIter != lEnd; ++lIter ){
+    (*lIter)->accept(v);
+  }
+
+  v.endVisit(*this);
+}
+
+ParseTime::~ParseTime() {}
+
+// </ParseTime>
+
+
+// <Timestamp>
+SERIALIZABLE_CLASS_VERSIONS(Timestamp)
+
+void Timestamp::serialize(::zorba::serialization::Archiver& ar)
+{
+  serialize_baseclass(ar,
+  (NaryBaseIterator<Timestamp, PlanIteratorState>*)this);
+}
+
+
+void Timestamp::accept(PlanIterVisitor& v) const
+{
+  v.beginVisit(*this);
+
+  std::vector<PlanIter_t>::const_iterator lIter = theChildren.begin();
+  std::vector<PlanIter_t>::const_iterator lEnd = theChildren.end();
+  for ( ; lIter != lEnd; ++lIter ){
+    (*lIter)->accept(v);
+  }
+
+  v.endVisit(*this);
+}
+
+Timestamp::~Timestamp() {}
+
+// </Timestamp>
+
+
+// <UTCOffset>
+SERIALIZABLE_CLASS_VERSIONS(UTCOffset)
+
+void UTCOffset::serialize(::zorba::serialization::Archiver& ar)
+{
+  serialize_baseclass(ar,
+  (NaryBaseIterator<UTCOffset, PlanIteratorState>*)this);
+}
+
+
+void UTCOffset::accept(PlanIterVisitor& v) const
+{
+  v.beginVisit(*this);
+
+  std::vector<PlanIter_t>::const_iterator lIter = theChildren.begin();
+  std::vector<PlanIter_t>::const_iterator lEnd = theChildren.end();
+  for ( ; lIter != lEnd; ++lIter ){
+    (*lIter)->accept(v);
+  }
+
+  v.endVisit(*this);
+}
+
+UTCOffset::~UTCOffset() {}
+
+// </UTCOffset>
+
+
+
+}
+
+

=== added file 'src/runtime/datetime/pregenerated/datetime.h'
--- src/runtime/datetime/pregenerated/datetime.h	1970-01-01 00:00:00 +0000
+++ src/runtime/datetime/pregenerated/datetime.h	2013-01-02 14:49:24 +0000
@@ -0,0 +1,299 @@
+/*
+ * Copyright 2006-2012 The FLWOR Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ 
+// ******************************************
+// *                                        *
+// * THIS IS A GENERATED FILE. DO NOT EDIT! *
+// * SEE .xml FILE WITH SAME NAME           *
+// *                                        *
+// ******************************************
+#ifndef ZORBA_RUNTIME_DATETIME_DATETIME_H
+#define ZORBA_RUNTIME_DATETIME_DATETIME_H
+
+
+#include "common/shared_types.h"
+
+
+
+#include "runtime/base/narybase.h"
+#include "runtime/base/narybase.h"
+
+
+namespace zorba {
+
+/**
+ * 
+ *    function for getting the current date
+ *  
+ * Author: Zorba Team
+ */
+class CurrentDate : public NaryBaseIterator<CurrentDate, PlanIteratorState>
+{ 
+public:
+  SERIALIZABLE_CLASS(CurrentDate);
+
+  SERIALIZABLE_CLASS_CONSTRUCTOR2T(CurrentDate,
+    NaryBaseIterator<CurrentDate, PlanIteratorState>);
+
+  void serialize( ::zorba::serialization::Archiver& ar);
+
+  CurrentDate(
+    static_context* sctx,
+    const QueryLoc& loc,
+    std::vector<PlanIter_t>& children)
+    : 
+    NaryBaseIterator<CurrentDate, PlanIteratorState>(sctx, loc, children)
+  {}
+
+  virtual ~CurrentDate();
+
+  void accept(PlanIterVisitor& v) const;
+
+  bool nextImpl(store::Item_t& result, PlanState& aPlanState) const;
+};
+
+
+/**
+ * 
+ *    function for getting the current date and time
+ *  
+ * Author: Zorba Team
+ */
+class CurrentDateTime : public NaryBaseIterator<CurrentDateTime, PlanIteratorState>
+{ 
+public:
+  SERIALIZABLE_CLASS(CurrentDateTime);
+
+  SERIALIZABLE_CLASS_CONSTRUCTOR2T(CurrentDateTime,
+    NaryBaseIterator<CurrentDateTime, PlanIteratorState>);
+
+  void serialize( ::zorba::serialization::Archiver& ar);
+
+  CurrentDateTime(
+    static_context* sctx,
+    const QueryLoc& loc,
+    std::vector<PlanIter_t>& children)
+    : 
+    NaryBaseIterator<CurrentDateTime, PlanIteratorState>(sctx, loc, children)
+  {}
+
+  virtual ~CurrentDateTime();
+
+  void accept(PlanIterVisitor& v) const;
+
+  bool nextImpl(store::Item_t& result, PlanState& aPlanState) const;
+};
+
+
+/**
+ * 
+ *    function for getting the current time
+ *  
+ * Author: Zorba Team
+ */
+class CurrentTime : public NaryBaseIterator<CurrentTime, PlanIteratorState>
+{ 
+public:
+  SERIALIZABLE_CLASS(CurrentTime);
+
+  SERIALIZABLE_CLASS_CONSTRUCTOR2T(CurrentTime,
+    NaryBaseIterator<CurrentTime, PlanIteratorState>);
+
+  void serialize( ::zorba::serialization::Archiver& ar);
+
+  CurrentTime(
+    static_context* sctx,
+    const QueryLoc& loc,
+    std::vector<PlanIter_t>& children)
+    : 
+    NaryBaseIterator<CurrentTime, PlanIteratorState>(sctx, loc, children)
+  {}
+
+  virtual ~CurrentTime();
+
+  void accept(PlanIterVisitor& v) const;
+
+  bool nextImpl(store::Item_t& result, PlanState& aPlanState) const;
+};
+
+
+/**
+ * 
+ *    function for parsing strings into a date
+ *  
+ * Author: Zorba Team
+ */
+class ParseDate : public NaryBaseIterator<ParseDate, PlanIteratorState>
+{ 
+public:
+  SERIALIZABLE_CLASS(ParseDate);
+
+  SERIALIZABLE_CLASS_CONSTRUCTOR2T(ParseDate,
+    NaryBaseIterator<ParseDate, PlanIteratorState>);
+
+  void serialize( ::zorba::serialization::Archiver& ar);
+
+  ParseDate(
+    static_context* sctx,
+    const QueryLoc& loc,
+    std::vector<PlanIter_t>& children)
+    : 
+    NaryBaseIterator<ParseDate, PlanIteratorState>(sctx, loc, children)
+  {}
+
+  virtual ~ParseDate();
+
+  void accept(PlanIterVisitor& v) const;
+
+  bool nextImpl(store::Item_t& result, PlanState& aPlanState) const;
+};
+
+
+/**
+ * 
+ *    function for parsing strings into a dateTime
+ *  
+ * Author: Zorba Team
+ */
+class ParseDateTime : public NaryBaseIterator<ParseDateTime, PlanIteratorState>
+{ 
+public:
+  SERIALIZABLE_CLASS(ParseDateTime);
+
+  SERIALIZABLE_CLASS_CONSTRUCTOR2T(ParseDateTime,
+    NaryBaseIterator<ParseDateTime, PlanIteratorState>);
+
+  void serialize( ::zorba::serialization::Archiver& ar);
+
+  ParseDateTime(
+    static_context* sctx,
+    const QueryLoc& loc,
+    std::vector<PlanIter_t>& children)
+    : 
+    NaryBaseIterator<ParseDateTime, PlanIteratorState>(sctx, loc, children)
+  {}
+
+  virtual ~ParseDateTime();
+
+  void accept(PlanIterVisitor& v) const;
+
+  bool nextImpl(store::Item_t& result, PlanState& aPlanState) const;
+};
+
+
+/**
+ * 
+ *    function for parsing strings into a time
+ *  
+ * Author: Zorba Team
+ */
+class ParseTime : public NaryBaseIterator<ParseTime, PlanIteratorState>
+{ 
+public:
+  SERIALIZABLE_CLASS(ParseTime);
+
+  SERIALIZABLE_CLASS_CONSTRUCTOR2T(ParseTime,
+    NaryBaseIterator<ParseTime, PlanIteratorState>);
+
+  void serialize( ::zorba::serialization::Archiver& ar);
+
+  ParseTime(
+    static_context* sctx,
+    const QueryLoc& loc,
+    std::vector<PlanIter_t>& children)
+    : 
+    NaryBaseIterator<ParseTime, PlanIteratorState>(sctx, loc, children)
+  {}
+
+  virtual ~ParseTime();
+
+  void accept(PlanIterVisitor& v) const;
+
+  bool nextImpl(store::Item_t& result, PlanState& aPlanState) const;
+};
+
+
+/**
+ * 
+ *    function for getting the current number of seconds since epoch
+ *  
+ * Author: Zorba Team
+ */
+class Timestamp : public NaryBaseIterator<Timestamp, PlanIteratorState>
+{ 
+public:
+  SERIALIZABLE_CLASS(Timestamp);
+
+  SERIALIZABLE_CLASS_CONSTRUCTOR2T(Timestamp,
+    NaryBaseIterator<Timestamp, PlanIteratorState>);
+
+  void serialize( ::zorba::serialization::Archiver& ar);
+
+  Timestamp(
+    static_context* sctx,
+    const QueryLoc& loc,
+    std::vector<PlanIter_t>& children)
+    : 
+    NaryBaseIterator<Timestamp, PlanIteratorState>(sctx, loc, children)
+  {}
+
+  virtual ~Timestamp();
+
+  void accept(PlanIterVisitor& v) const;
+
+  bool nextImpl(store::Item_t& result, PlanState& aPlanState) const;
+};
+
+
+/**
+ * 
+ *    function for getting the current offset from UTC
+ *  
+ * Author: Zorba Team
+ */
+class UTCOffset : public NaryBaseIterator<UTCOffset, PlanIteratorState>
+{ 
+public:
+  SERIALIZABLE_CLASS(UTCOffset);
+
+  SERIALIZABLE_CLASS_CONSTRUCTOR2T(UTCOffset,
+    NaryBaseIterator<UTCOffset, PlanIteratorState>);
+
+  void serialize( ::zorba::serialization::Archiver& ar);
+
+  UTCOffset(
+    static_context* sctx,
+    const QueryLoc& loc,
+    std::vector<PlanIter_t>& children)
+    : 
+    NaryBaseIterator<UTCOffset, PlanIteratorState>(sctx, loc, children)
+  {}
+
+  virtual ~UTCOffset();
+
+  void accept(PlanIterVisitor& v) const;
+
+  bool nextImpl(store::Item_t& result, PlanState& aPlanState) const;
+};
+
+
+}
+#endif
+/*
+ * Local variables:
+ * mode: c++
+ * End:
+ */ 

=== modified file 'src/runtime/pregenerated/iterator_enum.h'
--- src/runtime/pregenerated/iterator_enum.h	2012-12-10 16:02:05 +0000
+++ src/runtime/pregenerated/iterator_enum.h	2013-01-02 14:49:24 +0000
@@ -72,6 +72,14 @@
   TYPE_CurrentTimeIterator,
   TYPE_ImplicitTimezoneIterator,
   TYPE_DefaultCollationIterator,
+  TYPE_CurrentDate,
+  TYPE_CurrentDateTime,
+  TYPE_CurrentTime,
+  TYPE_ParseDate,
+  TYPE_ParseDateTime,
+  TYPE_ParseTime,
+  TYPE_Timestamp,
+  TYPE_UTCOffset,
   TYPE_DebugIterator,
   TYPE_YearsFromDurationIterator,
   TYPE_MonthsFromDurationIterator,

=== added directory 'src/runtime/spec/datetime'
=== added file 'src/runtime/spec/datetime/datetime.xml'
--- src/runtime/spec/datetime/datetime.xml	1970-01-01 00:00:00 +0000
+++ src/runtime/spec/datetime/datetime.xml	2013-01-02 14:49:24 +0000
@@ -0,0 +1,112 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<zorba:iterators
+  xmlns:zorba="http://www.zorba-xquery.com";
+  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
+  xsi:schemaLocation="http://www.zorba-xquery.com ../runtime.xsd">
+
+<!-- ////////////////////////////////////////////////////////////////////// -->
+
+<zorba:header>
+  <zorba:include form="Quoted">runtime/base/narybase.h</zorba:include>
+</zorba:header>
+
+<zorba:iterator name="CurrentDate">
+  <zorba:description author="Zorba Team">
+    function for getting the current date
+  </zorba:description>
+  <zorba:function>
+    <zorba:signature localname="current-date" prefix="fn-zorba-dateTime">
+      <zorba:output>xs:date</zorba:output>
+    </zorba:signature>
+  </zorba:function>
+</zorba:iterator>
+
+<zorba:iterator name="CurrentDateTime">
+  <zorba:description author="Zorba Team">
+    function for getting the current date and time
+  </zorba:description>
+  <zorba:function>
+    <zorba:signature localname="current-dateTime" prefix="fn-zorba-dateTime">
+      <zorba:output>xs:dateTime</zorba:output>
+    </zorba:signature>
+  </zorba:function>
+</zorba:iterator>
+
+<zorba:iterator name="CurrentTime">
+  <zorba:description author="Zorba Team">
+    function for getting the current time
+  </zorba:description>
+  <zorba:function>
+    <zorba:signature localname="current-time" prefix="fn-zorba-dateTime">
+      <zorba:output>xs:time</zorba:output>
+    </zorba:signature>
+  </zorba:function>
+</zorba:iterator>
+
+<zorba:iterator name="ParseDate">
+  <zorba:description author="Zorba Team">
+    function for parsing strings into a date
+  </zorba:description>
+  <zorba:function>
+    <zorba:signature localname="parse-date" prefix="fn-zorba-dateTime">
+      <zorba:param>xs:string</zorba:param>
+      <zorba:param>xs:string</zorba:param>
+      <zorba:output>xs:date</zorba:output>
+    </zorba:signature>
+  </zorba:function>
+</zorba:iterator>
+
+<zorba:iterator name="ParseDateTime">
+  <zorba:description author="Zorba Team">
+    function for parsing strings into a dateTime
+  </zorba:description>
+  <zorba:function>
+    <zorba:signature localname="parse-dateTime" prefix="fn-zorba-dateTime">
+      <zorba:param>xs:string</zorba:param>
+      <zorba:param>xs:string</zorba:param>
+      <zorba:output>xs:dateTime</zorba:output>
+    </zorba:signature>
+  </zorba:function>
+</zorba:iterator>
+
+<zorba:iterator name="ParseTime">
+  <zorba:description author="Zorba Team">
+    function for parsing strings into a time
+  </zorba:description>
+  <zorba:function>
+    <zorba:signature localname="parse-time" prefix="fn-zorba-dateTime">
+      <zorba:param>xs:string</zorba:param>
+      <zorba:param>xs:string</zorba:param>
+      <zorba:output>xs:time</zorba:output>
+    </zorba:signature>
+  </zorba:function>
+</zorba:iterator>
+
+<zorba:iterator name="Timestamp">
+  <zorba:description author="Zorba Team">
+    function for getting the current number of seconds since epoch
+  </zorba:description>
+  <zorba:function>
+    <zorba:signature localname="timestamp" prefix="fn-zorba-dateTime">
+      <zorba:output>xs:long</zorba:output>
+    </zorba:signature>
+  </zorba:function>
+</zorba:iterator>
+
+<zorba:iterator name="UTCOffset">
+  <zorba:description author="Zorba Team">
+    function for getting the current offset from UTC
+  </zorba:description>
+  <zorba:function>
+    <zorba:signature localname="utc-offset" prefix="fn-zorba-dateTime">
+      <zorba:output>xs:long</zorba:output>
+    </zorba:signature>
+  </zorba:function>
+</zorba:iterator>
+
+<!-- ////////////////////////////////////////////////////////////////////// -->
+
+</zorba:iterators>
+
+<!-- vim:set et sw=2 ts=2: -->

=== modified file 'src/runtime/spec/mappings.xml'
--- src/runtime/spec/mappings.xml	2012-10-08 12:09:36 +0000
+++ src/runtime/spec/mappings.xml	2013-01-02 14:49:24 +0000
@@ -81,6 +81,11 @@
       define="ZORBA_FULL_TEXT_FN_NS"
       prefix="full-text"/>
 
+    <zorba:namespace
+      uri="http://www.zorba-xquery.com/modules/datetime";
+      define="ZORBA_DATETIME_FN_NS"
+      prefix="fn-zorba-dateTime"/>
+
     <zorba:namespace uri="http://www.zorba-xquery.com/modules/xqdoc"; 
                      define="ZORBA_XQDOC_FN_NS" 
                      prefix="fn-zorba-xqdoc"/>

=== modified file 'src/runtime/visitors/pregenerated/planiter_visitor.h'
--- src/runtime/visitors/pregenerated/planiter_visitor.h	2012-12-14 21:50:53 +0000
+++ src/runtime/visitors/pregenerated/planiter_visitor.h	2013-01-02 14:49:24 +0000
@@ -134,6 +134,22 @@
 
     class DefaultCollationIterator;
 
+    class CurrentDate;
+
+    class CurrentDateTime;
+
+    class CurrentTime;
+
+    class ParseDate;
+
+    class ParseDateTime;
+
+    class ParseTime;
+
+    class Timestamp;
+
+    class UTCOffset;
+
 #ifdef ZORBA_WITH_DEBUGGER
     class DebugIterator;
 #endif
@@ -900,6 +916,30 @@
     virtual void beginVisit ( const DefaultCollationIterator& ) = 0;
     virtual void endVisit   ( const DefaultCollationIterator& ) = 0;
 
+    virtual void beginVisit ( const CurrentDate& ) = 0;
+    virtual void endVisit   ( const CurrentDate& ) = 0;
+
+    virtual void beginVisit ( const CurrentDateTime& ) = 0;
+    virtual void endVisit   ( const CurrentDateTime& ) = 0;
+
+    virtual void beginVisit ( const CurrentTime& ) = 0;
+    virtual void endVisit   ( const CurrentTime& ) = 0;
+
+    virtual void beginVisit ( const ParseDate& ) = 0;
+    virtual void endVisit   ( const ParseDate& ) = 0;
+
+    virtual void beginVisit ( const ParseDateTime& ) = 0;
+    virtual void endVisit   ( const ParseDateTime& ) = 0;
+
+    virtual void beginVisit ( const ParseTime& ) = 0;
+    virtual void endVisit   ( const ParseTime& ) = 0;
+
+    virtual void beginVisit ( const Timestamp& ) = 0;
+    virtual void endVisit   ( const Timestamp& ) = 0;
+
+    virtual void beginVisit ( const UTCOffset& ) = 0;
+    virtual void endVisit   ( const UTCOffset& ) = 0;
+
 #ifdef ZORBA_WITH_DEBUGGER
     virtual void beginVisit ( const DebugIterator& ) = 0;
     virtual void endVisit   ( const DebugIterator& ) = 0;

=== modified file 'src/runtime/visitors/pregenerated/printer_visitor.cpp'
--- src/runtime/visitors/pregenerated/printer_visitor.cpp	2012-12-14 21:50:53 +0000
+++ src/runtime/visitors/pregenerated/printer_visitor.cpp	2013-01-02 14:49:24 +0000
@@ -41,6 +41,7 @@
 #include "runtime/booleans/booleans.h"
 #include "runtime/collections/collections.h"
 #include "runtime/context/context.h"
+#include "runtime/datetime/datetime.h"
 #include "runtime/debug/debug_iterator.h"
 #include "runtime/durations_dates_times/durations_dates_times.h"
 #include "runtime/errors_and_diagnostics/errors_and_diagnostics.h"
@@ -701,6 +702,118 @@
 }
 // </DefaultCollationIterator>
 
+
+// <CurrentDate>
+void PrinterVisitor::beginVisit ( const CurrentDate& a) {
+  thePrinter.startBeginVisit("CurrentDate", ++theId);
+  printCommons( &a, theId );
+  thePrinter.endBeginVisit( theId );
+}
+
+void PrinterVisitor::endVisit ( const CurrentDate& ) {
+  thePrinter.startEndVisit();
+  thePrinter.endEndVisit();
+}
+// </CurrentDate>
+
+
+// <CurrentDateTime>
+void PrinterVisitor::beginVisit ( const CurrentDateTime& a) {
+  thePrinter.startBeginVisit("CurrentDateTime", ++theId);
+  printCommons( &a, theId );
+  thePrinter.endBeginVisit( theId );
+}
+
+void PrinterVisitor::endVisit ( const CurrentDateTime& ) {
+  thePrinter.startEndVisit();
+  thePrinter.endEndVisit();
+}
+// </CurrentDateTime>
+
+
+// <CurrentTime>
+void PrinterVisitor::beginVisit ( const CurrentTime& a) {
+  thePrinter.startBeginVisit("CurrentTime", ++theId);
+  printCommons( &a, theId );
+  thePrinter.endBeginVisit( theId );
+}
+
+void PrinterVisitor::endVisit ( const CurrentTime& ) {
+  thePrinter.startEndVisit();
+  thePrinter.endEndVisit();
+}
+// </CurrentTime>
+
+
+// <ParseDate>
+void PrinterVisitor::beginVisit ( const ParseDate& a) {
+  thePrinter.startBeginVisit("ParseDate", ++theId);
+  printCommons( &a, theId );
+  thePrinter.endBeginVisit( theId );
+}
+
+void PrinterVisitor::endVisit ( const ParseDate& ) {
+  thePrinter.startEndVisit();
+  thePrinter.endEndVisit();
+}
+// </ParseDate>
+
+
+// <ParseDateTime>
+void PrinterVisitor::beginVisit ( const ParseDateTime& a) {
+  thePrinter.startBeginVisit("ParseDateTime", ++theId);
+  printCommons( &a, theId );
+  thePrinter.endBeginVisit( theId );
+}
+
+void PrinterVisitor::endVisit ( const ParseDateTime& ) {
+  thePrinter.startEndVisit();
+  thePrinter.endEndVisit();
+}
+// </ParseDateTime>
+
+
+// <ParseTime>
+void PrinterVisitor::beginVisit ( const ParseTime& a) {
+  thePrinter.startBeginVisit("ParseTime", ++theId);
+  printCommons( &a, theId );
+  thePrinter.endBeginVisit( theId );
+}
+
+void PrinterVisitor::endVisit ( const ParseTime& ) {
+  thePrinter.startEndVisit();
+  thePrinter.endEndVisit();
+}
+// </ParseTime>
+
+
+// <Timestamp>
+void PrinterVisitor::beginVisit ( const Timestamp& a) {
+  thePrinter.startBeginVisit("Timestamp", ++theId);
+  printCommons( &a, theId );
+  thePrinter.endBeginVisit( theId );
+}
+
+void PrinterVisitor::endVisit ( const Timestamp& ) {
+  thePrinter.startEndVisit();
+  thePrinter.endEndVisit();
+}
+// </Timestamp>
+
+
+// <UTCOffset>
+void PrinterVisitor::beginVisit ( const UTCOffset& a) {
+  thePrinter.startBeginVisit("UTCOffset", ++theId);
+  printCommons( &a, theId );
+  thePrinter.endBeginVisit( theId );
+}
+
+void PrinterVisitor::endVisit ( const UTCOffset& ) {
+  thePrinter.startEndVisit();
+  thePrinter.endEndVisit();
+}
+// </UTCOffset>
+
 #ifdef ZORBA_WITH_DEBUGGER
 // <DebugIterator>
 void PrinterVisitor::beginVisit ( const DebugIterator& a) {

=== modified file 'src/runtime/visitors/pregenerated/printer_visitor.h'
--- src/runtime/visitors/pregenerated/printer_visitor.h	2012-12-14 21:50:53 +0000
+++ src/runtime/visitors/pregenerated/printer_visitor.h	2013-01-02 14:49:24 +0000
@@ -203,6 +203,30 @@
     void beginVisit( const DefaultCollationIterator& );
     void endVisit  ( const DefaultCollationIterator& );
 
+    void beginVisit( const CurrentDate& );
+    void endVisit  ( const CurrentDate& );
+
+    void beginVisit( const CurrentDateTime& );
+    void endVisit  ( const CurrentDateTime& );
+
+    void beginVisit( const CurrentTime& );
+    void endVisit  ( const CurrentTime& );
+
+    void beginVisit( const ParseDate& );
+    void endVisit  ( const ParseDate& );
+
+    void beginVisit( const ParseDateTime& );
+    void endVisit  ( const ParseDateTime& );
+
+    void beginVisit( const ParseTime& );
+    void endVisit  ( const ParseTime& );
+
+    void beginVisit( const Timestamp& );
+    void endVisit  ( const Timestamp& );
+
+    void beginVisit( const UTCOffset& );
+    void endVisit  ( const UTCOffset& );
+
 #ifdef ZORBA_WITH_DEBUGGER
     void beginVisit( const DebugIterator& );
     void endVisit  ( const DebugIterator& );

=== modified file 'src/unit_tests/CMakeLists.txt'
--- src/unit_tests/CMakeLists.txt	2012-11-12 21:17:32 +0000
+++ src/unit_tests/CMakeLists.txt	2013-01-02 14:49:24 +0000
@@ -17,15 +17,13 @@
   test_base64.cpp
   test_base64_streambuf.cpp
   test_fs_iterator.cpp
+  test_hashmaps.cpp
   test_json_parser.cpp
   test_string.cpp
+  test_strptime.cpp
   test_uri.cpp
   test_uuid.cpp
   unit_tests.cpp
-  test_uri.cpp
-  test_json_parser.cpp
-  test_fs_iterator.cpp
-  test_hashmaps.cpp
 )
 
 IF (NOT ZORBA_NO_FULL_TEXT)

=== modified file 'src/unit_tests/memory_manager.cpp'
--- src/unit_tests/memory_manager.cpp	2012-09-19 21:16:15 +0000
+++ src/unit_tests/memory_manager.cpp	2013-01-02 14:49:24 +0000
@@ -30,7 +30,7 @@
 }
 
 static void print_exception( char const *expr, char const *testName,
-        std::exception const &e ) {
+                             std::exception const &e ) {
     std::cout << "FAILED " << testName << ": exception: " << e.what() <<
         std::endl;
   ++failures;
@@ -40,19 +40,19 @@
 
 #define ASSERT_EXCEPTION( EXPR, EXCEPTION ) \
   try { EXPR; assert_true( #EXPR, testName, false); } \
-  catch (EXCEPTION const& ) { } \
-  catch ( std::exception const &e ){ print_exception( #EXPR, testName, e ); } \
+  catch ( EXCEPTION const& ) { } \
+  catch ( std::exception const &e ) { print_exception( #EXPR, testName, e ); } \
   catch ( ... ) { assert_true ( #EXPR, testName, false ); }
 
 #define ASSERT_NO_EXCEPTION( EXPR ) \
-  try {EXPR; } \
-  catch ( std::exception const &e ){ print_exception( #EXPR, testName, e ); } \
+  try { EXPR; } \
+  catch ( std::exception const &e ) { print_exception( #EXPR, testName, e ); } \
   catch ( ... ) { assert_true (#EXPR, testName, false ); }
 
 #define ASSERT_TRUE_AND_NO_EXCEPTION( EXPR ) \
   try { ASSERT_TRUE ( EXPR ); } \
   catch ( std::exception const &e ) { print_exception( #EXPR, testName, e ); } \
-  catch ( ... ) {assert_true( #EXPR, testName, false ); }
+  catch ( ... ) { assert_true( #EXPR, testName, false ); }
 
 #define TEST( TESTNAME ) \
 static void TESTNAME () { \
@@ -177,9 +177,11 @@
   ASSERT_TRUE(hugePage == mem);
 END_TEST
 
-namespace zorba { namespace UnitTests{
-
 ///////////////////////////////////////////////////////////////////////////////
+
+namespace zorba {
+namespace UnitTests {
+
 int test_mem_manager( int, char*[] )
 {
   PageCreationAllocatesMemoryDeletionFreesIt();
@@ -201,4 +203,7 @@
   return failures ? 1 : 0;
 }
 
-}} //namespace zorba::UnitTests
+} // namespace UnitTests
+} // namespace zorba
+
+/* vim:set et sw=2 ts=2: */

=== modified file 'src/unit_tests/test_base64.cpp'
--- src/unit_tests/test_base64.cpp	2012-09-19 21:16:15 +0000
+++ src/unit_tests/test_base64.cpp	2013-01-02 14:49:24 +0000
@@ -53,11 +53,13 @@
 
 #define ASSERT_NO_EXCEPTION( NO, EXPR ) \
   try { EXPR; } \
-  catch ( std::exception const &e ) { print_exception( NO, #EXPR, __LINE__, e ); }
+  catch ( exception const &e ) { print_exception( NO, #EXPR, __LINE__, e ); } \
+  catch ( ... ) { assert_true( NO, #EXPR, __LINE__, false ); }
 
 #define ASSERT_EXCEPTION( NO, EXPR, EXCEPTION ) \
   try { EXPR; assert_true( NO, #EXPR, __LINE__, false ); } \
-  catch ( EXCEPTION const& ) { }
+  catch ( EXCEPTION const& ) { } \
+  catch ( ... ) { assert_true( NO, #EXPR, __LINE__, false ); }
 
 ///////////////////////////////////////////////////////////////////////////////}
 

=== modified file 'src/unit_tests/test_base64_streambuf.cpp'
--- src/unit_tests/test_base64_streambuf.cpp	2012-06-15 17:01:01 +0000
+++ src/unit_tests/test_base64_streambuf.cpp	2013-01-02 14:49:24 +0000
@@ -51,7 +51,8 @@
 
 #define ASSERT_TRUE_AND_NO_EXCEPTION( NO, EXPR ) \
   try { ASSERT_TRUE( NO, EXPR ); } \
-  catch ( std::exception const &e ) { print_exception( NO, #EXPR, __LINE__, e ); }
+  catch ( exception const &e ) { print_exception( NO, #EXPR, __LINE__, e ); } \
+  catch ( ... ) { assert_true( NO, #EXPR, __LINE__, false ); }
 
 ///////////////////////////////////////////////////////////////////////////////
 

=== modified file 'src/unit_tests/test_icu_streambuf.cpp'
--- src/unit_tests/test_icu_streambuf.cpp	2012-09-19 21:16:15 +0000
+++ src/unit_tests/test_icu_streambuf.cpp	2013-01-02 14:49:24 +0000
@@ -71,7 +71,8 @@
 
 #define ASSERT_TRUE_AND_NO_EXCEPTION( NO, EXPR ) \
   try { ASSERT_TRUE( NO, EXPR ); } \
-  catch ( std::exception const &e ) { print_exception( NO, #EXPR, __LINE__, e ); }
+  catch ( exception const &e ) { print_exception( NO, #EXPR, __LINE__, e ); } \
+  catch ( ... ) { assert_true( NO, #EXPR, __LINE__, false ); }
 
 ///////////////////////////////////////////////////////////////////////////////
 

=== modified file 'src/unit_tests/test_json_parser.cpp'
--- src/unit_tests/test_json_parser.cpp	2012-09-19 21:16:15 +0000
+++ src/unit_tests/test_json_parser.cpp	2013-01-02 14:49:24 +0000
@@ -55,7 +55,8 @@
 
 #define ASSERT_EXCEPTION( EXPR, EXCEPTION ) \
   try { EXPR; assert_true( #EXPR, __LINE__, false ); } \
-  catch ( EXCEPTION const& ) { }
+  catch ( EXCEPTION const& ) { } \
+  catch ( ... ) { assert_true( #EXPR, __LINE__, false ); }
 
 #define ASSERT_NO_EXCEPTION( EXPR ) \
   try { EXPR; } \

=== modified file 'src/unit_tests/test_string.cpp'
--- src/unit_tests/test_string.cpp	2012-09-19 21:16:15 +0000
+++ src/unit_tests/test_string.cpp	2013-01-02 14:49:24 +0000
@@ -82,7 +82,8 @@
 
 #define ASSERT_EXCEPTION( EXPR, EXCEPTION ) \
   try { EXPR; assert_true( #EXPR, __LINE__, false ); } \
-  catch ( EXCEPTION const& ) { }
+  catch ( EXCEPTION const& ) { } \
+  catch ( ... ) { assert_true( #EXPR, __LINE__, false ); }
 
 #define ASSERT_NO_EXCEPTION( EXPR ) \
   try { EXPR; } \

=== added file 'src/unit_tests/test_strptime.cpp'
--- src/unit_tests/test_strptime.cpp	1970-01-01 00:00:00 +0000
+++ src/unit_tests/test_strptime.cpp	2013-01-02 14:49:24 +0000
@@ -0,0 +1,382 @@
+/*
+ * Copyright 2006-2008 The FLWOR Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "stdafx.h"
+
+#include <cstring>
+#include <functional>
+#include <iostream>
+#include <stdexcept>
+#include <string>
+
+#include "util/stl_util.h"
+#include "util/strptime.h"
+#include "zorbautils/locale.h"
+
+using namespace std;
+using namespace zorba;
+using namespace zorba::time;
+
+namespace zloc = zorba::locale;
+
+///////////////////////////////////////////////////////////////////////////////
+
+static int failures;
+
+static bool assert_true( char const *expr, int line, bool result ) {
+  if ( !result ) {
+    cout << "FAILED, line " << line << ": " << expr << endl;
+    ++failures;
+  }
+  return result;
+}
+
+static void print_exception( char const *expr, int line,
+                             std::exception const &e ) {
+  assert_true( expr, line, false );
+  cout << "+ exception: " << e.what() << endl;
+}
+
+#define ASSERT_TRUE( EXPR ) assert_true( #EXPR, __LINE__, !!(EXPR) )
+
+#define ASSERT_EXCEPTION( EXPR, EXCEPTION ) \
+  try { EXPR; assert_true( #EXPR, __LINE__, false ); } \
+  catch ( EXCEPTION const& ) { } \
+  catch ( ... ) { assert_true( #EXPR, __LINE__, false ); }
+
+#define ASSERT_NO_EXCEPTION( EXPR ) \
+  try { EXPR; } \
+  catch ( std::exception const &e ) { print_exception( #EXPR, __LINE__, e ); } \
+  catch ( ... ) { assert_true( #EXPR, __LINE__, false ); }
+
+#define ASSERT_TRUE_AND_NO_EXCEPTION( EXPR ) \
+  try { ASSERT_TRUE( EXPR ); } \
+  catch ( std::exception const &e ) { print_exception( #EXPR, __LINE__, e ); } \
+  catch ( ... ) { assert_true( #EXPR, __LINE__, false ); }
+
+///////////////////////////////////////////////////////////////////////////////
+
+static void test_ampm() {
+  char const fmt[] = "%l%M %p";
+  char const *bp;
+  ztm tm;
+
+  {
+    string buf = "0123 ";
+    buf += zloc::get_time_ampm( false );
+    ::memset( &tm, 0, sizeof( tm ) );
+    ASSERT_NO_EXCEPTION( bp = time::strptime( buf, fmt, &tm ) );
+    ASSERT_TRUE( bp = buf.c_str() + buf.length() );
+    ASSERT_TRUE( tm.tm_hour ==  1 );
+    ASSERT_TRUE( tm.tm_min  == 23 );
+  }
+  {
+    string buf = "0123 ";
+    buf += zloc::get_time_ampm( true );
+    ::memset( &tm, 0, sizeof( tm ) );
+    ASSERT_NO_EXCEPTION( bp = time::strptime( buf, fmt, &tm ) );
+    ASSERT_TRUE( bp = buf.c_str() + buf.length() );
+    ASSERT_TRUE( tm.tm_hour == 13 );    // note 1300 hours
+    ASSERT_TRUE( tm.tm_min  == 23 );
+  }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+static void test_literals() {
+  char const fmt[] = "JUNK %k %% JUNK %t JUNK %n %M";
+  char const buf[] = "JUNK 14 % JUNK JUNK 15";
+  size_t const len = ::strlen( buf );
+  char const *bp;
+  ztm tm;
+  ::memset( &tm, 0, sizeof( tm ) );
+  ASSERT_NO_EXCEPTION( bp = time::strptime( buf, fmt, &tm ) );
+  ASSERT_TRUE( bp == buf + len );
+  ASSERT_TRUE( tm.tm_hour == 14 );
+  ASSERT_TRUE( tm.tm_min  == 15 );
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+typedef char const* (*locale_fn_type)(unsigned);
+typedef int ztm::*ztm_int_ptr;
+
+static void test_locale( char const *conv, locale_fn_type locale_fn, int limit,
+                         ztm_int_ptr ztm_mbr ) {
+  ztm tm;
+  for ( int i = 0; i < limit; ++i ) {
+    char const *bp;
+    {
+      char const *const buf = (*locale_fn)( i );
+      size_t const len = ::strlen( buf );
+      ::memset( &tm, 0, sizeof( tm ) );
+      ASSERT_NO_EXCEPTION( bp = time::strptime( buf, conv, &tm ) )
+      ASSERT_TRUE( bp == buf + len );
+      ASSERT_TRUE( tm.*ztm_mbr == i );
+    }
+    {
+      string buf = (*locale_fn)( i );
+      string::size_type const len = buf.length();
+      buf += "JUNK";
+      ::memset( &tm, 0, sizeof( tm ) );
+      ASSERT_NO_EXCEPTION( bp = time::strptime( buf, conv, &tm ) )
+      ASSERT_TRUE( bp == buf.c_str() + len );
+      ASSERT_TRUE( tm.*ztm_mbr == i );
+    }
+  }
+  ASSERT_EXCEPTION( time::strptime( "JUNK", conv, &tm ), invalid_value );
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+typedef int (*unary_fn_type)(int);
+
+int identity( int i ) {
+  return i;
+}
+
+int minus_1( int i ) {
+  return i - 1;
+}
+
+int minus_1900( int i ) {
+  return i - 1900;
+}
+
+int mod_12( int i ) {
+  return i % 12;
+}
+
+int num_digits( int i ) {
+  int n = !i;
+  while ( i )
+    i /= 10, ++n;
+  return n;
+}
+
+static void test_range( char const *conv, int low, int high,
+                        ztm_int_ptr ztm_mbr,
+                        unary_fn_type unary_fn = &identity ) {
+  ztd::itoa_buf_type buf;
+  ztm tm;
+  for ( int i = low; i <= high; ++i ) {
+    ztd::itoa( i, buf );
+    size_t const len = ::strlen( buf );
+    char const *bp;
+    ::memset( &tm, 0, sizeof( tm ) );
+    ASSERT_NO_EXCEPTION( bp = time::strptime( buf, conv, &tm ) )
+    ASSERT_TRUE( bp == buf + len );
+    ASSERT_TRUE( tm.*ztm_mbr == (*unary_fn)(i) );
+  }
+  ASSERT_EXCEPTION( time::strptime( "JUNK", conv, &tm ), invalid_value );
+
+  ztd::itoa( --low, buf );
+  ASSERT_EXCEPTION( time::strptime( buf   , conv, &tm ), invalid_value );
+
+  int const high2 = high + 1;
+  if ( num_digits( high2 ) == num_digits( high ) ) {
+    ztd::itoa( ++high, buf );
+    ASSERT_EXCEPTION( time::strptime( buf   , conv, &tm ), invalid_value );
+  }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+static void test_bad_dates() {
+  struct bad_date {
+    char const *conv;
+    char const *date;
+  };
+  static bad_date bad_dates[] = {
+    { "%F",     "   2011-02-29" },      // not a leap year
+    { "%F",     "   2011-04-31" },      // Apr 31 is invalid
+    { "%F",     "   2011-06-31" },      // Jun 31 is invalid
+    { "%F",     "   2011-09-31" },      // Sep 31 is invalid
+    { "%F",     "   2011-11-31" },      // Nov 31 is invalid
+    { "%w %F",  " 1 2012-01-01" },      // date is a Sun (0)
+    { "%w %F",  " 2 2012-01-01" },      // date is a Sun (0)
+    { "%w %F",  " 3 2012-01-01" },      // date is a Sun (0)
+    { "%w %F",  " 4 2012-01-01" },      // date is a Sun (0)
+    { "%w %F",  " 5 2012-01-01" },      // date is a Sun (0)
+    { "%w %F",  " 6 2012-01-01" },      // date is a Sun (0)
+    { "%w %F",  " 0 2013-01-01" },      // date is a Tue (2)
+    { "%w %F",  " 1 2013-01-01" },      // date is a Tue (2)
+    { "%w %F",  " 3 2013-01-01" },      // date is a Tue (2)
+    { "%w %F",  " 4 2013-01-01" },      // date is a Tue (2)
+    { "%w %F",  " 5 2013-01-01" },      // date is a Tue (2)
+    { "%w %F",  " 6 2013-01-01" },      // date is a Tue (2)
+    { "%j %F",  " 1 2013-01-01" },      // day is 0
+    { "%j %F",  "31 2013-02-01" },      // day is 32
+    { "%j %F",  "33 2013-02-01" },      // day is 32
+    { "%j %F",  "60 2012-03-01" },      // day is 61
+    { "%j %F",  "62 2012-03-01" },      // day is 61
+    0
+  };
+  ztm tm;
+  for ( bad_date const *p = bad_dates; p->date; ++p ) {
+    ::memset( &tm, 0, sizeof( tm ) );
+    ASSERT_EXCEPTION( time::strptime( p->date, p->conv, &tm ), invalid_value );
+  }
+}
+
+static void test_D() {                  // %m/%d/%y
+  ztm tm;
+  char const *const buf = "1/2/12";
+  size_t const len = ::strlen( buf );
+  char const *bp;
+  ::memset( &tm, 0, sizeof( tm ) );
+  ASSERT_NO_EXCEPTION( bp = time::strptime( buf, "%D", &tm ) )
+  ASSERT_TRUE( bp == buf + len );
+  ASSERT_TRUE( tm.tm_mon == 0 );
+  ASSERT_TRUE( tm.tm_mday == 2 );
+  ASSERT_TRUE( tm.tm_year == 112 );     // years since 1900
+}
+
+static void test_F() {                  // %Y-%m-%d
+  ztm tm;
+  char const *const buf = "2012-1-2";
+  size_t const len = ::strlen( buf );
+  char const *bp;
+  ::memset( &tm, 0, sizeof( tm ) );
+  ASSERT_NO_EXCEPTION( bp = time::strptime( buf, "%F", &tm ) )
+  ASSERT_TRUE( bp == buf + len );
+  ASSERT_TRUE( tm.tm_mon == 0 );
+  ASSERT_TRUE( tm.tm_mday == 2 );
+  ASSERT_TRUE( tm.tm_year == 112 );     // years since 1900
+}
+
+static void test_invalid_specification() {
+  static char const bad_specs[] = "fgGiJKLNoPqQ";
+  ztm tm;
+  char spec[3];
+  spec[0] = '%';
+  spec[2] = '\0';
+  for ( char const *s = bad_specs; *s; ++s ) {
+    spec[1] = *s;
+    ASSERT_EXCEPTION(
+      time::strptime( "JUNK", spec, &tm ), invalid_specification
+    );
+  }
+}
+
+static void test_j() {                  // dat of year: 001-366
+  ztm tm;
+  char const *const buf = "2012-1-2";
+  size_t const len = ::strlen( buf );
+  char const *bp;
+  ::memset( &tm, 0, sizeof( tm ) );
+  ASSERT_NO_EXCEPTION( bp = time::strptime( buf, "%F", &tm ) )
+  ASSERT_TRUE( bp == buf + len );
+  ASSERT_TRUE( tm.tm_yday == 0 );
+}
+
+static void test_zZ() {
+  struct gmt_test {
+    char const* s_off;
+    long l_off;
+  };
+  static gmt_test const gmt_tests[] = {
+     "0000",                        0,
+     "0030",                  30 * 60,
+     "0100",    1 * 60 * 60 +  0 * 60,
+     "2300",   23 * 60 * 60 +  0 * 60,
+     "2400",   24 * 60 * 60 +  0 * 60,
+    "+0000",                        0,
+    "+0030",                  30 * 60,
+    "+0100",    1 * 60 * 60 +  0 * 60,
+    "+2300",   23 * 60 * 60 +  0 * 60,
+    "+2400",   24 * 60 * 60 +  0 * 60,
+    "-0000",                        0,
+    "-0030",                 -30 * 60,
+    "-0100",   -1 * 60 * 60 +  0 * 60,
+    "-2300",  -23 * 60 * 60 +  0 * 60,
+    "GMT"  ,                        0,
+    "UTC"  ,                        0,
+    "UT"   ,                        0,
+    "EDT"  ,   -4 * 60 * 60 +  0 * 60,
+    "EST"  ,   -5 * 60 * 60 +  0 * 60,
+    "CDT"  ,   -5 * 60 * 60 +  0 * 60,
+    "CST"  ,   -6 * 60 * 60 +  0 * 60,
+    "MDT"  ,   -6 * 60 * 60 +  0 * 60,
+    "MST"  ,   -7 * 60 * 60 +  0 * 60,
+    "PDT"  ,   -7 * 60 * 60 +  0 * 60,
+    "PST"  ,   -8 * 60 * 60 +  0 * 60,
+    0
+  };
+
+  ztm tm;
+  for ( gmt_test const *p = gmt_tests; p->s_off; ++p ) {
+    size_t const len = ::strlen( p->s_off );
+    char const *bp;
+    ::memset( &tm, 0, sizeof( tm ) );
+    ASSERT_NO_EXCEPTION( bp = time::strptime( p->s_off, "%z", &tm ) );
+    ASSERT_TRUE( bp == p->s_off + len );
+    ASSERT_TRUE( tm.ZTM_GMTOFF == p->l_off );
+    ASSERT_TRUE( tm.tm_isdst == (p->s_off[1] == 'D') );
+  }
+
+  static char const *const bad_gmts[] = {
+    "*0000",
+    "00A0",
+    "9960",
+    "XXX",
+    0
+  };
+  for ( char const *const *p = bad_gmts; *p; ++p )
+    ASSERT_EXCEPTION( time::strptime( *p, "%z", &tm ), invalid_value );
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+namespace zorba {
+namespace UnitTests {
+
+int test_strptime( int, char*[] ) {
+
+  test_locale( "%A", &zloc::get_weekday_abbr,  7, &ztm::tm_wday );
+  test_locale( "%A", &zloc::get_weekday_name,  7, &ztm::tm_wday );
+  test_locale( "%a", &zloc::get_weekday_abbr,  7, &ztm::tm_wday );
+  test_locale( "%a", &zloc::get_weekday_name,  7, &ztm::tm_wday );
+  test_locale( "%b", &zloc::get_month_abbr  , 12, &ztm::tm_mon  );
+  test_locale( "%B", &zloc::get_month_name  , 12, &ztm::tm_mon  );
+
+  test_range( "%d", 1,   31, &ztm::tm_mday );
+  test_range( "%j", 1,  366, &ztm::tm_yday, &minus_1 );
+  test_range( "%k", 0,   23, &ztm::tm_hour );
+  test_range( "%H", 0,   23, &ztm::tm_hour );
+  test_range( "%l", 1,   12, &ztm::tm_hour, &mod_12 );
+  test_range( "%I", 1,   12, &ztm::tm_hour, &mod_12 );
+  test_range( "%m", 1,   12, &ztm::tm_mon , &minus_1 );
+  test_range( "%M", 0,   59, &ztm::tm_min );
+  test_range( "%u", 1,    7, &ztm::tm_wday, &minus_1 );
+  test_range( "%w", 0,    6, &ztm::tm_wday );
+  test_range( "%Y", 0, 9999, &ztm::tm_year, &minus_1900 );
+
+  test_ampm();
+  test_bad_dates();
+  test_D();
+  test_F();
+  test_invalid_specification();
+  test_literals();
+  test_zZ();
+
+  cout << failures << " test(s) failed\n";
+  return failures ? 1 : 0;
+}
+
+} // namespace UnitTests
+} // namespace zorba
+/* vim:set et sw=2 ts=2: */

=== modified file 'src/unit_tests/unit_test_list.h'
--- src/unit_tests/unit_test_list.h	2012-09-19 21:16:15 +0000
+++ src/unit_tests/unit_test_list.h	2013-01-02 14:49:24 +0000
@@ -41,6 +41,7 @@
   int test_json_parser( int, char*[] );
 
   int test_string( int, char*[] );
+  int test_strptime( int, char*[] );
 
   int test_unique_ptr( int, char*[] );
 

=== modified file 'src/unit_tests/unit_tests.cpp'
--- src/unit_tests/unit_tests.cpp	2012-11-12 21:17:32 +0000
+++ src/unit_tests/unit_tests.cpp	2013-01-02 14:49:24 +0000
@@ -50,6 +50,7 @@
   libunittests["json_parser"] = test_json_parser;
 
   libunittests["string"] = test_string;
+  libunittests["strptime"] = test_strptime;
 
 #ifndef ZORBA_NO_FULL_TEXT
   libunittests["stemmer"] = test_stemmer;

=== modified file 'src/util/CMakeLists.txt'
--- src/util/CMakeLists.txt	2012-12-12 01:04:54 +0000
+++ src/util/CMakeLists.txt	2013-01-02 14:49:24 +0000
@@ -25,6 +25,8 @@
   mem_streambuf.cpp
   regex.cpp
   string_util.cpp
+  time_util.cpp
+  strptime.cpp
   unicode_util.cpp
   unicode_categories.cpp
   uri_util.cpp

=== modified file 'src/util/ascii_util.h'
--- src/util/ascii_util.h	2012-11-29 15:27:35 +0000
+++ src/util/ascii_util.h	2013-01-02 14:49:24 +0000
@@ -922,7 +922,7 @@
  * @param s The string.
  */
 template<class StringType> inline
-void trim_end_whitespace( StringType &s, char const *chars ) {
+void trim_end_whitespace( StringType &s ) {
   trim_end( s, whitespace );
 }
 

=== modified file 'src/util/string_util.cpp'
--- src/util/string_util.cpp	2012-09-19 21:16:15 +0000
+++ src/util/string_util.cpp	2013-01-02 14:49:24 +0000
@@ -58,7 +58,8 @@
 #define ENABLE_CLIPPING 0
 
 template<typename T>
-static void check_parse_number( char const *s, char *end,  T *result ) {
+static void check_parse_number( char const *s, char const *end,
+                                bool check_trailing_chars, T *result ) {
   if ( errno == ERANGE ) {
     if ( result ) {
 #if ENABLE_CLIPPING
@@ -74,48 +75,59 @@
   }
   if ( end == s )
     throw std::invalid_argument( BUILD_STRING( '"', s, "\": no digits" ) );
-  for ( ; *end; ++end )                 // remaining characters, if any, ...
-    if ( !ascii::is_space( *end ) )     // ... may only be whitespace
-      throw std::invalid_argument(
-        BUILD_STRING( '"', *end, "\": invalid character" )
-      );
-}
-
-double atod( char const *s ) {
-  char *end;
-  errno = 0;
-  double result = std::strtod( s, &end );
-  check_parse_number( s, end, &result );
-  return result;
-}
-
-float atof( char const *s ) {
-  char *end;
-  errno = 0;
-  float result = std::strtof( s, &end );
-  check_parse_number( s, end, &result );
-  return result;
-}
-
-long long atoll( char const *s ) {
-  char *end;
-  errno = 0;
-  long long const result = std::strtoll( s, &end, 10 );
-  check_parse_number( s, end, static_cast<long long*>( nullptr ) );
-  return result;
-}
-
-unsigned long long atoull( char const *s ) {
+  if ( check_trailing_chars )
+    for ( ; *end; ++end )               // remaining characters, if any, ...
+      if ( !ascii::is_space( *end ) )   // ... may only be whitespace
+        throw std::invalid_argument(
+          BUILD_STRING( '"', *end, "\": invalid character" )
+        );
+  }
+
+#define ATON_PREAMBLE()           \
+  bool check_trailing_chars;      \
+  char const *pc;                 \
+  if ( !end ) {                   \
+    end = &pc;                    \
+    check_trailing_chars = false; \
+  } else                          \
+    check_trailing_chars = true;  \
+  errno = 0
+
+double atod( char const *s, char const **end ) {
+  ATON_PREAMBLE();
+  double result = std::strtod( s, (char**)end );
+  check_parse_number( s, *end, check_trailing_chars, &result );
+  return result;
+}
+
+float atof( char const *s, char const **end ) {
+  ATON_PREAMBLE();
+  float result = std::strtof( s, (char**)end );
+  check_parse_number( s, *end, check_trailing_chars, &result );
+  return result;
+}
+
+long long atoll( char const *s, char const **end ) {
+  ATON_PREAMBLE();
+  long long const result = std::strtoll( s, (char**)end, 10 );
+  check_parse_number(
+    s, *end, check_trailing_chars, static_cast<long long*>( nullptr )
+  );
+  return result;
+}
+
+unsigned long long atoull( char const *s, char const **end ) {
+  ATON_PREAMBLE();
   //
   // We have to check for '-' ourselves since strtoull(3) allows it (oddly).
   //
   s = ascii::trim_start_whitespace( s );
   bool const minus = *s == '-';
 
-  char *end;
-  errno = 0;
-  unsigned long long const result = std::strtoull( s, &end, 10 );
-  check_parse_number( s, end, static_cast<unsigned long long*>( nullptr ) );
+  unsigned long long const result = std::strtoull( s, (char**)end, 10 );
+  check_parse_number(
+    s, *end, check_trailing_chars, static_cast<unsigned long long*>( nullptr )
+  );
 
   if ( minus && result ) {
     //
@@ -123,7 +135,7 @@
     // Hence, this allows "-0" and treats it as "0".
     //
     throw std::invalid_argument(
-      "\"-\": invalid character for unsigned integer"
+      "'-': invalid character for unsigned integer"
     );
   }
   return result;

=== modified file 'src/util/string_util.h'
--- src/util/string_util.h	2012-10-19 13:17:28 +0000
+++ src/util/string_util.h	2013-01-02 14:49:24 +0000
@@ -410,48 +410,56 @@
  *
  * @param s The null-terminated C string to parse.  Leading and trailing
  * whitespace is ignored.
+ * @param end If not \c null, this is set to point to the character after the
+ * last character parsed.
  * @return Returns the \c double value.
  * @throws invalid_argument if \a s contains characters other than digits or
  * leading/trailing whitespace, or contains no digits at all.
  * @throws range_error if the number overflows/underflows.
  */
-double atod( char const *s );
+double atod( char const *s, char const **end = nullptr );
 
 /**
  * Parses the given string for a \c float.
  *
  * @param s The null-terminated C string to parse.  Leading and trailing
  * whitespace is ignored.
+ * @param end If not \c null, this is set to point to the character after the
+ * last character parsed.
  * @return Returns the \c float value.
  * @throws invalid_argument if \a s contains characters other than digits or
  * leading/trailing whitespace, or contains no digits at all.
  * @throws range_error if the number overflows/underflows.
  */
-float atof( char const *s );
+float atof( char const *s, char const **end = nullptr );
 
 /**
  * Parses the given string for a <code>long lomg</code>.
  *
  * @param s The null-terminated C string to parse.  Leading and trailing
  * whitespace is ignored.
+ * @param end If not \c null, this is set to point to the character after the
+ * last character parsed.
  * @return Returns the <code>long long</code> value.
  * @throws invalid_argument if \a s contains characters other than digits or
  * leading/trailing whitespace, or contains no digits at all.
  * @throws range_error if the number overflows/underflows.
  */
-long long atoll( char const *s );
+long long atoll( char const *s, char const **end = nullptr );
 
 /**
  * Parses the given string for an <code>unsigned long lomg</code>.
  *
  * @param s The null-terminated C string to parse.  Leading and trailing
  * whitespace is ignored.
+ * @param end If not \c null, this is set to point to the character after the
+ * last character parsed.
  * @return Returns the <code>unsigned long long</code> value.
  * @throws invalid_argument if \a s contains characters other than digits or
  * leading/trailing whitespace, or contains no digits at all.
  * @throws range_error if the number overflows/underflows.
  */
-unsigned long long atoull( char const *s );
+unsigned long long atoull( char const *s, char const **end = nullptr );
 
 /**
  * Parses the given string for a C++ signed integral type.
@@ -459,10 +467,12 @@
  * @tparam IntegralType The C++ signed integral type to parse for.
  * @param s The null-terminated C string to parse.  Leading and trailing
  * whitespace is ignored.
+ * @param end If not \c null, this is set to point to the character after the
+ * last character parsed.
  * @return Returns the \c IntegralType value.
- * @throws invalid_argument if \a s contains characters other than digits or
- * leading/trailing whitespace, or contains no digits at all.
- * @throws range_error if the number overflows/underflows.
+ * @throws invalid_argument if \a s contains characters other than digits, a
+ * sign, or leading/trailing whitespace, or contains no digits at all.
+ * @throws range_error if the number is either too small or too big.
  */
 template<typename IntegralType> inline
 //
@@ -473,8 +483,8 @@
 typename std::enable_if<ZORBA_TR1_NS::is_integral<IntegralType>::value
                      && ZORBA_TR1_NS::is_signed<IntegralType>::value,
                         IntegralType>::type
-aton( char const *s ) {
-  long long const result = atoll( s );
+aton( char const *s, char const **end = nullptr ) {
+  long long const result = atoll( s, end );
   if ( result < std::numeric_limits<IntegralType>::min() ||
        result > std::numeric_limits<IntegralType>::max() )
     throw std::range_error(
@@ -484,31 +494,101 @@
 }
 
 /**
+ * Parses the given string for a C++ signed integral type.
+ *
+ * @tparam IntegralType The C++ signed integral type to parse for.
+ * @param s The null-terminated C string to parse.  Leading and trailing
+ * whitespace is ignored.
+ * @param low The lower acceptable bound.
+ * @param high the higher acceptable bound.
+ * @param end If not \c null, this is set to point to the character after the
+ * last character parsed.
+ * @return Returns the \c IntegralType value.
+ * @throws invalid_argument if \a s contains characters other than digits, a
+ * sign, or leading/trailing whitespace, or contains no digits at all.
+ * @throws range_error if the number is either too small or too big.
+ */
+template<typename IntegralType> inline
+//
+// Note that the is_integral shouldn't be needed since is_signed means "is a
+// signed integral type", but Microsoft's implementation is broken and returns
+// true for floating point types as well.
+//
+typename std::enable_if<ZORBA_TR1_NS::is_integral<IntegralType>::value
+                     && ZORBA_TR1_NS::is_signed<IntegralType>::value,
+                        IntegralType>::type
+aton( char const *s, IntegralType low, IntegralType high,
+      char const **end = nullptr ) {
+  long long const result = atoll( s, end );
+  if ( result < low || result > high )
+    throw std::range_error(
+      BUILD_STRING(
+        '"', result, "\": number not in range ", low, '-', high
+      )
+    );
+  return static_cast<IntegralType>( result );
+}
+
+/**
  * Parses the given string for a C++ unsigned integral types.
  *
  * @tparam IntegralType The C++ unsigned integral type to parse for.
  * @param s The null-terminated C string to parse.  Leading and trailing
  * whitespace is ignored.
+ * @param end If not \c null, this is set to point to the character after the
+ * last character parsed.
  * @return Returns the \c IntegralType value.
- * @throws invalid_argument if \a s contains characters other than digits or
- * leading/trailing whitespace, or contains no digits at all.
- * @throws range_error if the number overflows/underflows.
+ * @throws invalid_argument if \a s contains characters other than digits, a
+ * sign, or leading/trailing whitespace, or contains no digits at all.
+ * @throws range_error if the number is either too small or too big.
  */
 template<typename IntegralType> inline
 typename std::enable_if<ZORBA_TR1_NS::is_unsigned<IntegralType>::value,
                         IntegralType>::type
-aton( char const *s ) {
-  unsigned long long const result = atoull( s );
+aton( char const *s, char const **end = nullptr ) {
+  unsigned long long const result = atoull( s, end );
   if ( result > std::numeric_limits<IntegralType>::max() )
     throw std::range_error( BUILD_STRING( '"', result, "\": number too big" ) );
   return static_cast<IntegralType>( result );
 }
 
 /**
+ * Parses the given string for a C++ unsigned integral types.
+ *
+ * @tparam IntegralType The C++ unsigned integral type to parse for.
+ * @param s The null-terminated C string to parse.  Leading and trailing
+ * whitespace is ignored.
+ * @param low The lower acceptable bound.
+ * @param high the higher acceptable bound.
+ * @param end If not \c null, this is set to point to the character after the
+ * last character parsed.
+ * @return Returns the \c IntegralType value.
+ * @throws invalid_argument if \a s contains characters other than digits or
+ * leading/trailing whitespace, or contains no digits at all.
+ * @throws range_error if the number is either too small or too big.
+ */
+template<typename IntegralType> inline
+typename std::enable_if<ZORBA_TR1_NS::is_unsigned<IntegralType>::value,
+                        IntegralType>::type
+aton( char const *s, IntegralType low, IntegralType high,
+      char const **end = nullptr ) {
+  unsigned long long const result = atoull( s, end );
+  if ( result < low || result > high )
+    throw std::range_error(
+      BUILD_STRING(
+        '"', result, "\": number not in range ", low, '-', high
+      )
+    );
+  return static_cast<IntegralType>( result );
+}
+
+/**
  * Parses the given string for a C++ \c double type.
  *
  * @param s The null-terminated C string to parse.  Leading and trailing
  * whitespace is ignored.
+ * @param end If not \c null, this is set to point to the character after the
+ * last character parsed.
  * @return Returns the \c double value.
  * @throws invalid_argument if \a s contains characters other than those for a
  * valid \c double value or leading/trailing whitespace, or contains no digits
@@ -518,8 +598,8 @@
 template<typename NumericType> inline
 typename std::enable_if<ZORBA_TR1_NS::is_same<NumericType,double>::value,
                         NumericType>::type
-aton( char const *s ) {
-  return atod( s );
+aton( char const *s, char const **end = nullptr ) {
+  return atod( s, end );
 }
 
 /**
@@ -527,6 +607,8 @@
  *
  * @param s The null-terminated C string to parse.  Leading and trailing
  * whitespace is ignored.
+ * @param end If not \c null, this is set to point to the character after the
+ * last character parsed.
  * @return Returns the \c float value.
  * @throws invalid_argument if \a s contains characters other than those for a
  * valid \c float value or leading/trailing whitespace, or contains no digits
@@ -536,8 +618,8 @@
 template<typename NumericType> inline
 typename std::enable_if<ZORBA_TR1_NS::is_same<NumericType,float>::value,
                         NumericType>::type
-aton( char const *s ) {
-  return atof( s );
+aton( char const *s, char const **end = nullptr ) {
+  return atof( s, end );
 }
 
 ////////// To-string conversion ////////////////////////////////////////////////

=== added file 'src/util/strptime.cpp'
--- src/util/strptime.cpp	1970-01-01 00:00:00 +0000
+++ src/util/strptime.cpp	2013-01-02 14:49:24 +0000
@@ -0,0 +1,620 @@
+/*
+ * Copyright 2006-2008 The FLWOR Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// standard
+#include <cstring>
+#include <string>
+
+// Zorba
+#include "ascii_util.h"
+#include "cxx_util.h"
+#include "string_util.h"
+#include "zorbautils/locale.h"
+
+// local
+#include "strptime.h"
+#include "time_util.h"
+
+using namespace std;
+
+namespace zorba {
+namespace time {
+
+///////////////////////////////////////////////////////////////////////////////
+
+exception::exception( string const &msg ) :
+  runtime_error( msg )
+{
+}
+
+exception::~exception() throw() {
+  // out-of-line since it's virtual
+}
+
+insufficient_buffer::insufficient_buffer() :
+  exception( "insufficient buffer" )
+{
+}
+
+invalid_specification::invalid_specification( char spec ) :
+  invalid_argument(
+    BUILD_STRING( '\'', ascii::printable_char( spec ), "': invalid %" )
+  ),
+  spec_( spec )
+{
+}
+
+invalid_specification::~invalid_specification() throw() {
+  // out-of-line since it's virtual
+}
+
+invalid_value_specs::invalid_value_specs( char spec ) :
+  specs_( 1, spec )
+{
+}
+
+invalid_value_specs::invalid_value_specs( char const *specs ) :
+  specs_( specs )
+{
+}
+
+invalid_value_value::invalid_value_value( char c ) :
+  value_( 1, c )
+{
+}
+
+invalid_value_value::invalid_value_value( char const *buf, size_t len ) :
+  value_( buf, len )
+{
+  ascii::trim_end_whitespace( value_ );
+}
+
+template<typename ValueType>
+invalid_value_value::invalid_value_value( ValueType const &value ) :
+  value_( BUILD_STRING( value ) )
+{
+}
+
+std::string invalid_value::build_msg( string const &value,
+                                      string const &specs ) {
+  return BUILD_STRING( '"', value, "\": invalid value for %", specs );
+}
+
+invalid_value::invalid_value( char const *buf, size_t len, char spec ) :
+  invalid_value_value( buf, len ),
+  invalid_value_specs( spec ),
+  exception( build_msg( value_, specs_ ) )
+{
+}
+
+invalid_value::invalid_value( char const *buf, size_t len, char const *specs ) :
+  invalid_value_value( buf, len ),
+  invalid_value_specs( specs ),
+  exception( build_msg( value_, specs_ ) )
+{
+}
+
+template<typename ValueType>
+invalid_value::invalid_value( ValueType const &value, char spec ) :
+  invalid_value_value( value ),
+  invalid_value_specs( spec ),
+  exception( build_msg( value_, specs_ ) )
+{
+}
+
+template<typename ValueType>
+invalid_value::invalid_value( ValueType const &value, char const *specs ) :
+  invalid_value_value( value ),
+  invalid_value_specs( specs ),
+  exception( build_msg( value_, specs_ ) )
+{
+}
+
+invalid_value::~invalid_value() throw() {
+  // out-of-line since it's virtual
+}
+
+literal_mismatch::literal_mismatch( char expected, char got ) :
+  exception(
+    BUILD_STRING(
+      '\'', ascii::printable_char( got ), "': literal character mismatched '",
+      expected, '\''
+    )
+  ),
+  expected_( expected ),
+  got_( got )
+{
+}
+
+literal_mismatch::~literal_mismatch() throw() {
+  // out-of-line since it's virtual
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+struct rfc2822_obs_zone {
+  char const *name;
+  long gmtoff;
+  bool isdst;
+};
+
+//
+// See RFC 2822: "Internet Message Format," section 4.3, "Obsolete Date and
+// Time."
+//
+static rfc2822_obs_zone const rfc2822_obs_zones[] = {
+  { "GMT",  0                 },
+  { "UTC",  0                 }, // non-RFC: be liberal in what you accept....
+  { "UT" ,  0                 }, // must go after "UTC"
+  { "EDT", -4 * 60 * 60, true },
+  { "EST", -5 * 60 * 60       },
+  { "CDT", -5 * 60 * 60, true },
+  { "CST", -6 * 60 * 60       },
+  { "MDT", -6 * 60 * 60, true },
+  { "MST", -7 * 60 * 60       },
+  { "PDT", -7 * 60 * 60, true },
+  { "PST", -8 * 60 * 60       },
+  { 0, 0, 0 }
+};
+
+///////////////////////////////////////////////////////////////////////////////
+
+typedef char const* (*locale_fn_type)(unsigned);
+
+template<typename IntType> inline
+bool bits_set( IntType flags, IntType bits ) {
+  return (flags & bits) == bits;
+}
+
+//
+// This is an adapter function to adapt locale::get_time_ampm(bool) to a
+// function that takes an unsigned parameter so that locale_find() can be used
+// for it.
+//
+static char const* get_time_ampm( unsigned pm ) {
+  return locale::get_time_ampm( pm );
+}
+
+static void locale_find( char conv, char const **bpp, locale_fn_type locale_fn,
+                         int limit, int *result, bool *found = nullptr ) {
+  char const *&bp = *bpp;
+  size_t len_sum = 0;
+
+  for ( int i = 0; i < limit; ++i ) {
+    char const *const s = (*locale_fn)( i );
+    size_t const len = ::strlen( s );
+    len_sum += len;
+    if ( ::strncmp( bp, s, len ) == 0 ) {
+      *result = i;
+      if ( found )
+        *found = true;
+      bp += len;
+      return;
+    }
+  }
+  if ( !found ) {
+    //
+    // Since we don't know the extent of the value in the buffer, extract a
+    // representative chunk whose length is the average length of all the legal
+    // values.
+    //
+    throw invalid_value( bp, len_sum / limit, conv );
+  }
+  *found = false;
+}
+
+static void parse_num( char conv, char const **bpp, unsigned low,
+                       unsigned high, int *result ) {
+  char const *&bp = *bpp;
+  char c = *bp;
+  if ( !ascii::is_digit( c ) )
+    throw invalid_value( c, conv );
+
+  unsigned limit = high; // "high" also determines the number of digits
+  unsigned n = 0;
+
+  do {
+    n = n * 10 + c - '0';
+    limit /= 10;
+    c = *++bp;
+  } while ( limit && ascii::is_digit( c ) );
+
+  if ( n < low || n > high )
+    throw invalid_value( n, conv );
+  *result = n;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+/*-
+ * Copyright (c) 1997, 1998, 2005, 2008 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code was contributed to The NetBSD Foundation by Klaus Klein.
+ * Heavily optimised by David Laight
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+//
+// We do not implement alternate representations. However, we always check
+// whether a given modifier is allowed for a certain conversion.
+//
+int const ALT_E = 0x01;
+int const ALT_O = 0x02;
+#define CHECK_ALT(x) \
+  do { if ( alt_format & ~(x) ) throw invalid_specification( c ); } while (0)
+
+static char const* strptime_impl( char const *buf, char const *fmt, ztm *tm,
+                                  unsigned *set_fields ) {
+  char const *bp = buf;
+  char c;
+  bool found;
+  char const *recurse_fmt;
+  bool split_year = false;
+
+  while ( (c = *fmt++) ) {
+    if ( !*bp )
+      throw insufficient_buffer();
+
+    if ( ascii::is_space( c ) ) {
+      bp = ascii::trim_start_whitespace( bp );
+      continue;
+    }
+
+    int alt_format = 0;
+    int n;
+
+    if ( c != '%' ) {                   // literal
+literal:
+      CHECK_ALT(0);
+      if ( *bp != c )
+        throw literal_mismatch( c, *bp );
+      ++bp;
+      continue;
+    }
+
+again:
+    switch ( c = *fmt++ ) {
+      case '%':
+        goto literal;
+
+      case 'a': // abbreviated weekday name
+      case 'A': // full weekday name
+        CHECK_ALT(0);
+        locale_find(
+          c, &bp, &locale::get_weekday_name, 7, &tm->tm_wday, &found
+        );
+        if ( !found )
+          locale_find( c, &bp, &locale::get_weekday_abbr, 7, &tm->tm_wday );
+        *set_fields |= set_wday;
+        break;
+
+      case 'b': // abbreviated month name
+      case 'B': // full month name
+      case 'h': // same as %b
+        CHECK_ALT(0);
+        locale_find( c, &bp, &locale::get_month_name, 12, &tm->tm_mon, &found );
+        if ( !found )
+          locale_find( c, &bp, &locale::get_month_abbr, 12, &tm->tm_mon );
+        *set_fields |= set_mon;
+        break;
+
+      case 'c': // date and time
+        CHECK_ALT(ALT_E);
+        recurse_fmt = locale::get_date_time_format();
+        goto recurse;
+
+      case 'C': // century number
+        CHECK_ALT(ALT_E);
+        parse_num( c, &bp, 0, 99, &n );
+        n = n * 100 - TM_YEAR_BASE;
+        if ( split_year )
+          n += tm->tm_year % 100;
+        else
+          split_year = true;
+        tm->tm_year = n;
+        *set_fields |= set_year;
+        break;
+
+      case 'D':
+        CHECK_ALT(0);
+        recurse_fmt = "%m/%d/%y";
+        goto recurse;
+
+      case 'd': // day of month: 01-31
+      case 'e': // day of month: 1-31
+        CHECK_ALT(ALT_O);
+        parse_num( c, &bp, 1, 31, &tm->tm_mday );
+        *set_fields |= set_mday;
+        break;
+
+      case 'E': // "%E?" alternative conversion modifier
+        alt_format = ALT_E;
+        goto again;
+
+      case 'F':
+        CHECK_ALT(0);
+        recurse_fmt = "%Y-%m-%d";
+        goto recurse;
+
+      case 'H': // hour: 00-23
+        CHECK_ALT(ALT_O);
+case_H: parse_num( c, &bp, 0, 23, &tm->tm_hour );
+        *set_fields |= set_hour;
+        break;
+
+      case 'I': // hour: 01-12
+        CHECK_ALT(ALT_O);
+case_I: parse_num( c, &bp, 1, 12, &tm->tm_hour );
+        if ( tm->tm_hour == 12 )
+          tm->tm_hour = 0;              // assume AM until %p
+        *set_fields |= set_hour;
+        break;
+
+      case 'j': // day of year: 001-366
+        CHECK_ALT(0);
+        parse_num( c, &bp, 1, 366, &n );
+        tm->tm_yday = n - 1;
+        *set_fields |= set_yday;
+        break;
+
+      case 'k': // hour: 0-23
+        CHECK_ALT(0);
+        goto case_H;
+
+      case 'l': // hour: 1-12
+        CHECK_ALT(0);
+        goto case_I;
+
+      case 'm': // month: 01-12
+        CHECK_ALT(ALT_O);
+        parse_num( c, &bp, 1, 12, &n );
+        tm->tm_mon = n - 1;
+        *set_fields |= set_mon;
+        break;
+
+      case 'M': // minute: 00-59
+        CHECK_ALT(ALT_O);
+        parse_num( c, &bp, 0, 59, &tm->tm_min );
+        *set_fields |= set_min;
+        break;
+
+      case 'n': // newline
+      case 't': // tab
+        CHECK_ALT(0);
+        bp = ascii::trim_start_whitespace( bp );
+        break;
+
+      case 'O': // "%O?" alternative conversion modifier
+        alt_format = ALT_O;
+        goto again;
+
+      case 'p': // AM/PM
+        CHECK_ALT(0);
+        locale_find( c, &bp, &get_time_ampm, 2, &n );
+        if ( tm->tm_hour > 11 )
+          throw invalid_value( tm->tm_hour, "Il" );
+        if ( n /* i.e., PM */ )
+          tm->tm_hour += 12;
+        break;
+
+      case 'r':
+        CHECK_ALT(0);
+        recurse_fmt = "%I:%M:%S %p";
+        goto recurse;
+
+      case 'R':
+        CHECK_ALT(0);
+        recurse_fmt = "%H:%M";
+        goto recurse;
+
+      case 'S': // seconds: 00-60 (60 for leap second)
+        CHECK_ALT(ALT_O);
+        parse_num( c, &bp, 0, 60, &tm->tm_sec );
+        *set_fields |= set_sec;
+        break;
+
+#if 0
+      case 's': // number of seconds since epoch
+        break;
+#endif
+
+      case 'T':
+        CHECK_ALT(0);
+        recurse_fmt = "%H:%M:%S";
+        goto recurse;
+
+      case 'u': // day of week, beginning on Monday: 1-7
+        CHECK_ALT(ALT_O);
+        parse_num( c, &bp, 1, 7, &n );
+        tm->tm_wday = n - 1;
+        *set_fields |= set_wday;
+        break;
+
+      case 'v':
+        CHECK_ALT(0);
+        recurse_fmt = "%e-%b-%Y";
+        goto recurse;
+
+      case 'V': // week of year, beginning on Monday: 01-53
+        CHECK_ALT(ALT_O);
+        //
+        // This is bogus since we can not assume any valid information present
+        // in the tm structure at this point to calculate a real value, so just
+        // check the range for now.
+        //
+        parse_num( c, &bp, 1, 53, &n );
+        break;
+
+      case 'U': // week of year, beginning on Sunday: 00-53
+      case 'W': // week of year, beginning on Monday: 00-53
+        CHECK_ALT(ALT_O);
+        //
+        // This is bogus since we can not assume any valid information present
+        // in the tm structure at this point to calculate a real value, so just
+        // check the range for now.
+        //
+        parse_num( c, &bp, 0, 53, &n );
+        break;
+
+      case 'w': // day of week, beginning on Sunday: 0-6
+        CHECK_ALT(ALT_O);
+        parse_num( c, &bp, 0, 6, &tm->tm_wday );
+        *set_fields |= set_wday;
+        break;
+
+      case 'x': // date
+        CHECK_ALT(ALT_E);
+        recurse_fmt = locale::get_date_format();
+        goto recurse;
+
+      case 'X': // time
+        CHECK_ALT(ALT_E);
+        recurse_fmt = locale::get_time_format();
+        goto recurse;
+
+      case 'y': // year within 100 years of the epoch
+        CHECK_ALT(ALT_E | ALT_O);
+        parse_num( c, &bp, 0, 99, &n );
+        if ( split_year )               // preserve century
+          n += (tm->tm_year / 100) * 100;
+        else {
+          n += (n <= 68 ? 2000 : 1900) - TM_YEAR_BASE;
+          split_year = true;
+        }
+        tm->tm_year = n;
+        *set_fields |= set_year;
+        break;
+
+      case 'Y': // year: 0-9999
+        CHECK_ALT(ALT_E);
+        parse_num( c, &bp, 0, 9999, &n );
+        tm->tm_year = n - TM_YEAR_BASE;
+        *set_fields |= set_year;
+        break;
+
+      case 'z': { // RFC 2822 timezone offset or name: [+|-]HHMM | ZZZ
+        CHECK_ALT(0);
+        char const *const bp0 = bp;
+        int sign;
+        switch ( *bp ) {
+          case '+': sign =  1; ++bp; break;
+          case '-': sign = -1; ++bp; break;
+          default : sign =  0;
+        }
+        if ( ascii::is_digit( *bp ) ) { // start of HHMM
+          int hour = (*bp - '0') * 10;
+          if ( !ascii::is_digit( *++bp ) )
+            goto bad_tz;
+          hour += *bp - '0';
+          //
+          // We don't need to check the hour because values [-99,99] are legal.
+          //
+          if ( !ascii::is_digit( *++bp ) )
+            goto bad_tz;
+          int minute = (*bp - '0') * 10;
+          if ( !ascii::is_digit( *++bp ) )
+            goto bad_tz;
+          minute += *bp++ - '0';
+          if ( minute > 59 )
+            goto bad_tz;
+          long gmtoff = hour * 60 * 60 + minute * 60;
+          if ( sign )
+            gmtoff *= sign;
+          tm->ZTM_GMTOFF = gmtoff;
+          tm->tm_isdst = 0;
+          *set_fields |= set_gmtoff;
+          break;
+        } else if ( sign )              // sign followed by non-digit
+bad_tz:   throw invalid_value( bp0, 4 + !!sign, c );
+        // no break;
+      } // case 'z'
+
+      case 'Z': { // RFC 2822 timezone name only: ZZZ
+        CHECK_ALT(0);
+        for ( rfc2822_obs_zone const *z = rfc2822_obs_zones; z->name; ++z ) {
+          size_t const len = ::strlen( z->name );
+          if ( ::strncmp( bp, z->name, len ) == 0 ) {
+            tm->ZTM_GMTOFF = z->gmtoff;
+            tm->tm_isdst = z->isdst;
+            *set_fields |= set_gmtoff;
+            bp += len;
+            goto next_outer_loop;
+          }
+        }
+        throw invalid_value( bp, 3 /* assume */, c );
+      } // case 'Z'
+
+      default: // unknown/unsupported conversion
+        throw invalid_specification( c );
+    } // switch
+
+next_outer_loop:
+    continue;
+
+recurse:
+    bp = strptime_impl( bp, recurse_fmt, tm, set_fields );
+  } // while
+
+  if ( bits_set( *set_fields, set_mday | set_mon | set_year ) ) {
+    int const year = TM_YEAR_BASE + tm->tm_year;
+    if ( !is_mday_valid( tm->tm_mday, tm->tm_mon, year ) )
+      throw invalid_value( tm->tm_mday, "de" );
+    if ( (*set_fields & set_wday) &&
+         !is_wday_valid( tm->tm_wday, tm->tm_mday, tm->tm_mon, year ) )
+      throw invalid_value( tm->tm_wday, "uw" );
+    if ( (*set_fields & set_yday) &&
+         !is_yday_valid( tm->tm_yday, tm->tm_mday, tm->tm_mon, year ) )
+      throw invalid_value( tm->tm_yday, 'j' );
+  }
+
+  return bp;
+}
+
+char const* strptime( char const *buf, char const *fmt, ztm *tm,
+                      unsigned *set_fields ) {
+  unsigned local_fields;
+  if ( !set_fields )
+    set_fields = &local_fields;
+  *set_fields = 0;
+  return strptime_impl( buf, fmt, tm, set_fields );
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+} // namespace time
+} // namespace zorba
+/* vim:set et sw=2 ts=2: */

=== added file 'src/util/strptime.h'
--- src/util/strptime.h	1970-01-01 00:00:00 +0000
+++ src/util/strptime.h	2013-01-02 14:49:24 +0000
@@ -0,0 +1,432 @@
+/*
+ * Copyright 2006-2008 The FLWOR Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ZORBA_STRPTIME_H
+#define ZORBA_STRPTIME_H
+
+// standard
+#include <stdexcept>
+
+// Zorba
+#include <zorba/config.h>
+#include "cxx_util.h"
+#include "string_util.h"
+#include "time_util.h"
+
+namespace zorba {
+namespace time {
+
+///////////////////////////////////////////////////////////////////////////////
+
+/**
+ * An %exception is the root of strptime %exception hierarchy.
+ */
+class exception : public std::runtime_error {
+public:
+  ~exception() throw();
+protected:
+  exception( std::string const &msg );
+};
+
+/**
+ * This exception is thrown when the buffer is exhausted before the format
+ * string.
+ */
+class insufficient_buffer : public exception {
+public:
+  insufficient_buffer();
+};
+
+/**
+ * This exception is thrown when an invalid conversion specification is given,
+ * i.e., an invalid character after a \c %.
+ */
+class invalid_specification : public std::invalid_argument {
+public:
+  invalid_specification( char spec );
+  ~invalid_specification() throw();
+
+  /**
+   * Gets the invalid specification.
+   *
+   * @return Returns said specification character.
+   */
+  char get_spec() const {
+    return spec_;
+  }
+
+private:
+  char spec_;
+};
+
+/**
+ * This is a helper class for invalid_value.
+ */
+class invalid_value_specs {
+protected:
+  invalid_value_specs( char spec );
+  invalid_value_specs( char const *specs );
+
+  std::string specs_;
+};
+
+/**
+ * This is a helper class for invalid_value.
+ */
+class invalid_value_value {
+protected:
+  invalid_value_value( char c );
+  invalid_value_value( char const *buf, size_t len );
+
+  template<typename ValueType>
+  invalid_value_value( ValueType const &value );
+
+  std::string value_;
+};
+
+/**
+ * This exception is thrown when an invalid value for a given specification was
+ * given.
+ */
+class invalid_value :
+  protected invalid_value_value,
+  protected invalid_value_specs,
+  public exception {
+public:
+  invalid_value( char const *buf, size_t len, char spec );
+  invalid_value( char const *buf, size_t len, char const *specs );
+
+  template<typename ValueType>
+  invalid_value( ValueType const &value, char spec );
+
+  template<typename ValueType>
+  invalid_value( ValueType const &value, char const *specs );
+
+  ~invalid_value() throw();
+
+  /**
+   * Gets the conversion specification character(s) the value is invalid for.
+   *
+   * @return Returns said character(s).
+   */
+  std::string const& get_specs() const {
+    return specs_;
+  }
+
+  /**
+   * Gets the invalid value.
+   *
+   * @return Returns said value.
+   */
+  std::string const& get_value() const {
+    return value_;
+  }
+
+private:
+  static std::string build_msg( std::string const &value,
+                                std::string const &specs );
+};
+
+/**
+ * This exception is thrown when a literal character in the \a buf parameter of
+ * the strptime() function does not match is corresponding character in the
+ * \a fmt parameter.
+ */
+class literal_mismatch : public exception {
+public:
+  literal_mismatch( char expected, char got );
+  ~literal_mismatch() throw();
+
+  /**
+   * Gets the character that was expected.
+   *
+   * @return Returns said character.
+   */
+  char get_expected() const {
+    return expected_;
+  }
+
+  /**
+   * Gets the character that was actually gotten.
+   *
+   * @return Returns said character.
+   */
+  char get_got() const {
+    return got_;
+  }
+
+private:
+  char expected_;
+  char got_;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+
+//
+// The bit-wise-or of these constants comprise the value returned by the
+// set_fields parameter of the strptime() function.
+//
+unsigned const set_gmtoff = 0x001;      // minutes: 0-59
+unsigned const set_hour   = 0x002;      // hour: 0-23
+unsigned const set_mday   = 0x004;      // month day: 1-{28,29,30,31}
+unsigned const set_min    = 0x008;      // minutes: 0-59
+unsigned const set_mon    = 0x010;      // month: 0-11
+unsigned const set_sec    = 0x020;      // seconds: 0-60
+unsigned const set_wday   = 0x040;      // weekday: 0-6
+unsigned const set_yday   = 0x080;      // day of the year: 0-365
+unsigned const set_year   = 0x100;
+
+/**
+ * Parses the string in the buffer according to the given format and fills in
+ * the given \c tm structure.
+ *
+ * @param buf The buffer to parse.
+ * @param fmt The format string containing zero or more directives. Each
+ * specification is of one of the following:
+ *  - one or more white-space characters
+ *  - an ordinary character (neither \c '%' nor a whitespace character)
+ *  - a conversion specification
+ * All whitespace characters in \a fmt match one or more whitespace characters
+ * in \a buf.
+ * Every ordinary character in \a fmt must exactly match the same character in
+ * the same position in \a buf.
+ * A conversion specification is composed of a \c '%' character followed by a
+ * conversion character that specifies the replacement required.  The following
+ * conversion specifications are supported:
+ *  <table>
+ *    <tr>
+ *      <td>%a</td>
+ *      <td>
+ *        The day of the week using the locale's weekday names;
+ *        either the abbreviated or full name may be specified.
+ *      </td>
+ *    </tr>
+ *    <tr>
+ *      <td>%A</td>
+ *      <td>Same as \c %a.</td>
+ *    </tr>
+ *    <tr>
+ *      <td>%b</td>
+ *      <td>
+ *        The month using the locale's month names;
+ *        either the abbreviated or full name may be specified.
+ *      </td>
+ *    </tr>
+ *    <tr>
+ *      <td>%B</td>
+ *      <td>Same as \c %a.</td>
+ *    </tr>
+ *    <tr>
+ *      <td>%c</td>
+ *      <td>
+ *        The locale's appropriate date and time representation.
+ *      </td>
+ *    </tr>
+ *    <tr>
+ *      <td>%C</td>
+ *      <td>
+ *        The century number [00,99]; leading zeros are permitted but not
+ *        required.
+ *      </td>
+ *    </tr>
+ *    <tr>
+ *      <td>%d</td>
+ *      <td>
+ *        The day of the month [01,31]; leading zeros are permitted but not
+ *        required.
+ *      </td>
+ *    </tr>
+ *    <tr>
+ *      <td>%D</td>
+ *      <td>Same as <code>%m/%d/%y</code>.</td>
+ *    </tr>
+ *    <tr>
+ *      <td>%e</td>
+ *      <td>Same as \c %d.</td>
+ *    </tr>
+ *    <tr>
+ *      <td>%h</td>
+ *      <td>Same as \c %b.</td>
+ *    </tr>
+ *    <tr>
+ *      <td>%H</td>
+ *      <td>
+ *        The hour (24-hour clock) [00,23]; leading zeros are permitted but not
+ *        required.
+ *      </td>
+ *    </tr>
+ *    <tr>
+ *      <td>%I</td>
+ *      <td>
+ *        The hour (12-hour clock) [01,12]; leading zeros are permitted but not
+ *        required.
+ *      </td>
+ *    </tr>
+ *    <tr>
+ *      <td>%j</td>
+ *      <td>
+ *        The day number of the year [001,366]; leading zeros are permitted but
+ *        not required.
+ *      </td>
+ *    </tr>
+ *    <tr>
+ *      <td>%m</td>
+ *      <td>
+ *        The month number [01,12]; leading zeros are permitted but not
+ *        required.
+ *      </td>
+ *    </tr>
+ *    <tr>
+ *      <td>%M</td>
+ *      <td>
+ *        The minute [00,59]; leading zeros are permitted but not required.
+ *      </td>
+ *    </tr>
+ *    <tr>
+ *      <td>%n</td>
+ *      <td>Any whitespace.</td>
+ *    </tr>
+ *    <tr>
+ *      <td>%p</td>
+ *      <td>
+ *        The locale's equivalent of \c AM or \c PM.
+ *      </td>
+ *    </tr>
+ *    <tr>
+ *      <td>%r</td>
+ *      <td>
+ *        The 12-hour clock time using the AM/PM notation.
+ *      </td>
+ *    </tr>
+ *    <tr>
+ *      <td>%R</td>
+ *      <td>Same as <code>%H:%M</code>.</td>
+ *    </tr>
+ *    <tr>
+ *      <td>%S</td>
+ *      <td>
+ *        The seconds [00,60]; leading zeros are permitted but not required.
+ *      </td>
+ *    </tr>
+ *    <tr>
+ *      <td>%t</td>
+ *      <td>Any whitespace.</td>
+ *    </tr>
+ *    <tr>
+ *      <td>%T</td>
+ *      <td>Same as <code>%H:%M:%S</code>.</td>
+ *    </tr>
+ *    <tr>
+ *      <td>%U</td>
+ *      <td>
+ *        The week number of the year (Sunday as the first day of the week)
+ *        [00,53]; leading zeros are permitted but not required.
+ *      </td>
+ *    <tr>
+ *      <td>%w</td>
+ *      <td>
+ *        The weekday [0,6] with 0 representing Sunday; leading zeros are
+ *        permitted but not required.
+ *      </td>
+ *    </tr>
+ *    <tr>
+ *      <td>%W</td>
+ *      <td>
+ *        The week number of the year (Monday as the first day of the week)
+ *        [00,53]; leading zeros are permitted but not required.
+ *      </td>
+ *    </tr>
+ *    <tr>
+ *      <td>%x</td>
+ *      <td>
+ *        The date using the locale's date format.
+ *      </td>
+ *    </tr>
+ *    <tr>
+ *      <td>%X</td>
+ *      <td>
+ *        The time using the locale's time format.
+ *      </td>
+ *    </tr>
+ *    <tr>
+ *      <td>%y</td>
+ *      <td>
+ *        The year within century. When a century is not otherwise specified
+ *        (via \c %C), values in the range [69,99] shall refer to years 1969 to
+ *        1999 and values in the range [00,68] shall refer to years 2000 to
+ *        2068; leading zeros are permitted but not required.
+ *      </td>
+ *    </tr>
+ *    <tr>
+ *      <td>%Y</td>
+ *      <td>
+ *        The year including the century (for example, 1988).
+ *      </td>
+ *    </tr>
+ *    <tr>
+ *      <td>%%</td>
+ *      <td>Literal \c %.</td>
+ *    </tr>
+ *  </table>
+ * @param tm The tm structure to fill in.
+ * @param set_fields If not null, this is set to the bit-wise-or of the tm
+ * structure fields that have been set.
+ * @return Returns a pointer to the first character in \a buf past the last
+ * character parsed.
+ * @throws insufficient_buffer if \a buf is insufficient for \a fmt.
+ * @throws invalid_specification if \a fmt contains an invalid character
+ * following \c %
+ * @throws invalid_value if \a buf contains an invalid value for a
+ * specification.
+ * @throws literal_mismatch if a literal character in \a buf does not match is
+ * corresponding character in \a fmt.
+ */
+char const* strptime( char const *buf, char const *fmt, ztm *tm,
+                      unsigned *set_fields = nullptr );
+
+//
+// Template version of strptime().
+//
+template<class BufferType> inline
+typename std::enable_if<
+  ztd::has_c_str<BufferType,char const* (BufferType::*)() const>::value,
+  char const*
+>::type
+strptime( BufferType const &buf, char const *fmt, ztm *tm,
+          unsigned *set_fields = nullptr ) {
+  return time::strptime( buf.c_str(), fmt, tm, set_fields );
+}
+
+//
+// Template version of strptime().
+//
+template<class BufferType,class FormatType> inline
+typename std::enable_if<
+  ztd::has_c_str<BufferType,char const* (BufferType::*)() const>::value &&
+  ztd::has_c_str<FormatType,char const* (FormatType::*)() const>::value,
+  char const*
+>::type
+strptime( BufferType const &buf, FormatType const &fmt, ztm *tm,
+          unsigned *set_fields = nullptr ) {
+  return time::strptime( buf.c_str(), fmt.c_str(), tm, set_fields );
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+} // namespace time
+} // namespace zorba
+#endif /* ZORBA_STRPTIME_H */
+/* vim:set et sw=2 ts=2: */

=== added file 'src/util/time_util.cpp'
--- src/util/time_util.cpp	1970-01-01 00:00:00 +0000
+++ src/util/time_util.cpp	2013-01-02 14:49:24 +0000
@@ -0,0 +1,202 @@
+/*
+ * Copyright 2006-2008 The FLWOR Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <cassert>
+#ifdef WIN32
+# include <windows.h>
+# if defined(_MSC_VER) || defined(_MSC_EXTENSIONS)
+#   define DELTA_EPOCH_IN_USEC 11644473600000000Ui64
+# else
+#   define DELTA_EPOCH_IN_USEC 11644473600000000ULL
+# endif
+#else
+# include <ctime>
+# include <sys/time.h>
+#endif /* WIN32 */
+
+// local
+#include "time_util.h"
+
+namespace zorba {
+namespace time {
+
+///////////////////////////////////////////////////////////////////////////////
+
+static unsigned const yday_mon[][13] = {
+  // 0   1   2   3    4    5    6    7    8    9   10   11   12
+  {  0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 },  // non-leap
+  {  0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }   // leap
+};
+
+///////////////////////////////////////////////////////////////////////////////
+
+bool calc_mday_mon( unsigned yday, unsigned *mday, unsigned *mon,
+                    unsigned year ) {
+  assert( yday < 365 + is_leap_year( year ) );
+
+  unsigned const *const ym = yday_mon[ is_leap_year( year ) ];
+  for ( unsigned m = 1; m <= 12; ++m ) 
+    if ( ym[ m ] > yday ) {
+      --m;
+      if ( mday )
+        *mday = yday - ym[ m ] + 1;
+      if ( mon )
+        *mon = m;
+      return true;
+    }
+  return false;
+}
+
+/**
+ * Tondering's algorithm for calculating the weekday given a date; see:
+ * http://www.tondering.dk/claus/calendar.html
+ *
+ * COPYRIGHT:
+ *   These functions are Copyright (c) 2008 by Claus Tondering
+ *   (claus@xxxxxxxxxxxx).
+ *  
+ * LICENSE:
+ *   The code is distributed under the Boost Software License, which
+ *   says:
+ *  
+ *     Boost Software License - Version 1.0 - August 17th, 2003
+ *  
+ *     Permission is hereby granted, free of charge, to any person or
+ *     organization obtaining a copy of the software and accompanying
+ *     documentation covered by this license (the "Software") to use,
+ *     reproduce, display, distribute, execute, and transmit the
+ *     Software, and to prepare derivative works of the Software, and
+ *     to permit third-parties to whom the Software is furnished to do
+ *     so, all subject to the following:
+ *  
+ *     The copyright notices in the Software and this entire
+ *     statement, including the above license grant, this restriction
+ *     and the following disclaimer, must be included in all copies of
+ *     the Software, in whole or in part, and all derivative works of
+ *     the Software, unless such copies or derivative works are solely
+ *     in the form of machine-executable object code generated by a
+ *     source language processor.
+ *  
+ *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
+ *     NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
+ *     ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE FOR ANY DAMAGES OR
+ *     OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ *     ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ *     USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * @param mday Month day: 1-31.
+ * @param mon Month: 0-11.
+ * @param year Year.
+ * @return Returns the weekday where 0 = Sunday.
+ */
+unsigned calc_wday( unsigned mday, unsigned mon, unsigned year ) {
+  assert( mday >= 1 );
+  assert( mday <= days_in_month( mon, year ) );
+  assert( mon < 12 );
+
+  ++mon; // Tondering's algorithm assumes month value in range 1-12.
+  unsigned const a = (14 - mon) / 12;
+  unsigned const y = year - a;
+  unsigned const m = mon + 12 * a - 2;
+  return (mday + y + y/4 - y/100 + y/400 + (31 * m) / 12) % 7;
+}
+
+unsigned calc_yday( unsigned mday, unsigned mon, unsigned year ) {
+  assert( mday >= 1 );
+  assert( mday <= days_in_month( mon, year ) );
+  return yday_mon[ is_leap_year( year ) ][ mon ] + mday - 1;
+}
+
+unsigned days_in_month( unsigned mon, unsigned year ) {
+  static unsigned const days[] = {
+    31, //  0: Jan
+    28, //  1: Feb
+    31, //  2: Mar
+    30, //  3: Apr
+    31, //  4: May
+    30, //  5: Jun
+    31, //  6: Jul
+    31, //  7: Aug
+    30, //  8: Sep
+    31, //  9: Oct
+    30, // 10: Nov
+    31  // 11: Dec
+  };
+  assert( mon < 12 );
+  return days[ mon ] + (mon == 1 /* Feb */ && is_leap_year( year ));
+}
+
+void get_epoch( time_t *sec, usec_type *usec ) {
+#ifdef WIN32
+  FILETIME ft;
+  GetSystemTimeAsFileTime( &ft );
+  unsigned __int64 temp = (ft.dwHighDateTime << 32) | ft.dwLowDateTime;
+  temp /= 10;                           // nanosec -> usec
+  temp -= DELTA_EPOCH_IN_USEC;          // 1601 -> 1970
+  *sec = (time_t)(temp / 1000000UL);    // usec -> sec
+  if ( usec )
+    *usec = (usec_type)(temp % 1000000UL);
+#else
+  timeval tv;
+  ::gettimeofday( &tv, nullptr );
+  *sec = tv.tv_sec;
+  if ( usec )
+    *usec = tv.tv_usec;
+#endif /* WIN32 */
+}
+
+void get_gmtime( ztm *tm, time_t when ) {
+  if ( !when )
+    get_epoch( &when );
+#ifdef WIN32
+  ::_gmtime_s( tm, &when );
+  tm->ZTM_GMTOFF = 0;
+#else
+  ::gmtime_r( &when, tm );
+#endif /* WIN32 */
+}
+
+void get_localtime( ztm *tm, time_t when ) {
+  if ( !when )
+    get_epoch( &when );
+#ifdef WIN32
+  ::localtime_s( tm, &when );
+  tm->ZTM_GMTOFF = - _timezone;         // seconds west -> east
+#else
+  ::localtime_r( &when, tm );
+#endif /* WIN32 */
+}
+
+long get_gmt_offset() {
+#ifdef WIN32
+  TIME_ZONE_INFORMATION tz;
+  GetTimeZoneInformation( &tz );
+  return tz.Bias * -60;                 // minutes west -> seconds east
+#else
+  time_t const now = ::time( nullptr );
+  ztm tm;
+  ::localtime_r( &now, &tm );
+  return ::timegm( &tm ) - now;
+#endif /* WIN32 */
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+} // namespace time
+} // namespace zorba
+/* vim:set et sw=2 ts=2: */

=== added file 'src/util/time_util.h'
--- src/util/time_util.h	1970-01-01 00:00:00 +0000
+++ src/util/time_util.h	2013-01-02 14:49:24 +0000
@@ -0,0 +1,205 @@
+/*
+ * Copyright 2006-2008 The FLWOR Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ZORBA_TIME_UTIL_H
+#define ZORBA_TIME_UTIL_H
+
+// standard
+#include <ctime>                        /* for struct tm */
+#ifdef ZORBA_HAVE_TZFILE_H
+# include <tzfile.h>                    /* for TM_YEAR_BASE */
+#endif /* ZORBA_HAVE_TZFILE_H */
+
+// Zorba
+#include <zorba/config.h>
+#include "cxx_util.h"
+
+#ifndef TM_YEAR_BASE
+# define TM_YEAR_BASE 1900
+#endif
+
+namespace zorba {
+namespace time {
+
+///////////////////////////////////////////////////////////////////////////////
+
+#ifdef WIN32
+typedef unsigned long usec_type;
+#else
+typedef suseconds_t usec_type;
+#endif /* WIN32 */
+
+//
+// If the OS's tm struct has a GMT-timezone offset field, simply typedef tm as
+// ztm; otherwise declare ztm as a struct derived from tm that adds a
+// GMT-timezone offset field.
+//
+#if defined(ZORBA_HAVE_STRUCT_TM_TM_GMTOFF) || \
+    defined(ZORBA_HAVE_STRUCT_TM___TM_GMTOFF)
+typedef struct tm ztm;
+#else
+struct ztm : tm {
+  long tm_gmtoff;
+};
+#endif
+
+//
+// Always use this macro to access the tm_gmtoff field of the tm struct since
+// its name varies across plattorms.
+//
+#ifdef ZORBA_HAVE_STRUCT_TM___TM_GMTOFF
+# define ZTM_GMTOFF __tm_gmtoff
+#else
+# define ZTM_GMTOFF tm_gmtoff
+#endif
+
+///////////////////////////////////////////////////////////////////////////////
+
+/**
+ * Calculates the day of the month and month from the given day of the year.
+ *
+ * @param yday The year day (0-365) where 0 = January 1.
+ * @param mday A pointer to the result for the month day (1-31) or \c null if
+ * this is not desired.
+ * @param mon A pointer to the result for the month (0-11) or \c null if this
+ * is not desired.
+ * @param year The year.
+ * @return Returns \c true if \a yday and \a year are a valid combination and
+ * a result is yielded.
+ */
+bool calc_mday_mon( unsigned yday, unsigned *mday, unsigned *mon,
+                    unsigned year );
+
+/**
+ * Calculates the weekday for the given date.
+ *
+ * @param mday The month day (1-31).
+ * @param mon The month (0-11).
+ * @param year The year.
+ * @return Returns the weekday (0-6) where 0 = Sunday.
+ */
+unsigned calc_wday( unsigned mday, unsigned mon, unsigned year );
+
+/**
+ * Calculates the day of the year for the given date.
+ *
+ * @param mday The month day (1-31).
+ * @param mon The month (0-11).
+ * @param year The year.
+ * @return Returns the day of the year (0-365) where 0 = January 1.
+ */
+unsigned calc_yday( unsigned mday, unsigned mon, unsigned year );
+
+/**
+ * Gets the number of days in the given month.
+ *
+ * @param mon The month (0-11).
+ * @param year The year.
+ * @return Returns said number of days (1-31).
+ */
+unsigned days_in_month( unsigned mon, unsigned year );
+
+/**
+ * Gets the number of seconds and microseconds since epoch.
+ *
+ * @param sec A pointer to the result in seconds.
+ * @param usec A pointer to the result in microseconds or \c null if this is
+ * not desired.
+ */
+void get_epoch( time_t *sec, usec_type *usec = nullptr );
+
+/**
+ * Gets the Greenwich time and populates the given ztm structure.
+ *
+ * @param tm A pointer to the ztm struct to populate.
+ * @param when If &gt; 0, populates \a tm based on \a when number of seconds
+ * since \e epoch; if 0, populates \a when based on \e now.
+ */
+void get_gmtime( ztm *tm, time_t when = 0 );
+
+/**
+ * Gets the offset of the current timezone from Greenwich time.
+ *
+ * @return Returns the offset in seconds with positive values being east of the
+ * prime meridian.
+ */
+long get_gmt_offset();
+
+/**
+ * Gets the local time and populates the given ztm structure.
+ *
+ * @param tm A pointer to the ztm struct to populate.
+ * @param when If &gt; 0, populates \a tm based on \a when number of seconds
+ * since \e epoch; if 0, populates \a when based on \e now.
+ */
+void get_localtime( ztm *tm, time_t when = 0 );
+
+/**
+ * Checks whether the given year is a leap year.
+ *
+ * @param year The year to check.
+ * @return Returns \c true only if \a year is a leap year.
+ */
+inline bool is_leap_year( unsigned year ) {
+  return !(year % 4) && ((year % 100) || !(year % 400));
+}
+
+/**
+ * Checks whether the given day of the month is valid.
+ *
+ * @param mday The month day (1-31).
+ * @param mon The month (0-11).
+ * @param year The year.
+ * @return Returns \a true only if the given day of the month is valid.
+ */
+inline bool is_mday_valid( unsigned mday, unsigned mon, unsigned year ) {
+  return mday >= 1 && mday <= days_in_month( mon, year );
+}
+
+/**
+ * Checks whether the given weekday is valid.
+ *
+ * @param wday The weekday (0-6) where 0 = Sunday.
+ * @param mday The month day (1-31).
+ * @param mon The month (0-11).
+ * @param year The year.
+ * @return Returns \a true only if the given weekday is valid.
+ */
+inline bool is_wday_valid( unsigned wday, unsigned mday, unsigned mon,
+                           unsigned year ) {
+  return wday == calc_wday( mday, mon, year );
+}
+
+/**
+ * Checks whether the given day of the year is valid.
+ *
+ * @param yday The day of the year (0-365).
+ * @param mday The month day (1-31).
+ * @param mon The month (0-11).
+ * @param year The year.
+ * @return Returns \a true only if the given day of the year is valid.
+ */
+inline bool is_yday_valid( unsigned yday, unsigned mday, unsigned mon,
+                           unsigned year ) {
+  return yday == calc_yday( mday, mon, year );
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+} // namespace time
+} // namespace zorba
+#endif /* ZORBA_TIME_UTIL_H */
+/* vim:set et sw=2 ts=2: */

=== modified file 'src/zorbautils/locale.cpp'
--- src/zorbautils/locale.cpp	2012-09-19 21:16:15 +0000
+++ src/zorbautils/locale.cpp	2013-01-02 14:49:24 +0000
@@ -21,17 +21,22 @@
 #else
 # include <clocale>
 # include <cstdlib>                     /* for getenv(3) */
+# include <langinfo.h>                  /* for nl_langinfo(3) */
 #endif /* WIN32 */
 
 #include <algorithm>
 #include <cstring>
+#include <stdexcept>
 
 #include <zorba/internal/unique_ptr.h>
 
+// Zorba
 #include "util/cxx_util.h"
 #include "util/less.h"
 #include "util/stl_util.h"
+#include "util/string_util.h"
 
+// local
 #include "locale.h"
 
 #define DEF_END(CHAR_ARRAY)                             \
@@ -46,6 +51,59 @@
 namespace zorba {
 namespace locale {
 
+#ifdef WIN32
+typedef LCTYPE locale_index;
+#else
+typedef nl_item locale_index;
+#endif /* WIN32 */
+
+///////////////////////////////////////////////////////////////////////////////
+
+static locale_index const month_abbr[] = {
+#ifdef WIN32
+  LOCALE_SABBREVMONTHNAME1, LOCALE_SABBREVMONTHNAME2,
+  LOCALE_SABBREVMONTHNAME3, LOCALE_SABBREVMONTHNAME4,
+  LOCALE_SABBREVMONTHNAME5, LOCALE_SABBREVMONTHNAME6,
+  LOCALE_SABBREVMONTHNAME7, LOCALE_SABBREVMONTHNAME8,
+  LOCALE_SABBREVMONTHNAME9, LOCALE_SABBREVMONTHNAME10,
+  LOCALE_SABBREVMONTHNAME11, LOCALE_SABBREVMONTHNAME12
+#else
+  ABMON_1, ABMON_2, ABMON_3, ABMON_4, ABMON_5, ABMON_6,
+  ABMON_7, ABMON_8, ABMON_9, ABMON_10, ABMON_11, ABMON_12
+#endif /* WIN32 */
+};
+
+static locale_index const month_name[] = {
+#ifdef WIN32
+  LOCALE_SMONTHNAME1, LOCALE_SMONTHNAME2, LOCALE_SMONTHNAME3,
+  LOCALE_SMONTHNAME4, LOCALE_SMONTHNAME5, LOCALE_SMONTHNAME6,
+  LOCALE_SMONTHNAME7, LOCALE_SMONTHNAME8, LOCALE_SMONTHNAME9,
+  LOCALE_SMONTHNAME10, LOCALE_SMONTHNAME11, LOCALE_SMONTHNAME12
+#else
+  MON_1, MON_2, MON_3, MON_4, MON_5, MON_6,
+  MON_7, MON_8, MON_9, MON_10, MON_11, MON_12
+#endif /* WIN32 */
+};
+
+static locale_index const weekday_abbr[] = {
+#ifdef WIN32
+  LOCALE_SABBREVDAYNAME1, LOCALE_SABBREVDAYNAME2, LOCALE_SABBREVDAYNAME3,
+  LOCALE_SABBREVDAYNAME4, LOCALE_SABBREVDAYNAME5, LOCALE_SABBREVDAYNAME6,
+  LOCALE_SABBREVDAYNAME7
+#else
+  ABDAY_1, ABDAY_2, ABDAY_3, ABDAY_4, ABDAY_5, ABDAY_6, ABDAY_7
+#endif /* WIN32 */
+};
+
+static locale_index const weekday_name[] = {
+#ifdef WIN32
+  LOCALE_SDAYNAME1, LOCALE_SDAYNAME2, LOCALE_SDAYNAME3, LOCALE_SDAYNAME4,
+  LOCALE_SDAYNAME5, LOCALE_SDAYNAME6, LOCALE_SDAYNAME7
+#else
+  DAY_1, DAY_2, DAY_3, DAY_4, DAY_5, DAY_6, DAY_7
+#endif /* WIN32 */
+};
+
 ///////////////////////////////////////////////////////////////////////////////
 
 /**
@@ -849,6 +907,100 @@
   return iso639_2_to_639_1[ iso639_2::find( lang ) ];
 }
 
+char const* get_date_format() {
+#ifdef WIN32
+  static string format;
+  if ( format.empty() ) {
+    unique_ptr<char[]> const w32_format(
+      get_win32_locale_info( LOCALE_SSHORTDATE )
+    );
+    //
+    // Convert Windows' date format for that used by strptime(3); see:
+    // http://msdn.microsoft.com/en-us/library/windows/desktop/dd317787(v=vs.85).aspx
+    //
+    for ( char const *buf = w32_format.get(); *buf; ++buf ) {
+      char const c = *buf;
+      switch ( c ) {
+
+        case 'd':
+          if ( buf[1] == c )
+            if ( buf[2] == c )
+              if ( buf[3] == c )
+                format += "%A", buf += 3; // dddd = full weekday name
+              else
+                format += "%a", buf += 2; // ddd = abbreviated weekday name
+            else
+              format += "%d", buf += 1;   // dd = day of month: 01-31
+          else
+            format += "%e";               // d = day of month: 1-31
+          break;
+
+        case 'g':                         // period/era
+          //
+          // There's no equivalent strftime(3) conversion specification: just
+          // ignore it and hope for the best.
+          //
+          if ( buf[1] == c )
+            ++buf;                        // gg = same as g
+          break;
+
+        case 'M':
+          if ( buf[1] == c )
+            if ( buf[2] == c )
+              if ( buf[3] == c )
+                format += "%B", buf += 3; // MMMM = full month name
+              else
+                format += "%b", buf += 2; // MMM = abbreviated month name
+            else
+              format += "%m", buf += 1;   // MM = month: 01-12
+          else
+            format += "%m";               // M = month: 1-12
+          break;
+
+        case 'y':
+          if ( buf[1] == c )
+            if ( buf[2] == c )
+              if ( buf[3] == c ) {
+                format += "%Y", buf += 3; // yyyy = 4-digit year
+                if ( buf[3] == c )
+                  ++buf;                  // yyyyy = same as yyyy
+              } else
+                ;
+            else
+              format += "%y", buf += 1;   // yy = 2-digit year
+          else
+            format += "%y";               // y = 1-digit year
+          break;
+
+        default:
+          format += c;
+      } // switch
+    } // for
+  } // if
+  return format.c_str();
+#else
+  return nl_langinfo( D_FMT );
+#endif /* WIN32 */
+}
+
+char const* get_date_time_format() {
+#ifdef WIN32
+  static string format;
+  if ( format.empty() ) {
+    //
+    // Windows have no equivalent for both date and time, so glue its date and
+    // time together and hope for the best.
+    //
+    format = get_date_format();
+    format += ' ';
+    format += get_time_format();
+  }
+  return format.c_str();
+#else
+  return nl_langinfo( D_T_FMT );
+#endif /* WIN32 */
+}
+
 iso3166_1::type get_host_country() {
   //
   // ICU's Locale::getDefault().getLanguage() should be used here, but it
@@ -920,6 +1072,145 @@
   return lang_code;
 }
 
+char const* get_month_abbr( unsigned month_index ) {
+  if ( month_index > 11 )
+    throw invalid_argument(
+      BUILD_STRING( month_index, " not in range 0-11" )
+    );
+#ifdef WIN32
+  static unique_ptr<char[]> month[12];
+  if ( !month[ month_index ] )
+    month[ month_index ].reset(
+      get_win32_locale_info( month_abbr[ month_index ] )
+    );
+  return month[ month_index ].get();
+#else
+  return nl_langinfo( month_abbr[ month_index ] );
+#endif /* WIN32 */
+}
+
+char const* get_month_name( unsigned month_index ) {
+  if ( month_index > 11 )
+    throw invalid_argument(
+      BUILD_STRING( month_index, " not in range 0-11" )
+    );
+#ifdef WIN32
+  static unique_ptr<char[]> month[12];
+  if ( !month[ month_index ] )
+    month[ month_index ].reset(
+      get_win32_locale_info( month_name[ month_index ] )
+    );
+  return month[ month_index ].get();
+#else
+  return nl_langinfo( month_name[ month_index ] );
+#endif /* WIN32 */
+}
+
+char const* get_time_ampm( bool pm ) {
+#ifdef WIN32
+  static unique_ptr<char[]> ampm[2];
+  if ( ampm[ pm ] )
+    ampm[ pm ].reset(
+      get_win32_locale_info( pm ? LOCALE_S2359 : LOCALE_S1159 )
+    );
+  return ampm[ pm ].get();
+#else
+  return nl_langinfo( pm ? PM_STR : AM_STR );
+#endif /* WIN32 */
+}
+
+char const* get_time_format() {
+#ifdef WIN32
+  static string format;
+  if ( format.empty() ) {
+    unique_ptr<char[]> const w32_format(
+      get_win32_locale_info( LOCALE_STIMEFORMAT )
+    );
+    //
+    // Convert Windows' time format for that used by strptime(3); see:
+    // http://msdn.microsoft.com/en-us/library/windows/desktop/dd318148(v=vs.85).aspx
+    //
+    for ( char const *buf = w32_format.get(); *buf; ++buf ) {
+      char const c = *buf;
+      switch ( c ) {
+
+        case 'h':
+          if ( buf[1] == 'h' )
+            format += "%I", ++buf;
+          else
+            format += "%l";
+          break;
+
+        case 'H':
+          if ( buf[1] == 'H' )
+            format += "%H", ++buf;
+          else
+            format += "%k";
+          break;
+
+        case 'm':
+          format += "%M";
+          if ( buf[1] == 'm' )
+            ++buf;
+          break;
+
+        case 's':
+          format += "%S";
+          if ( buf[1] == 's' )
+            ++buf;
+          break;
+
+        case 't':
+          format += "%p";
+          if ( buf[1] == 't' )
+            ++buf;
+          break;
+
+        default:
+          format += c;
+      } // switch
+    } // for
+  } // if
+  return format.c_str();
+#else
+  return nl_langinfo( T_FMT );
+#endif /* WIN32 */
+}
+
+char const* get_weekday_abbr( unsigned day_index ) {
+  if ( day_index > 6 )
+    throw invalid_argument(
+      BUILD_STRING( day_index, " not in range 0-6" )
+    );
+#ifdef WIN32
+  static unique_ptr<char[]> weekday[7];
+  if ( !weekday[ day_index ] )
+    weekday[ day_index ].reset(
+      get_win32_locale_info( weekday_abbr[ day_index ] )
+    );
+  return weekday[ day_index ].get();
+#else
+  return nl_langinfo( weekday_abbr[ day_index ] );
+#endif /* WIN32 */
+}
+
+char const* get_weekday_name( unsigned day_index ) {
+  if ( day_index > 6 )
+    throw invalid_argument(
+      BUILD_STRING( day_index, " not in range 0-6" )
+    );
+#ifdef WIN32
+  static unique_ptr<char[]> weekday[7];
+  if ( !weekday[ day_index ] )
+    weekday[ day_index ].reset(
+      get_win32_locale_info( weekday_name[ day_index ] )
+    );
+  return weekday[ day_index ].get();
+#else
+  return nl_langinfo( weekday_name[ day_index ] );
+#endif /* WIN32 */
+}
+
 ///////////////////////////////////////////////////////////////////////////////
 
 } // namespace locale

=== modified file 'src/zorbautils/locale.h'
--- src/zorbautils/locale.h	2012-09-19 21:16:15 +0000
+++ src/zorbautils/locale.h	2013-01-02 14:49:24 +0000
@@ -297,7 +297,7 @@
        * @return Returns said enumeration or \c unknown.
        */
       type find( char const *country );
-    }
+    } // namespace iso3166_1
 
     /////////////////////////////////////////////////////////////////////////// 
 
@@ -474,7 +474,7 @@
        * @return Returns said enumeration or \c unknown.
        */
       type find( char const *lang );
-    }
+    } // namespace iso639_2
 
     /////////////////////////////////////////////////////////////////////////// 
 
@@ -487,6 +487,22 @@
     iso639_1::type find_lang( char const *lang );
 
     /**
+     * Gets the date format for the current locale.  The format is that used by
+     * strptime(3).
+     *
+     * @return Returns said date format.
+     */
+    char const* get_date_format();
+
+    /**
+     * Gets the date and time format for the current locale.  The format is
+     * that used by strptime(3).
+     *
+     * @return Returns said date format.
+     */
+    char const* get_date_time_format();
+
+    /**
      * Gets the ISO 3166-1 country code enumeration for the host system.
      *
      * @return Returns said enumeration or \c unknown.
@@ -500,12 +516,58 @@
      */
     iso639_1::type get_host_lang();
 
+    /**
+     * Gets a month's abbreviation in the current locale.
+     *
+     * @param month_index The index of the month to get in the range 0-11.
+     * @return Returns said abbreviation.
+     */
+    char const* get_month_abbr( unsigned month_index );
+
+    /**
+     * Gets a month's full name in the current locale.
+     *
+     * @param month_index The index of the month to get in the range 0-11.
+     * @return Returns said full name.
+     */
+    char const* get_month_name( unsigned month_index );
+
+    /**
+     * Gets the time AM or PM string in the current locale.
+     *
+     * @param pm If \c true, gets the PM string; else the AM string.
+     * @return Returns said string.
+     */
+    char const* get_time_ampm( bool pm );
+
+    /**
+     * Gets the time format for the current locale.  The format is that used by
+     * strptime(3).
+     *
+     * @return Returns said time format.
+     */
+    char const* get_time_format();
+
+    /**
+     * Gets a weekday's abbreviation in the current locale.
+     *
+     * @param day_index The index of the weekday to get in the range 0-6.
+     * @return Returns said abbreviation.
+     */
+    char const* get_weekday_abbr( unsigned day_index );
+
+    /**
+     * Gets a weekday's full name in the current locale.
+     *
+     * @param day_index The index of the month to get in the range 0-6.
+     * @return Returns said full name.
+     */
+    char const* get_weekday_name( unsigned day_index );
+
     ///////////////////////////////////////////////////////////////////////////
 
   } // namespace locale
 } // namespace zorba
 
-#undef DEF_OSTREAM_INSERT_OPERATOR
-
 #endif  /* ZORBA_CORE_LOCALE_H */
 /* vim:set et sw=2 ts=2: */

=== added directory 'test/rbkt/ExpQueryResults/zorba/datetime'
=== added file 'test/rbkt/ExpQueryResults/zorba/datetime/datetime-parse-date-lj-uY-1.xml.res'
--- test/rbkt/ExpQueryResults/zorba/datetime/datetime-parse-date-lj-uY-1.xml.res	1970-01-01 00:00:00 +0000
+++ test/rbkt/ExpQueryResults/zorba/datetime/datetime-parse-date-lj-uY-1.xml.res	2013-01-02 14:49:24 +0000
@@ -0,0 +1,1 @@
+2012-12-28

=== added file 'test/rbkt/ExpQueryResults/zorba/datetime/datetime-parse-date-uD-1.xml.res'
--- test/rbkt/ExpQueryResults/zorba/datetime/datetime-parse-date-uD-1.xml.res	1970-01-01 00:00:00 +0000
+++ test/rbkt/ExpQueryResults/zorba/datetime/datetime-parse-date-uD-1.xml.res	2013-01-02 14:49:24 +0000
@@ -0,0 +1,1 @@
+2068-01-02

=== added file 'test/rbkt/ExpQueryResults/zorba/datetime/datetime-parse-date-uD-2.xml.res'
--- test/rbkt/ExpQueryResults/zorba/datetime/datetime-parse-date-uD-2.xml.res	1970-01-01 00:00:00 +0000
+++ test/rbkt/ExpQueryResults/zorba/datetime/datetime-parse-date-uD-2.xml.res	2013-01-02 14:49:24 +0000
@@ -0,0 +1,1 @@
+1969-01-02

=== added file 'test/rbkt/ExpQueryResults/zorba/datetime/datetime-parse-date-uF-1.xml.res'
--- test/rbkt/ExpQueryResults/zorba/datetime/datetime-parse-date-uF-1.xml.res	1970-01-01 00:00:00 +0000
+++ test/rbkt/ExpQueryResults/zorba/datetime/datetime-parse-date-uF-1.xml.res	2013-01-02 14:49:24 +0000
@@ -0,0 +1,1 @@
+1912-12-28

=== added file 'test/rbkt/ExpQueryResults/zorba/datetime/datetime-parse-dateTime-uFTZ-1.xml.res'
--- test/rbkt/ExpQueryResults/zorba/datetime/datetime-parse-dateTime-uFTZ-1.xml.res	1970-01-01 00:00:00 +0000
+++ test/rbkt/ExpQueryResults/zorba/datetime/datetime-parse-dateTime-uFTZ-1.xml.res	2013-01-02 14:49:24 +0000
@@ -0,0 +1,1 @@
+1912-12-28T05:00:00-08:00

=== added file 'test/rbkt/ExpQueryResults/zorba/datetime/datetime-parse-time-uH-1.xml.res'
--- test/rbkt/ExpQueryResults/zorba/datetime/datetime-parse-time-uH-1.xml.res	1970-01-01 00:00:00 +0000
+++ test/rbkt/ExpQueryResults/zorba/datetime/datetime-parse-time-uH-1.xml.res	2013-01-02 14:49:24 +0000
@@ -0,0 +1,1 @@
+23:00:00Z

=== added file 'test/rbkt/ExpQueryResults/zorba/datetime/datetime-parse-time-uIMS-1.xml.res'
--- test/rbkt/ExpQueryResults/zorba/datetime/datetime-parse-time-uIMS-1.xml.res	1970-01-01 00:00:00 +0000
+++ test/rbkt/ExpQueryResults/zorba/datetime/datetime-parse-time-uIMS-1.xml.res	2013-01-02 14:49:24 +0000
@@ -0,0 +1,1 @@
+00:34:56Z

=== added file 'test/rbkt/ExpQueryResults/zorba/datetime/datetime-parse-time-uR-1.xml.res'
--- test/rbkt/ExpQueryResults/zorba/datetime/datetime-parse-time-uR-1.xml.res	1970-01-01 00:00:00 +0000
+++ test/rbkt/ExpQueryResults/zorba/datetime/datetime-parse-time-uR-1.xml.res	2013-01-02 14:49:24 +0000
@@ -0,0 +1,1 @@
+23:45:00Z

=== added file 'test/rbkt/ExpQueryResults/zorba/datetime/datetime-parse-time-uT-1.xml.res'
--- test/rbkt/ExpQueryResults/zorba/datetime/datetime-parse-time-uT-1.xml.res	1970-01-01 00:00:00 +0000
+++ test/rbkt/ExpQueryResults/zorba/datetime/datetime-parse-time-uT-1.xml.res	2013-01-02 14:49:24 +0000
@@ -0,0 +1,1 @@
+23:45:01Z

=== added directory 'test/rbkt/Queries/zorba/datetime'
=== added file 'test/rbkt/Queries/zorba/datetime/datetime-parse-date-ld-1.spec'
--- test/rbkt/Queries/zorba/datetime/datetime-parse-date-ld-1.spec	1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/datetime/datetime-parse-date-ld-1.spec	2013-01-02 14:49:24 +0000
@@ -0,0 +1,1 @@
+Error: http://www.zorba-xquery.com/errors:ZDTP0005

=== added file 'test/rbkt/Queries/zorba/datetime/datetime-parse-date-ld-1.xq'
--- test/rbkt/Queries/zorba/datetime/datetime-parse-date-ld-1.xq	1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/datetime/datetime-parse-date-ld-1.xq	2013-01-02 14:49:24 +0000
@@ -0,0 +1,3 @@
+import module namespace dt = "http://www.zorba-xquery.com/modules/datetime";;
+
+dt:parse-date( "1", "%d" )

=== added file 'test/rbkt/Queries/zorba/datetime/datetime-parse-date-lj-uY-1.xq'
--- test/rbkt/Queries/zorba/datetime/datetime-parse-date-lj-uY-1.xq	1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/datetime/datetime-parse-date-lj-uY-1.xq	2013-01-02 14:49:24 +0000
@@ -0,0 +1,3 @@
+import module namespace dt = "http://www.zorba-xquery.com/modules/datetime";;
+
+dt:parse-date( "363 2012", "%j %Y" )

=== added file 'test/rbkt/Queries/zorba/datetime/datetime-parse-date-uD-1.xq'
--- test/rbkt/Queries/zorba/datetime/datetime-parse-date-uD-1.xq	1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/datetime/datetime-parse-date-uD-1.xq	2013-01-02 14:49:24 +0000
@@ -0,0 +1,3 @@
+import module namespace dt = "http://www.zorba-xquery.com/modules/datetime";;
+
+dt:parse-date( "1/2/68", "%D" )

=== added file 'test/rbkt/Queries/zorba/datetime/datetime-parse-date-uD-2.xq'
--- test/rbkt/Queries/zorba/datetime/datetime-parse-date-uD-2.xq	1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/datetime/datetime-parse-date-uD-2.xq	2013-01-02 14:49:24 +0000
@@ -0,0 +1,3 @@
+import module namespace dt = "http://www.zorba-xquery.com/modules/datetime";;
+
+dt:parse-date( "1/2/69", "%D" )

=== added file 'test/rbkt/Queries/zorba/datetime/datetime-parse-date-uF-1.xq'
--- test/rbkt/Queries/zorba/datetime/datetime-parse-date-uF-1.xq	1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/datetime/datetime-parse-date-uF-1.xq	2013-01-02 14:49:24 +0000
@@ -0,0 +1,3 @@
+import module namespace dt = "http://www.zorba-xquery.com/modules/datetime";;
+
+dt:parse-date( "1912-12-28", "%F" )

=== added file 'test/rbkt/Queries/zorba/datetime/datetime-parse-dateTime-uFTZ-1.xq'
--- test/rbkt/Queries/zorba/datetime/datetime-parse-dateTime-uFTZ-1.xq	1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/datetime/datetime-parse-dateTime-uFTZ-1.xq	2013-01-02 14:49:24 +0000
@@ -0,0 +1,3 @@
+import module namespace dt = "http://www.zorba-xquery.com/modules/datetime";;
+
+dt:parse-dateTime( "1912-12-28 05:00:00 PST", "%F %T %Z" )

=== added file 'test/rbkt/Queries/zorba/datetime/datetime-parse-time-uH-1.xq'
--- test/rbkt/Queries/zorba/datetime/datetime-parse-time-uH-1.xq	1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/datetime/datetime-parse-time-uH-1.xq	2013-01-02 14:49:24 +0000
@@ -0,0 +1,3 @@
+import module namespace dt = "http://www.zorba-xquery.com/modules/datetime";;
+
+dt:parse-time( "23", "%H" )

=== added file 'test/rbkt/Queries/zorba/datetime/datetime-parse-time-uH-2.spec'
--- test/rbkt/Queries/zorba/datetime/datetime-parse-time-uH-2.spec	1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/datetime/datetime-parse-time-uH-2.spec	2013-01-02 14:49:24 +0000
@@ -0,0 +1,1 @@
+Error: http://www.zorba-xquery.com/errors:ZDTP0003

=== added file 'test/rbkt/Queries/zorba/datetime/datetime-parse-time-uH-2.xq'
--- test/rbkt/Queries/zorba/datetime/datetime-parse-time-uH-2.xq	1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/datetime/datetime-parse-time-uH-2.xq	2013-01-02 14:49:24 +0000
@@ -0,0 +1,3 @@
+import module namespace dt = "http://www.zorba-xquery.com/modules/datetime";;
+
+dt:parse-time( "24", "%H" )

=== added file 'test/rbkt/Queries/zorba/datetime/datetime-parse-time-uIMS-1.xq'
--- test/rbkt/Queries/zorba/datetime/datetime-parse-time-uIMS-1.xq	1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/datetime/datetime-parse-time-uIMS-1.xq	2013-01-02 14:49:24 +0000
@@ -0,0 +1,3 @@
+import module namespace dt = "http://www.zorba-xquery.com/modules/datetime";;
+
+dt:parse-time( "12:34:56", "%I:%M:%S" )

=== added file 'test/rbkt/Queries/zorba/datetime/datetime-parse-time-uM-1.spec'
--- test/rbkt/Queries/zorba/datetime/datetime-parse-time-uM-1.spec	1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/datetime/datetime-parse-time-uM-1.spec	2013-01-02 14:49:24 +0000
@@ -0,0 +1,1 @@
+Error: http://www.zorba-xquery.com/errors:ZDTP0005

=== added file 'test/rbkt/Queries/zorba/datetime/datetime-parse-time-uM-1.xq'
--- test/rbkt/Queries/zorba/datetime/datetime-parse-time-uM-1.xq	1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/datetime/datetime-parse-time-uM-1.xq	2013-01-02 14:49:24 +0000
@@ -0,0 +1,3 @@
+import module namespace dt = "http://www.zorba-xquery.com/modules/datetime";;
+
+dt:parse-time( "59", "%M" )

=== added file 'test/rbkt/Queries/zorba/datetime/datetime-parse-time-uR-1.xq'
--- test/rbkt/Queries/zorba/datetime/datetime-parse-time-uR-1.xq	1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/datetime/datetime-parse-time-uR-1.xq	2013-01-02 14:49:24 +0000
@@ -0,0 +1,3 @@
+import module namespace dt = "http://www.zorba-xquery.com/modules/datetime";;
+
+dt:parse-time( "23:45", "%R" )

=== added file 'test/rbkt/Queries/zorba/datetime/datetime-parse-time-uS-1.spec'
--- test/rbkt/Queries/zorba/datetime/datetime-parse-time-uS-1.spec	1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/datetime/datetime-parse-time-uS-1.spec	2013-01-02 14:49:24 +0000
@@ -0,0 +1,1 @@
+Error: http://www.zorba-xquery.com/errors:ZDTP0005

=== added file 'test/rbkt/Queries/zorba/datetime/datetime-parse-time-uS-1.xq'
--- test/rbkt/Queries/zorba/datetime/datetime-parse-time-uS-1.xq	1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/datetime/datetime-parse-time-uS-1.xq	2013-01-02 14:49:24 +0000
@@ -0,0 +1,3 @@
+import module namespace dt = "http://www.zorba-xquery.com/modules/datetime";;
+
+dt:parse-time( "59", "%S" )

=== added file 'test/rbkt/Queries/zorba/datetime/datetime-parse-time-uT-1.xq'
--- test/rbkt/Queries/zorba/datetime/datetime-parse-time-uT-1.xq	1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/datetime/datetime-parse-time-uT-1.xq	2013-01-02 14:49:24 +0000
@@ -0,0 +1,3 @@
+import module namespace dt = "http://www.zorba-xquery.com/modules/datetime";;
+
+dt:parse-time( "23:45:01", "%T" )


Follow ups