← Back to team overview

zorba-coders team mailing list archive

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

 

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

Commit message:
Fixed many date/time formatting bugs by completely rewriting the code; added basic support for multiple calendar systems; added default countries-for-languages look-up for locales.

Requested reviews:
  Paul J. Lucas (paul-lucas)
Related bugs:
  Bug #1123162 in Zorba: "FOTS: formatting dates and times failures"
  https://bugs.launchpad.net/zorba/+bug/1123162

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

Fixed many date/time formatting bugs by completely rewriting the code; added basic support for multiple calendar systems; added default countries-for-languages look-up for locales.
-- 
https://code.launchpad.net/~zorba-coders/zorba/bug-1123162/+merge/154529
Your team Zorba Coders is subscribed to branch lp:zorba.
=== modified file 'ChangeLog'
--- ChangeLog	2013-03-20 18:39:54 +0000
+++ ChangeLog	2013-03-20 21:54:22 +0000
@@ -14,6 +14,8 @@
   * In store API, added ability to specify a stream's originating URI (file)
     for streamable strings and base64Binary.
   * Added millis-to-dateTime() function in datetime module.
+  * Added setCalendar(), getCalendar(), setLocale(), and getLocale() to
+    DynamicContext class in C++ API.
   * fn:trace outputs "empty-sequence()" if the input is the empty-sequence.
   * Allow multiple default function namespaces.
   * Added xqxq:variable-value function.
@@ -33,6 +35,7 @@
   * Fixed bug #1095889 (Improve error message for xml-parsing error).
   * Fixed bug in index join rule (no index join if inner clause has positional var).
   * Fixed bug in index join rule (copy var ids after cloning index domain expr).
+  * Fixed bug #1123162 (FOTS: formatting dates and times failures)
   * Added missing wrapper expressions around some variable references.
   * Fixed bug in the throwing of error XQTY0086 during node construction.
   * Fixed bug #1148335 (where-clause expression was not always reset when it should be)

=== modified file 'include/zorba/dynamic_context.h'
--- include/zorba/dynamic_context.h	2013-03-08 04:26:02 +0000
+++ include/zorba/dynamic_context.h	2013-03-20 21:54:22 +0000
@@ -22,6 +22,7 @@
 
 #include <zorba/config.h>
 #include <zorba/locale.h>
+#include <zorba/time.h>
 #include <zorba/api_shared_types.h>
 #include <zorba/static_context_consts.h>
 #include <zorba/xmldatamanager.h>
@@ -268,6 +269,20 @@
   getLocale( locale::iso639_1::type *aLang,
              locale::iso3166_1::type *aCountry ) const = 0;
 
+  /** \brief Sets the calendar.
+   *
+   * @param aCalendar The calendar to use.
+   */
+  virtual void
+  setCalendar( time::calendar::type aCalendar ) = 0;
+
+  /** \brief Gets the current calendar.
+   *
+   * @return the current calendar.
+   */
+  virtual time::calendar::type
+  getCalendar() const = 0;
+
   /** \brief Add a name-value pair to this context.
    *         The value can be accessed in the evaluate method
    *         of external functions (see ContextualExternalFunction).

=== modified file 'include/zorba/locale.h'
--- include/zorba/locale.h	2013-03-08 04:26:02 +0000
+++ include/zorba/locale.h	2013-03-20 21:54:22 +0000
@@ -263,7 +263,7 @@
         BZ,   ///< Belize
         CA,   ///< Canada
         CC,   ///< Cocos Islands
-        CD,   ///< Congo
+        CD,   ///< Congo, the Democratic Republic of the
         CF,   ///< Central African Republic
         CG,   ///< Congo
         CH,   ///< Switzerland

=== modified file 'include/zorba/pregenerated/diagnostic_list.h'
--- include/zorba/pregenerated/diagnostic_list.h	2013-03-06 10:37:33 +0000
+++ include/zorba/pregenerated/diagnostic_list.h	2013-03-20 21:54:22 +0000
@@ -192,9 +192,9 @@
 
 extern ZORBA_DLL_PUBLIC XQueryErrorCode XTDE1310;
 
-extern ZORBA_DLL_PUBLIC XQueryErrorCode XTDE1340;
+extern ZORBA_DLL_PUBLIC XQueryErrorCode FOFD1340;
 
-extern ZORBA_DLL_PUBLIC XQueryErrorCode XTDE1350;
+extern ZORBA_DLL_PUBLIC XQueryErrorCode FOFD1350;
 
 #if !defined(ZORBA_NO_FULL_TEXT)
 extern ZORBA_DLL_PUBLIC XQueryErrorCode FTST0008;

=== added file 'include/zorba/time.h'
--- include/zorba/time.h	1970-01-01 00:00:00 +0000
+++ include/zorba/time.h	2013-03-20 21:54:22 +0000
@@ -0,0 +1,68 @@
+/*
+ * 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_API_H
+#define ZORBA_TIME_API_H
+
+namespace zorba {
+namespace time {
+
+///////////////////////////////////////////////////////////////////////////////
+
+/**
+ * XQuery 3.0 F&O: 9.8.4.3: The calendars listed below were known to be in use
+ * during the last hundred years.
+ */
+namespace calendar {
+  enum type {
+    unknown,
+    AD,   ///< Anno Domini (Christian Era)
+    AH,   ///< Anno Hegirae (Muhammedan Era)
+    AM,   ///< Anno Mundi (Jewish Calendar)
+    AME,  ///< Mauludi Era (solar years since Mohammed's birth)
+    AP,   ///< Anno Persici
+    AS,   ///< Aji Saka Era (Java)
+    BE,   ///< Buddhist Era
+    CB,   ///< Cooch Behar Era
+    CE,   ///< Common Era
+    CL,   ///< Chinese Lunar Era
+    CS,   ///< Chula Sakarat Era
+    EE,   ///< Ethiopian Era
+    FE,   ///< Fasli Era
+    ISO,  ///< ISO 8601 calendar
+    JE,   ///< Japanese Calendar
+    KE,   ///< Khalsa Era (Sikh calendar)
+    KY,   ///< Kali Yuga
+    ME,   ///< Malabar Era
+    MS,   ///< Monarchic Solar Era
+    OS,   ///< Old Style (Julian Calendar)
+    RS,   ///< Rattanakosin (Bangkok) Era
+    SE,   ///< Saka Era
+    SH,   ///< Mohammedan Solar Era (Iran)
+    SS,   ///< Saka Samvat
+    TE,   ///< Tripurabda Era
+    VE,   ///< Vikrama Era
+    VS    ///< Vikrama Samvat Era
+  };
+
+} // namespace calendar
+
+///////////////////////////////////////////////////////////////////////////////
+
+} // namespace time
+} // namespace zorba
+#endif /* ZORBA_TIME_API_H */
+/* vim:set et sw=2 ts=2: */

=== modified file 'modules/org/expath/ns/file.xq.src/file.cpp'
--- modules/org/expath/ns/file.xq.src/file.cpp	2013-03-06 02:54:03 +0000
+++ modules/org/expath/ns/file.xq.src/file.cpp	2013-03-20 21:54:22 +0000
@@ -657,7 +657,7 @@
 int
 LastModifiedFunction::getGmtOffset()
 {
-  time_t t = time(0);
+  time_t t = ::time(0);
   struct tm* data;
   data = localtime(&t);
   data->tm_isdst = 0;

=== modified file 'modules/w3c/pregenerated/xqt-errors.xq'
--- modules/w3c/pregenerated/xqt-errors.xq	2013-03-06 10:37:33 +0000
+++ modules/w3c/pregenerated/xqt-errors.xq	2013-03-20 21:54:22 +0000
@@ -861,17 +861,17 @@
  : 
  : @see http://www.w3.org/2005/xqt-errors
 :)
-declare variable $err:XTDE1340 as xs:QName := fn:QName($err:NS, "err:XTDE1340");
+declare variable $err:FOFD1340 as xs:QName := fn:QName($err:NS, "err:FOFD1340");
 
 (:~
  :
- : It is a non-recoverable dynamic error if a component specifier within the
- : picture refers to components that are not available in the given type of
- : \c $value.
+ : It is a non-recoverable dynamic error if a component specifier within
+ : the picture refers to components that are not available in the given
+ : type of $value.
  : 
  : @see http://www.w3.org/2005/xqt-errors
 :)
-declare variable $err:XTDE1350 as xs:QName := fn:QName($err:NS, "err:XTDE1350");
+declare variable $err:FOFD1350 as xs:QName := fn:QName($err:NS, "err:FOFD1350");
 
 (:~
  :

=== modified file 'modules/xqxq/xqxq.xq.src/xqxq.cpp'
--- modules/xqxq/xqxq.xq.src/xqxq.cpp	2013-02-22 17:09:54 +0000
+++ modules/xqxq/xqxq.xq.src/xqxq.cpp	2013-03-20 21:54:22 +0000
@@ -238,7 +238,7 @@
   :
   theModule(aModule)
 {
-  srand(time(NULL));
+  srand(::time(NULL));
 }
     
 

=== modified file 'src/api/dynamiccontextimpl.cpp'
--- src/api/dynamiccontextimpl.cpp	2013-03-08 04:26:02 +0000
+++ src/api/dynamiccontextimpl.cpp	2013-03-20 21:54:22 +0000
@@ -691,6 +691,17 @@
 /****************************************************************************//**
 
 ********************************************************************************/
+void DynamicContextImpl::setCalendar( time::calendar::type aCalendar ) {
+  theCtx->set_calendar( aCalendar );
+}
+
+time::calendar::type DynamicContextImpl::getCalendar() const {
+  return theCtx->get_calendar();
+}
+
+/****************************************************************************//**
+
+********************************************************************************/
 bool DynamicContextImpl::addExternalFunctionParam(
     const String& aName,
     void* aValue)

=== modified file 'src/api/dynamiccontextimpl.h'
--- src/api/dynamiccontextimpl.h	2013-03-08 04:26:02 +0000
+++ src/api/dynamiccontextimpl.h	2013-03-20 21:54:22 +0000
@@ -151,6 +151,12 @@
   getLocale( locale::iso639_1::type *aLang, 
              locale::iso3166_1::type *aCountry ) const;
 
+  virtual void
+  setCalendar( time::calendar::type aCalendar );
+
+  virtual time::calendar::type
+  getCalendar() const;
+
   virtual bool
   addExternalFunctionParam(const String& aName, void* aValue);
 

=== modified file 'src/context/dynamic_context.cpp'
--- src/context/dynamic_context.cpp	2013-03-12 17:03:31 +0000
+++ src/context/dynamic_context.cpp	2013-03-20 21:54:22 +0000
@@ -137,6 +137,7 @@
     reset_current_date_time();
     theLang = locale::get_host_lang();
     theCountry = locale::get_host_country();
+    theCalendar = time::calendar::get_default();
   }
   else
   {
@@ -145,6 +146,7 @@
     theDefaultCollectionUri = parent->theDefaultCollectionUri;
     theLang = parent->theLang;
     theCountry = parent->theCountry;
+    theCalendar = parent->theCalendar;
   }
 }
 

=== modified file 'src/context/dynamic_context.h'
--- src/context/dynamic_context.h	2013-03-12 17:03:31 +0000
+++ src/context/dynamic_context.h	2013-03-20 21:54:22 +0000
@@ -18,6 +18,7 @@
 #define ZORBA_DYNAMIC_CONTEXT_H
 
 #include <zorba/external_function_parameter.h>
+#include <zorba/time.h>
 
 #include "zorbautils/hashmap_zstring.h"
 #include "zorbautils/hashmap_itemp.h"
@@ -141,6 +142,7 @@
 
   locale::iso639_1::type       theLang;
   locale::iso3166_1::type      theCountry;
+  time::calendar::type         theCalendar;
 
 public:
   double                       theDocLoadingUserTime;
@@ -189,6 +191,14 @@
       *country = theCountry;
   }
 
+  void set_calendar( time::calendar::type calendar ) {
+    theCalendar = calendar;
+  }
+
+  time::calendar::type get_calendar() const {
+    return theCalendar;
+  }
+
   const std::vector<VarValue>& get_variables() const { return theVarValues; }
 
   void add_variable(ulong varid, store::Item_t& value);

=== modified file 'src/diagnostics/diagnostic_en.xml'
--- src/diagnostics/diagnostic_en.xml	2013-03-07 10:10:10 +0000
+++ src/diagnostics/diagnostic_en.xml	2013-03-20 21:54:22 +0000
@@ -1012,21 +1012,51 @@
       <value>"$1": picture string does not satisfy format-number() function rules</value>
     </diagnostic>
 
-    <diagnostic code="XTDE1340">
+    <diagnostic code="FOFD1340">
       <comment>
-       It is a non-recoverable dynamic error if the syntax of the picture is
-       incorrect.
+        It is a non-recoverable dynamic error if the syntax of the picture is
+        incorrect.
       </comment>
-      <value>"$1": invalid picture string for date/time</value>
+      <value>"$1": invalid picture string for date/time${: 2}</value>
+      <entry key="BadComponent_3">
+        <value>'$3': invalid component specifier</value>
+      </entry>
+      <entry key="BadWidthModifier">
+        <value>invalid width modifier</value>
+      </entry>
+      <entry key="DigitNotSameFamily_34">
+        <value>"$3": digit not from same digit family as $4</value>
+      </entry>
+      <entry key="MultipleComponent_3">
+        <value>'$3': multiple component specifiers between []</value>
+      </entry>
+      <entry key="MustBeOneMandatoryDigit">
+        <value>there must be at least one mandatory-digit-sign</value>
+      </entry>
+      <entry key="NoComponent">
+        <value>component specifier expected between []</value>
+      </entry>
+      <entry key="NoAdjacentGroupSep_3">
+        <value>"$3": grouping separator must not be adjacent to others</value>
+      </entry>
+      <entry key="NoGroupSepAtStart_3">
+        <value>"$3": grouping separator illegal at start of decimal-digit-pattern</value>
+      </entry>
+      <entry key="NoGroupSepAtEnd_3">
+        <value>"$3": grouping separator illegal at end of decimal-digit-pattern</value>
+      </entry>
+      <entry key="NoOptDigitAfterMandatory">
+        <value>"#": optional-digit-sign must precede all mandatory-digit-signs</value>
+      </entry>
     </diagnostic>
 
-    <diagnostic code="XTDE1350">
+    <diagnostic code="FOFD1350">
       <comment>
-       It is a non-recoverable dynamic error if a component specifier within the
-       picture refers to components that are not available in the given type of
-       \c $value.
+        It is a non-recoverable dynamic error if a component specifier within
+        the picture refers to components that are not available in the given
+        type of $value.
       </comment>
-      <value>component specifier not available</value>
+      <value>"$1": component specifier not available</value>
     </diagnostic>
 
     <!--////////// XQuery Full-Text Errors /////////////////////////////////-->

=== modified file 'src/diagnostics/pregenerated/diagnostic_list.cpp'
--- src/diagnostics/pregenerated/diagnostic_list.cpp	2013-03-06 10:37:33 +0000
+++ src/diagnostics/pregenerated/diagnostic_list.cpp	2013-03-20 21:54:22 +0000
@@ -271,10 +271,10 @@
 XQueryErrorCode XTDE1310( "XTDE1310" );
 
 
-XQueryErrorCode XTDE1340( "XTDE1340" );
-
-
-XQueryErrorCode XTDE1350( "XTDE1350" );
+XQueryErrorCode FOFD1340( "FOFD1340" );
+
+
+XQueryErrorCode FOFD1350( "FOFD1350" );
 
 
 #if !defined(ZORBA_NO_FULL_TEXT)

=== modified file 'src/diagnostics/pregenerated/dict_en.cpp'
--- src/diagnostics/pregenerated/dict_en.cpp	2013-03-07 10:10:10 +0000
+++ src/diagnostics/pregenerated/dict_en.cpp	2013-03-20 21:54:22 +0000
@@ -53,6 +53,8 @@
   { "FODT0002", "overflow/underflow in duration operation" },
   { "FODT0003", "\"$1\": invalid timezone value (in seconds)" },
   { "FOER0000", "unidentifier error" },
+  { "FOFD1340", "\"$1\": invalid picture string for date/time${: 2}" },
+  { "FOFD1350", "\"$1\": component specifier not available" },
   { "FOFI0001", "\"$1\": not castable to xs:language" },
   { "FOFI0002", "invalid argument in format-integer: $1" },
   { "FONS0004", "\"$1\": no namespace found for prefix" },
@@ -270,8 +272,6 @@
   { "XSST0009", "\"break loop\" statement not inside while statement" },
   { "XSST0010", "\"continue loop\" statement not inside while statement" },
   { "XTDE1310", "\"$1\": picture string does not satisfy format-number() function rules" },
-  { "XTDE1340", "\"$1\": invalid picture string for date/time" },
-  { "XTDE1350", "component specifier not available" },
   { "XUDY0009", "node has no parent in \"replace\" expression (without \"value of\")" },
   { "XUDY0014", "\"modify\" can not modify node not created by \"copy\"" },
   { "XUDY0015", "node is target of multiple \"rename\" expressions in same query" },
@@ -613,6 +613,16 @@
   { "~FOCA0002_BadLexicalQName_2", "\"$2\": value is not a valid lexical QName" },
   { "~FOCA0002_NoCastTo_234", "\"$2\": value of type $3 is not castable to type $4" },
   { "~FOCA0002_NoURIforPrefix_2", "no namespace URI provided for prefix in lexical QName \"$2\"" },
+  { "~FOFD1340_BadComponent_3", "'$3': invalid component specifier" },
+  { "~FOFD1340_BadWidthModifier", "invalid width modifier" },
+  { "~FOFD1340_DigitNotSameFamily_34", "\"$3\": digit not from same digit family as $4" },
+  { "~FOFD1340_MultipleComponent_3", "'$3': multiple component specifiers between []" },
+  { "~FOFD1340_MustBeOneMandatoryDigit", "there must be at least one mandatory-digit-sign" },
+  { "~FOFD1340_NoAdjacentGroupSep_3", "\"$3\": grouping separator must not be adjacent to others" },
+  { "~FOFD1340_NoComponent", "component specifier expected between []" },
+  { "~FOFD1340_NoGroupSepAtEnd_3", "\"$3\": grouping separator illegal at end of decimal-digit-pattern" },
+  { "~FOFD1340_NoGroupSepAtStart_3", "\"$3\": grouping separator illegal at start of decimal-digit-pattern" },
+  { "~FOFD1340_NoOptDigitAfterMandatory", "\"#\": optional-digit-sign must precede all mandatory-digit-signs" },
   { "~FORG0001_BadHexDigit_2", "'$2': invalid hexedecimal digit" },
   { "~FORG0001_Base64BadChar_2", "\"$2\": invalid Base64 character" },
   { "~FORG0001_Base64Multiple4", "Base64 data must be a multiple of 4 characters" },

=== modified file 'src/diagnostics/pregenerated/dict_zed_keys.h'
--- src/diagnostics/pregenerated/dict_zed_keys.h	2013-03-07 10:10:10 +0000
+++ src/diagnostics/pregenerated/dict_zed_keys.h	2013-03-20 21:54:22 +0000
@@ -63,6 +63,16 @@
 #define ZED_XQDY0074_NotCastToQName "~XQDY0074_NotCastToQName"
 #define ZED_XQDY0074_NoEmptyLocalname "~XQDY0074_NoEmptyLocalname"
 #define ZED_XQDY0074_NameSapceConstructor "~XQDY0074_NameSapceConstructor"
+#define ZED_FOFD1340_BadComponent_3 "~FOFD1340_BadComponent_3"
+#define ZED_FOFD1340_BadWidthModifier "~FOFD1340_BadWidthModifier"
+#define ZED_FOFD1340_DigitNotSameFamily_34 "~FOFD1340_DigitNotSameFamily_34"
+#define ZED_FOFD1340_MultipleComponent_3 "~FOFD1340_MultipleComponent_3"
+#define ZED_FOFD1340_MustBeOneMandatoryDigit "~FOFD1340_MustBeOneMandatoryDigit"
+#define ZED_FOFD1340_NoComponent "~FOFD1340_NoComponent"
+#define ZED_FOFD1340_NoAdjacentGroupSep_3 "~FOFD1340_NoAdjacentGroupSep_3"
+#define ZED_FOFD1340_NoGroupSepAtStart_3 "~FOFD1340_NoGroupSepAtStart_3"
+#define ZED_FOFD1340_NoGroupSepAtEnd_3 "~FOFD1340_NoGroupSepAtEnd_3"
+#define ZED_FOFD1340_NoOptDigitAfterMandatory "~FOFD1340_NoOptDigitAfterMandatory"
 #define ZED_FTST0009_BadStopWordsLang "~FTST0009_BadStopWordsLang"
 #define ZED_FTST0009_BadStemmerLang "~FTST0009_BadStemmerLang"
 #define ZED_FTST0009_BadThesaurusLang "~FTST0009_BadThesaurusLang"

=== modified file 'src/functions/func_durations_dates_times_impl.cpp'
--- src/functions/func_durations_dates_times_impl.cpp	2013-02-07 17:24:36 +0000
+++ src/functions/func_durations_dates_times_impl.cpp	2013-03-20 21:54:22 +0000
@@ -19,6 +19,7 @@
 #include "functions/function_impl.h"
 
 #include "runtime/durations_dates_times/DurationsDatesTimesImpl.h"
+#include "runtime/durations_dates_times/format_dateTime.h"
 #include "runtime/numerics/NumericsImpl.h"
 #include "runtime/core/arithmetic_impl.h"
 #include "zorbamisc/ns_consts.h"

=== modified file 'src/runtime/CMakeLists.txt'
--- src/runtime/CMakeLists.txt	2013-02-07 17:24:36 +0000
+++ src/runtime/CMakeLists.txt	2013-03-20 21:54:22 +0000
@@ -125,6 +125,7 @@
   core/gflwor/outerfor_iterator.cpp
   core/internal_operators.cpp
   durations_dates_times/DurationsDatesTimesImpl.cpp
+  durations_dates_times/format_dateTime.cpp
   indexing/doc_indexer.cpp
   indexing/index_ddl.cpp
   json/common.cpp

=== modified file 'src/runtime/durations_dates_times/DurationsDatesTimesImpl.cpp'
--- src/runtime/durations_dates_times/DurationsDatesTimesImpl.cpp	2013-02-28 11:15:32 +0000
+++ src/runtime/durations_dates_times/DurationsDatesTimesImpl.cpp	2013-03-20 21:54:22 +0000
@@ -45,8 +45,6 @@
 {
 SERIALIZABLE_CLASS_VERSIONS(FnDateTimeConstructorIterator)
 
-SERIALIZABLE_CLASS_VERSIONS(FnFormatDateTimeIterator)
-
 SERIALIZABLE_CLASS_VERSIONS(FnAdjustToTimeZoneIterator_1)
 
 SERIALIZABLE_CLASS_VERSIONS(FnAdjustToTimeZoneIterator_2)
@@ -54,19 +52,11 @@
 
 BINARY_ACCEPT(FnDateTimeConstructorIterator);
 
-NARY_ACCEPT(FnFormatDateTimeIterator);
-
 UNARY_ACCEPT(FnAdjustToTimeZoneIterator_1);
 
 BINARY_ACCEPT(FnAdjustToTimeZoneIterator_2);
 
 
-static void skip_whitespace(zstring& str, ascii::size_type& position, int delta = 0)
-{
-  while (position+delta < str.size() && ascii::is_space(str[position+delta]))
-    position++;
-}
-
 bool FnDateTimeConstructorIterator::nextImpl(store::Item_t& result, PlanState& planState) const
 {
   store::Item_t item0;
@@ -199,555 +189,5 @@
   STACK_END(state);
 }
 
-
-/**
- *______________________________________________________________________
- *
- * fn:format-dateTime()
- *
- *_______________________________________________________________________*/
-
-class Modifier
-{
-public:
-  zstring presentation_modifier;
-  zstring second_modifier;
-
-  // for min_width and max_width
-  // -3 means an error in the picture
-  // -2 means width modifiers are not specified
-  // -1 means '*'
-  // >=0 means explicitly specified width
-  long min_width_modifier;
-  long max_width_modifier;
-
-  Modifier()
-    :
-    presentation_modifier(""),
-    second_modifier(""),
-    min_width_modifier(-2),
-    max_width_modifier(-2)
-  {
-  };
-};
-
-
-static void format_number(zstring& str, long number, Modifier& modifier)
-{
-  // Presentation modifier can be:
-  // 'Ww', "Nn', 'W', 'w', 'N', 'n'
-  // 'i', 'I', '1', '00...01'
-  // the modifier will not be checked if it is supported or not
-  zstring temp;
-
-  if (modifier.presentation_modifier.size() > 0 && modifier.presentation_modifier[0] == '0')
-  {
-    ztd::to_string(number, &temp);
-    while (temp.size() < modifier.presentation_modifier.size())
-      temp = "0" + temp;
-  }
-  else // "1" or fallback
-  {
-    ztd::to_string(number, &temp);
-  }
-
-  if (modifier.second_modifier == "o")
-  {
-    if ((number % 10) == 1 && (number % 100) != 11)
-      temp.append("st");
-    else if ((number % 10) == 2 && (number % 100) != 12)
-      temp.append("nd");
-    else if ((number % 10) == 3 && (number % 100) != 13)
-      temp.append("rd");
-    else
-      temp.append("th");
-  }
-
-  if (modifier.min_width_modifier >= 0)
-    while (temp.size() < (unsigned int)modifier.min_width_modifier)
-    temp = "0" + temp;
-
-  str.append(temp.c_str());
-}
-
-
-static void format_string_width(
-    zstring& destination,
-    zstring& source,
-    Modifier& modifier)
-{
-  zstring temp = source;
-  while (modifier.max_width_modifier > 0 && temp.size() < (unsigned int)modifier.max_width_modifier)
-    temp.append(" ");
-  destination.append(temp.c_str());
-}
-
-
-static bool format_string(
-    zstring& destination,
-    zstring& source,
-    Modifier& modifier)
-{
-  zstring temp;
-  if (modifier.presentation_modifier == "n")
-  {
-    zstring newcase = source;
-    ascii::to_lower(newcase);
-    temp.append(newcase);
-  }
-  else if (modifier.presentation_modifier == "N")
-  {
-    zstring newcase = source;
-    ascii::to_upper(newcase);
-    temp.append(newcase);
-  }
-  else if (modifier.presentation_modifier == "Nn")
-  {
-    zstring newcase;
-
-    newcase = source.substr(0, 1);
-    ascii::to_upper(newcase);
-    temp.append(newcase);
-
-    newcase = source.substr(1,source.size()-1);
-    ascii::to_lower(newcase);
-    temp.append(newcase);
-  }
-  else
-    return false;
-
-  format_string_width(destination, temp, modifier);
-  return true;
-}
-
-
-static bool format_string(
-    zstring& destination,
-    const char* source,
-    Modifier& modifier)
-{
-  zstring temp(source);
-  return format_string(destination, temp, modifier);
-}
-
-
-static void format_component(
-    zstring& destination,
-    long number,
-    zstring& source,
-    Modifier& modifier)
-{
-  if (!format_string(destination, source, modifier))
-    format_number(destination, number, modifier);
-}
-
-
-static void output_year(
-    zstring& destination,
-    long number,
-    Modifier& modifier)
-{
-  format_number(destination, number, modifier);
-
-  if (modifier.max_width_modifier >= 0)
-  {
-    if ((unsigned int)modifier.max_width_modifier > destination.size())
-      modifier.max_width_modifier = destination.size();
-
-    destination = destination.substr(destination.size() - modifier.max_width_modifier, modifier.max_width_modifier);
-  }
-}
-
-
-static void output_month(
-    zstring& destination,
-    long number,
-    Modifier& modifier)
-{
-  static const char* month[12]  = { "january", "february", "march", "april", "may", "june", "july", "august", "september", "october", "november", "december"};
-  zstring temp(month[number-1]);
-  if (modifier.max_width_modifier > 0 && (unsigned int)modifier.max_width_modifier < temp.size())
-    temp = temp.substr(0, modifier.max_width_modifier);
-
-  format_component(destination, number, temp, modifier);
-}
-
-
-static void output_day_of_week(
-    zstring& destination,
-    long number,
-    Modifier& modifier)
-{
-  static const char* day[7]  = { "sunday", "monday", "tuesday", "wednesday", "thursday", "friday", "saturday"};
-  zstring temp(day[number]);
-  if (modifier.max_width_modifier > 0 && (unsigned int)modifier.max_width_modifier < temp.size())
-    temp = temp.substr(0, modifier.max_width_modifier);
-
-  if (modifier.presentation_modifier.size() == 0)
-    modifier.presentation_modifier = "n"; // Default for day of week is "n"
-
-  format_component(destination, number, temp, modifier);
-}
-
-
-static void parse_presentation_modifier(
-    zstring& str,
-    ascii::size_type& position,
-    zstring& result)
-{
-  result = "";
-
-  skip_whitespace(str, position, 1);
-
-  if (position+1 >= str.size())
-    return;
-
-  zstring modifier = "";
-
-  if (str[position+1] == '1' || str[position+1] == 'i' || str[position+1] == 'I'
-           || str[position+1] == 'a' || str[position+1] == 'A'
-           || str[position+1] == 'w' || str[position+1] == 'W'
-           || str[position+1] == 'n' || str[position+1] == 'N' )
-  {
-    modifier.append(str, position+1, 1);
-    position++;
-
-    skip_whitespace(str, position, 1);
-
-    if (position+1 < str.size() &&
-        ((modifier[0] == 'W' && str[position+1] == 'w')
-          ||
-        (modifier[0] == 'N' && str[position+1] == 'n')))
-    {
-      modifier.append(str, position+1, 1);
-      position++;
-    }
-  }
-  else if (str[position+1] == '0')
-  {
-    ascii::size_type start = position;
-    while (position+1 < str.size() && (str[position+1] == '0' || ascii::is_space(str[position+1])))
-    {
-      if (str[position+1] == '0')
-        modifier.append(str, position+1, 1);
-      position++;
-    }
-
-    if (position+1 >= str.size() || str[position+1] != '1')
-    {
-      position = start;
-      return;
-    }
-
-    modifier.append(str, position+1, 1);
-    position++;
-  }
-
-  result = modifier;
-}
-
-
-static void parse_second_modifier(
-    zstring& str,
-    ascii::size_type& position,
-    zstring& result)
-{
-  result = "";
-
-  skip_whitespace(str, position, 1);
-
-  if (position+1 >= str.size())
-    return;
-
-  position++;
-  if (str[position] == 't')
-    result = "t";
-  else if (str[position] == 'o')
-    result = "o";
-  else
-    position--;
-}
-
-
-// for min_width and max_width
-// -3 means an error in the picture
-// -2 means width modifiers are not specified
-// -1 means '*'
-// >=0 means explicitly specified width
-static void parse_width_modifier(
-    zstring& str,
-    ascii::size_type& position,
-    long& min_width,
-    long& max_width)
-{
-  min_width = -2;
-  max_width = -2;
-
-  skip_whitespace(str, position, 1);
-
-  if (position+1 >= str.size() || str[position+1] != ',')
-    return;
-
-  position++;
-  skip_whitespace(str, position, 1);
-
-  // The min_width must be present if there is a comma symbol
-  min_width = -3;
-  if (position+1 >= str.size())
-    return;
-
-  if (str[position+1] == '*')
-  {
-    min_width = -1;
-    position++;
-  }
-  else
-  {
-    if (parse_long(str.data(), str.size(), position, min_width, -1, -1, 1))
-      min_width = -3;
-  }
-
-  skip_whitespace(str, position, 1);
-
-  if (position+1 >= str.size() || str[position+1] != '-')
-    return;
-
-  position++;
-  skip_whitespace(str, position, 1);
-
-  if (position+1 < str.size() && str[position+1] == '*')
-  {
-    max_width = -1;
-    position++;
-  }
-  else
-  {
-    if (parse_long(str.data(), str.size(), position, max_width, -1, -1, 1))
-      min_width = -3;
-  }
-}
-
-
-static int get_data_type(char component)
-{
-  switch (component)
-  {
-  case 'Y':
-    return DateTime::YEAR_DATA;
-  case 'M':
-    return DateTime::MONTH_DATA;
-  case 'D':
-    return DateTime::DAY_DATA;
-  case 'd':  // day in year
-    return DateTime::DAY_DATA;
-  case 'F':  // day of week
-    return DateTime::DAY_DATA;
-  case 'W':  // week in year
-    return DateTime::DAY_DATA;
-  case 'w':  // week in month
-    return DateTime::DAY_DATA;
-  case 'H':  // hour in day (24 hours)
-    return DateTime::HOUR_DATA;
-  case 'h':  // hour in half-day (12 hours)
-    return DateTime::HOUR_DATA;
-  case 'P':  // am/pm marker
-    return DateTime::HOUR_DATA;
-  case 'm':
-    return DateTime::MINUTE_DATA;
-  case 's':
-    return DateTime::SECONDS_DATA;
-  case 'f': // fractional seconds
-    return DateTime::FRACSECONDS_DATA;
-  case 'Z': // timezone as a time offset from UTC, or if an alphabetic modifier is present the conventional name of a timezone (such as PST)
-    return -1;
-  case 'z': // timezone as a time offset using GMT, for example GMT+1
-    return -1;
-  case 'C': // calendar: the name or abbreviation of a calendar name
-    return -1;
-  case 'E': // era: the name of a baseline for the numbering of years, for example the reign of a monarch
-    return -1;
-  default:
-    return -1;
-  }
-}
-
-
-bool FnFormatDateTimeIterator::nextImpl(
-    store::Item_t& result,
-    PlanState& planState) const
-{
-  bool variable_marker;
-  zstring pictureString, resultString;
-  store::Item_t dateTimeItem, picture;
-  PlanIteratorState* state;
-  DEFAULT_STACK_INIT(PlanIteratorState, state, planState);
-
-  if (!consumeNext(dateTimeItem, theChildren[0].getp(), planState))
-  {
-    // Got void -- returning void
-    STACK_PUSH(false, state);
-  }
-  else
-  {
-    consumeNext(picture, theChildren[1].getp(), planState);
-
-    pictureString = picture->getStringValue().str();
-    resultString = "";
-    variable_marker = false;
-
-    for (ascii::size_type i = 0; i < pictureString.size(); i++)
-    {
-      if (!variable_marker)
-      {
-        if (pictureString[i] == '[')
-        {
-          // check for quoted "[["
-          if (i<pictureString.size()-1 && pictureString[i+1] == '[')
-            i++;
-          else
-          {
-            variable_marker = true;
-            continue;
-          }
-        }
-        else if (pictureString[i] == ']')
-        {
-          // check for quoted "]]"
-          if (i<pictureString.size()-1 && pictureString[i+1] == ']')
-            i++;
-        }
-
-        resultString.append(pictureString, i, 1);
-      }
-      else  // variable_marker == true
-      {
-        char component = 0;
-        Modifier modifier;
-
-        switch (pictureString[i])
-        {
-        case 'Y': case 'M': case 'D': case 'd': case 'F': case 'W': case 'w':
-        case 'H': case 'h': case 'P': case 'm': case 's': case 'f':
-        case 'Z': case 'z': case 'C': case 'E':
-          component = pictureString[i];
-          break;
-
-        case ' ': case '\f': case '\n': case '\r': case '\t': case '\v':
-          continue; // ignore whitespace
-          break;
-
-        case ']':
-          variable_marker = false;
-          break;
-
-        default:
-          throw XQUERY_EXCEPTION(
-            err::XTDE1340, ERROR_PARAMS( pictureString ), ERROR_LOC( loc )
-          );
-        }
-
-        if (variable_marker == false)
-          continue;
-
-        parse_presentation_modifier(pictureString, i, modifier.presentation_modifier);
-
-        parse_second_modifier(pictureString, i, modifier.second_modifier);
-
-        parse_width_modifier(pictureString,
-                             i,
-                             modifier.min_width_modifier,
-                             modifier.max_width_modifier);
-
-        // min_width_modifier is -3, there was an error in the picture
-        if (modifier.min_width_modifier == -3)
-          throw XQUERY_EXCEPTION(
-            err::XTDE1340, ERROR_PARAMS( pictureString ), ERROR_LOC( loc )
-          );
-
-        int data_type = get_data_type(component);
-        if (data_type != -1 && (!DateTime::FACET_MEMBERS[facet_type][data_type]))
-          throw XQUERY_EXCEPTION(err::XTDE1350, ERROR_LOC(loc));
-
-        switch (component)
-        {
-        case 'Y':
-          output_year(resultString, std::abs(dateTimeItem->getDateTimeValue().getYear()), modifier);
-          break;
-        case 'M':
-          output_month(resultString, dateTimeItem->getDateTimeValue().getMonth(), modifier);
-          break;
-        case 'D':
-          format_number(resultString, dateTimeItem->getDateTimeValue().getDay(), modifier);
-          break;
-        case 'd':  // day in year
-          format_number(resultString, dateTimeItem->getDateTimeValue().getDayOfYear(), modifier);
-          break;
-        case 'F':  // day of week
-          output_day_of_week(resultString, dateTimeItem->getDateTimeValue().getDayOfWeek(), modifier);
-          break;
-        case 'W':  // week in year
-          format_number(resultString, dateTimeItem->getDateTimeValue().getWeekInYear(), modifier);
-          break;
-        case 'w':  // week in month
-          format_number(resultString, dateTimeItem->getDateTimeValue().getWeekInMonth(), modifier);
-          break;
-        case 'H':  // hour in day (24 hours)
-          format_number(resultString, dateTimeItem->getDateTimeValue().getHours(), modifier);
-          break;
-        case 'h':  // hour in half-day (12 hours)
-          // Convert hour from:      0  1  ...  12  13  ...  23   0
-          //                to:     12  1  ...  12   1  ...  11  12
-          format_number(resultString, 1 + (11 + dateTimeItem->getDateTimeValue().getHours()) % 12,
-                        modifier);
-          break;
-        case 'P':  // am/pm marker
-          if (modifier.presentation_modifier.empty())
-            modifier.presentation_modifier = "n";  // Default for the AM/PM marker is "n"
-          format_string(resultString, dateTimeItem->getDateTimeValue().getHours() >= 12 ? "pm" : "am", modifier);
-          break;
-        case 'm':
-          if (modifier.presentation_modifier.empty())
-            modifier.presentation_modifier.append("01");
-          format_number(resultString, dateTimeItem->getDateTimeValue().getMinutes(), modifier);
-          break;
-        case 's':
-          if (modifier.presentation_modifier.empty())
-            modifier.presentation_modifier.append("01");
-          format_number(resultString, dateTimeItem->getDateTimeValue().getIntSeconds(), modifier);
-          break;
-        case 'f': // fractional seconds
-          format_number(resultString, (long)(dateTimeItem->getDateTimeValue().getFractionalSeconds()*1000.0/DateTime::FRAC_SECONDS_UPPER_LIMIT),
-                        modifier);
-          break;
-        case 'Z': // timezone as a time offset from UTC, or if an alphabetic modifier is present the conventional name of a timezone (such as PST)
-          // deliberate fall-through
-        case 'z': // timezone as a time offset using GMT, for example GMT+1
-          {
-            zstring temp = "gmt";
-            temp += dateTimeItem->getDateTimeValue().getTimezone().toString();
-            format_string(resultString, temp.c_str(), modifier);
-          }
-          break;
-        case 'C': // calendar: the name or abbreviation of a calendar name
-          if (modifier.presentation_modifier.empty())
-            modifier.presentation_modifier.append("n");
-          format_string(resultString, "gregorian", modifier);
-          break;
-        case 'E': // era: the name of a baseline for the numbering of years, for example the reign of a monarch
-          if (modifier.presentation_modifier.empty())
-            modifier.presentation_modifier.append("n");
-          format_string(resultString, dateTimeItem->getDateTimeValue().getYear() < 0 ? "ad" : "bc", modifier);
-          break;
-        } // switch
-      } // if (!variable_marker)
-
-    } // for
-
-    STACK_PUSH(GENV_ITEMFACTORY->createString(result, resultString), state);
-  }
-
-  STACK_END (state);
-}
-
 } // namespace zorba
 /* vim:set et sw=2 ts=2: */

=== modified file 'src/runtime/durations_dates_times/DurationsDatesTimesImpl.h'
--- src/runtime/durations_dates_times/DurationsDatesTimesImpl.h	2013-02-07 17:24:36 +0000
+++ src/runtime/durations_dates_times/DurationsDatesTimesImpl.h	2013-03-20 21:54:22 +0000
@@ -24,53 +24,12 @@
 #include "runtime/base/unarybase.h"
 #include "runtime/base/narybase.h"
 
+namespace zorba {
 
-namespace zorba
-{
+///////////////////////////////////////////////////////////////////////////////
 
 BINARY_ITER(FnDateTimeConstructorIterator);
 
-
-// XQuery 3.0 DateTime formatting
-class FnFormatDateTimeIterator : public NaryBaseIterator<FnFormatDateTimeIterator,
-                                                         PlanIteratorState >
-{
-private:
-  DateTime::FACET_TYPE facet_type;
-
-public:
-  SERIALIZABLE_CLASS(FnFormatDateTimeIterator);
-
-  SERIALIZABLE_CLASS_CONSTRUCTOR2T(
-  FnFormatDateTimeIterator,
-  NaryBaseIterator<FnFormatDateTimeIterator, PlanIteratorState >);
-
-  void serialize(::zorba::serialization::Archiver &ar)
-  {
-    serialize_baseclass(ar,
-    (NaryBaseIterator<FnFormatDateTimeIterator, PlanIteratorState >*)this);
-
-    SERIALIZE_ENUM(DateTime::FACET_TYPE, facet_type);
-  }
-
-public:
-  FnFormatDateTimeIterator(
-        static_context* sctx,
-        const QueryLoc& loc,
-        std::vector<PlanIter_t>& aChildren,
-        DateTime::FACET_TYPE a_facet_type = DateTime::DATETIME_FACET)
-    :
-    NaryBaseIterator<FnFormatDateTimeIterator, PlanIteratorState>(sctx, loc, aChildren),
-    facet_type(a_facet_type)
-  {
-  }
-
-  void accept(PlanIterVisitor& v) const;
-
-  bool nextImpl(store::Item_t& result, PlanState& aPlanState) const;
-};
-
-
 /*
 10.7 Timezone Adjustment Functions on Dates and Time Values
 */
@@ -88,14 +47,14 @@
 */
 BINARY_ITER(FnAdjustToTimeZoneIterator_2);
 
+///////////////////////////////////////////////////////////////////////////////
+
 } // namespace zorba
 
-#endif
-
+#endif /* ZORBA_RUNTIME_DURATIONSDATESTIMES */
 /*
  * Local variables:
  * mode: c++
  * End:
  */
-
 /* vim:set et sw=2 ts=2: */

=== added file 'src/runtime/durations_dates_times/format_dateTime.cpp'
--- src/runtime/durations_dates_times/format_dateTime.cpp	1970-01-01 00:00:00 +0000
+++ src/runtime/durations_dates_times/format_dateTime.cpp	2013-03-20 21:54:22 +0000
@@ -0,0 +1,1377 @@
+/*
+ * 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"
+
+// standard
+#include <algorithm>
+#include <cctype>
+#include <cmath>
+#include <cstdlib>
+#include <functional>
+#include <iomanip>
+#include <iostream>
+#include <sstream>
+
+// Zorba
+#include "context/dynamic_context.h"
+#include "context/static_context.h"
+#include "runtime/core/arithmetic_impl.h"
+#include "runtime/visitors/planiter_visitor.h"
+#include "store/api/item.h"
+#include "store/api/item_factory.h"
+#include "store/api/store.h"
+#include "system/globalenv.h"
+#include "util/ascii_util.h"
+#include "util/stream_util.h"
+#include "util/string_util.h"
+#include "util/time_util.h"
+#include "util/utf8_util.h"
+#include "zorbatypes/datetime.h"
+#include "zorbatypes/datetime/parse.h"
+#include "zorbatypes/duration.h"
+#include "zorbatypes/zstring.h"
+#include "zorbautils/locale.h"
+
+// local
+#include "format_dateTime.h"
+
+using namespace std;
+using namespace zorba::locale;
+using namespace zorba::time;
+
+namespace zorba {
+
+SERIALIZABLE_CLASS_VERSIONS(FnFormatDateTimeIterator)
+NARY_ACCEPT(FnFormatDateTimeIterator);
+
+///////////////////////////////////////////////////////////////////////////////
+
+/**
+ * Holds presentation modifier data.
+ */
+struct modifier {
+  enum first_type {
+    arabic,       // '1' : 0 1 2 ... 10 11 12 ...
+    alpha,        // 'a' : a b c ... z aa ab ac ...
+    ALPHA,        // 'A' : A B C ... Z AA AB AC ...
+    roman,        // 'i' : i ii iii iv v vi vii viii ix x ...
+    ROMAN,        // 'I' : I II III IV V VI VII VIII IX X ...
+    name,         // 'n' : name
+    Name,         // 'Nn': Name
+    NAME,         // 'N' : NAME
+    words,        // 'w' : one two three four ...
+    Words,        // 'Ww': One Two Three Four ...
+    WORDS,        // 'W' : ONE TWO THREE FOUR ...
+    military_tz   // 'Z' : A B C ... J ... X Y Z
+  };
+
+  enum second_co_type {
+    no_second_co,
+    cardinal,     // 'c': 7 or seven
+    ordinal       // 'o': 7th or seventh
+  };
+
+  enum second_at_type {
+    no_second_at,
+    alphabetic,   // 'a'
+    traditional   // 't'
+  };
+
+  typedef unsigned width_type;
+
+  struct {
+    bool parsed;
+    first_type type;
+    zstring format;
+    bool has_grouping_separators;
+    unicode::code_point zero;
+  } first;
+
+  struct {
+    second_co_type co_type;
+    zstring co_string;
+    second_at_type at_type;
+  } second;
+
+  width_type min_width;
+  width_type max_width;
+
+  //
+  // This stuff isn't part of the "presentation modifier" as discussed in the
+  // XQuery3.0 F&O spec, but this is a convenient place to put it nonetheless.
+  //
+  iso639_1::type lang;
+  bool lang_is_fallback;
+  iso3166_1::type country;
+  calendar::type cal;
+  bool cal_is_fallback;
+
+  void append_if_fallback_lang( zstring *s ) const {
+    if ( lang_is_fallback ) {
+      //
+      // XQuery 3.0 F&O: 9.8.4.3: If the fallback representation uses a
+      // different language from that requested, the output string must
+      // identify the language actually used, for example by prefixing the
+      // string with [Language: Y] (where Y is the language actually used)
+      // localized in an implementation-dependent way.
+      //
+      ostringstream oss;
+      // TODO: localize "Language"
+      oss << "[Language: " << lang << ']';
+      *s += oss.str();
+    }
+  }
+
+  bool gt_max_width( width_type n ) const {
+    return max_width > 0 && n > max_width;
+  }
+
+  zstring const& left_pad_zero( zstring *s ) const {
+    if ( min_width )
+      utf8::left_pad( s, min_width, first.zero );
+    return *s;
+  }
+
+  zstring const& right_pad_space( zstring *s ) const {
+    if ( min_width )
+      utf8::right_pad( s, min_width, ' ' );
+    return *s;
+  }
+
+  void set_default_width( width_type width ) {
+    if ( !(first.parsed || min_width || max_width) )
+      min_width = max_width = width;
+  }
+
+  modifier() {
+    first.parsed = false;
+    first.type = arabic;
+    first.has_grouping_separators = false;
+    first.zero = '0';
+    second.co_type = cardinal;
+    second.at_type = no_second_at;
+    min_width = max_width = 0;
+  };
+};
+
+///////////////////////////////////////////////////////////////////////////////
+
+zstring alpha( unsigned n, bool capital ) {
+  zstring result;
+  if ( n ) {
+    char const c = capital ? 'A' : 'a';
+    while ( n ) {
+      unsigned const m = n - 1;
+      result.insert( (zstring::size_type)0, 1, c + m % 26 );
+      n = m / 26;
+    }
+  } else
+    result = "0";
+  return result;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+namespace english_impl {
+
+// Based on code from:
+// http://www.cprogramming.com/challenges/integer-to-english-sol.html
+
+static string const ones[][2] = {
+  { "",          ""            },
+  { "one",       "first"       },
+  { "two",       "second"      },
+  { "three",     "third"       },
+  { "four",      "fourth"      },
+  { "five",      "fifth"       },
+  { "six",       "sixth"       },
+  { "seven",     "seventh"     },
+  { "eight",     "eighth"      },
+  { "nine",      "ninth"       },
+  { "ten",       "tenth"       },
+  { "eleven",    "eleventh"    },
+  { "twelve",    "twelveth"    },
+  { "thirteen",  "thirteenth"  },
+  { "fourteen",  "fourteenth"  },
+  { "fifteen",   "fifteenth"   },
+  { "sixteen",   "sixteenth"   },
+  { "seventeen", "seventeenth" },
+  { "eighteen",  "eighteenth"  },
+  { "nineteen",  "nineteenth"  }
+};
+
+static zstring const tens[][2] = {
+  { "",        ""           },
+  { "",        ""           },
+  { "twenty",  "twentieth"  },
+  { "thirty",  "thirtieth"  },
+  { "forty",   "fortieth"   },
+  { "fifty",   "fiftieth"   },
+  { "sixty",   "sixtieth"   },
+  { "seventy", "seventieth" },
+  { "eighty",  "eighteenth" },
+  { "ninety",  "ninetieth"  }
+};
+
+// Enough entries to print English for 64-bit integers.
+static zstring const big[][2] = {
+  { "",            ""              },
+  { "thousand",    "thousandth"    },
+  { "million",     "millionth"     },
+  { "billion",     "billionth"     },
+  { "trillion",    "trillionth"    },
+  { "quadrillion", "quadrillionth" },
+  { "quintillion", "quintillionth" }
+};
+
+inline zstring if_space( zstring const &s ) {
+  return s.empty() ? "" : ' ' + s;
+}
+
+static zstring hundreds( int64_t n, bool ordinal ) {
+  if ( n < 20 )
+    return ones[ n ][ ordinal ];
+  zstring const tmp( if_space( ones[ n % 10 ][ ordinal ] ) );
+  return tens[ n / 10 ][ ordinal && tmp.empty() ] + tmp;
+}
+
+} // namespace english_impl
+
+/**
+ * Converts a signed integer to English, e.g, 42 becomes "forty two".
+ *
+ * @param n The integer to convert.
+ * @param ordinal If \c true, ordinal words ("forty second") are returned.
+ * @return Returns \a n in English.
+ */
+static zstring english( int64_t n, bool ordinal = false ) {
+  using namespace english_impl;
+
+  if ( !n )
+    return ordinal ? "zeroth" : "zero";
+
+  bool const negative = n < 0;
+  if ( negative )
+    n = -n;
+
+  int big_count = 0;
+  bool big_ordinal = ordinal;
+  zstring r;
+
+  while ( n ) {
+    if ( int64_t const m = n % 1000 ) {
+      zstring s;
+      if ( m < 100 )
+        s = hundreds( m, ordinal );
+      else {
+        zstring const tmp( if_space( hundreds( m % 100, ordinal ) ) );
+        s = ones[ m / 100 ][0] + ' '
+          + (ordinal && tmp.empty() ? "hundredth" : "hundred") + tmp;
+      }
+      zstring const tmp( if_space( r ) );
+      r = s + if_space( big[ big_count ][ big_ordinal && tmp.empty() ] + tmp );
+      big_ordinal = false;
+    }
+    n /= 1000;
+    ++big_count;
+    ordinal = false;
+  }
+
+  if ( negative )
+    r = "negative " + r;
+  return r;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+static bool is_grouping_separator( unicode::code_point cp ) {
+  using namespace unicode;
+  //
+  // XQuery 3.0 F&O: 4.6.1: a grouping-separator-sign is a non-alphanumeric
+  // character, that is a character whose Unicode category is other than Nd,
+  // Nl, No, Lu, Ll, Lt, Lm or Lo.
+  //
+  return !( is_category( cp, Nd )
+         || is_category( cp, Nl )
+         || is_category( cp, No )
+         || is_category( cp, Lu )
+         || is_category( cp, Ll )
+         || is_category( cp, Lt )
+         || is_category( cp, Lm )
+         || is_category( cp, Lo )
+  );
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+/**
+ * Returns the English ordinal suffix for an integer, e.g., "st" for 1, "nd"
+ * for 2, etc.
+ *
+ * @param n The integer to return the ordinal suffix for.
+ * @return Returns said suffix.
+ */
+static char const* ordinal( int n ) {
+  n = std::abs( n );
+  switch ( n % 100 ) {
+    case 11:
+    case 12:
+    case 13:
+      break;
+    default:
+      switch ( n % 10 ) {
+        case 1: return "st";
+        case 2: return "nd";
+        case 3: return "rd";
+      }
+  }
+  return "th";
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+/**
+ * A unary_function to convert a (presumed) lower-case string to title-case
+ * "Like This."
+ */
+class to_title : public unary_function<char,char> {
+public:
+  to_title() : capitalize_( true ) { }
+
+  result_type operator()( argument_type c ) {
+    if ( ascii::is_alpha( c ) ) {
+      if ( capitalize_ ) {
+        c = ascii::to_upper( c );
+        capitalize_ = false;
+      }
+    } else if ( ascii::is_space( c ) )
+      capitalize_ = true;
+    return c;
+  };
+
+private:
+  bool capitalize_;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+
+static void append_number( int n, modifier const &mod, zstring *dest ) {
+  switch ( mod.first.type ) {
+    case modifier::arabic: {
+      utf8::itou_buf_type buf;
+      zstring tmp( utf8::itou( n, buf, mod.first.zero ) );
+      if ( mod.second.co_type == modifier::ordinal )
+        tmp += ordinal( n );
+      *dest += mod.left_pad_zero( &tmp );
+      break;
+    }
+
+    case modifier::alpha:
+    case modifier::ALPHA: {
+      zstring tmp( alpha( n, mod.first.type == modifier::ALPHA ) );
+      *dest += mod.right_pad_space( &tmp );
+      break;
+    }
+
+    case modifier::roman:
+    case modifier::ROMAN: {
+      ostringstream oss;
+      if ( mod.first.type == modifier::ROMAN )
+        oss << uppercase;
+      oss << roman( n );
+      zstring tmp( oss.str() );
+      *dest += mod.right_pad_space( &tmp );
+      break;
+    }
+
+    case modifier::words: {
+      zstring tmp( english( n, mod.second.co_type == modifier::ordinal ) );
+      *dest += mod.right_pad_space( &tmp );
+      break;
+    }
+
+    case modifier::Words: {
+      zstring tmp( english( n, mod.second.co_type == modifier::ordinal ) );
+      std::transform( tmp.begin(), tmp.end(), tmp.begin(), to_title() );
+      *dest += mod.right_pad_space( &tmp );
+      break;
+    }
+
+    case modifier::WORDS: {
+      zstring tmp( english( n, mod.second.co_type == modifier::ordinal ) );
+      ascii::to_upper( tmp );
+      *dest += mod.right_pad_space( &tmp );
+      break;
+    }
+
+    default:
+      /* handled elsewhere */;
+  }
+}
+
+static void append_fractional_seconds( int n, modifier const &mod,
+                                       zstring *dest ) {
+  switch ( mod.first.type ) {
+    case modifier::arabic:
+      if ( mod.min_width || mod.max_width ) {
+        if ( mod.max_width ) {
+          double const f = (double)n / DateTime::FRAC_SECONDS_UPPER_LIMIT;
+          double const p = ::pow( 10, mod.max_width );
+          n = (int)( f * p + 0.5 );
+        } else
+          n = (int)( n * 1000.0 / DateTime::FRAC_SECONDS_UPPER_LIMIT );
+
+        ascii::itoa_buf_type buf;
+        zstring tmp( ascii::itoa( n, buf ) );
+
+        if ( tmp.size() < mod.min_width )
+          ascii::right_pad( &tmp, mod.min_width, '0' );
+        else if ( mod.min_width > 0 )
+          while ( tmp.size() > mod.min_width &&
+                  tmp[ tmp.size() - 1 ] == '0' ) {
+            tmp = tmp.substr( 0, tmp.size() - 1 );
+          }
+        *dest += tmp;
+        break;
+      }
+      n = (int)( n * 1000.0 / DateTime::FRAC_SECONDS_UPPER_LIMIT );
+      // no break;
+    default:
+      append_number( n, mod, dest );
+  }
+}
+
+static void append_string( zstring const &s, modifier const &mod,
+                           zstring *dest ) {
+  zstring tmp;
+  switch ( mod.first.type ) {
+    case modifier::name:
+      utf8::to_lower( s, &tmp );
+      break;
+    case modifier::Name: {
+      utf8::to_upper( s.substr( 0, 1 ), &tmp );
+      zstring tmp2;
+      utf8::to_lower( s.substr( 1 ), &tmp2 );
+      tmp += tmp2;
+      break;
+    }
+    case modifier::NAME:
+      utf8::to_upper( s, &tmp );
+      break;
+    default:
+      break;
+  }
+  *dest += mod.right_pad_space( &tmp );
+}
+
+static void append_month( unsigned mon, modifier const &mod, zstring *dest ) {
+  switch ( mod.first.type ) {
+    case modifier::name:
+    case modifier::Name:
+    case modifier::NAME: {
+      zstring name( locale::get_month_name( mon, mod.lang, mod.country ) );
+      utf8_string<zstring> u_name( name );
+      if ( mod.gt_max_width( u_name.size() ) ) {
+        //
+        // XQuery 3.0 F&O: 9.8.4.1: If the full representation of the value
+        // exceeds the specified maximum width, then the processor should
+        // attempt to use an alternative shorter representation that fits
+        // within the maximum width.  Where the presentation modifier is N, n,
+        // or Nn, this is done by abbreviating the name, using either
+        // conventional abbreviations if available, or crude right-truncation
+        // if not.
+        //
+        name = locale::get_month_abbr( mon, mod.lang, mod.country );
+        if ( mod.gt_max_width( u_name.size() ) )
+          u_name = u_name.substr( 0, mod.max_width );
+      }
+      mod.append_if_fallback_lang( dest );
+      append_string( name, mod, dest );
+      break;
+    }
+    default:
+      append_number( mon + 1, mod, dest );
+  }
+}
+
+static void append_timezone( char component, TimeZone const &tz,
+                             modifier const &mod, zstring *dest ) {
+  ascii::itoa_buf_type buf;
+  zstring format, tmp;
+  bool has_grouping_separators;
+
+  if ( mod.first.format.empty() ) {
+    format = "01:01";
+    has_grouping_separators = true;
+  } else {
+    format = mod.first.format;
+    has_grouping_separators = mod.first.has_grouping_separators;
+  }
+
+  int hour = tz.getHours();
+  int const min  = std::abs( tz.getMinutes() );
+
+  switch ( mod.first.type ) {
+    case modifier::NAME:
+      //
+      // XQuery 3.0 F&O: 9.8.4.2: If the first presentation modifier is N, then
+      // the timezone is output (where possible) as a timezone name, for
+      // example EST or CET. The same timezone offset has different names in
+      // different places; it is therefore recommended that this option should
+      // be used only if a country code or Olson timezone name is supplied in
+      // the $place argument. In the absence of this information, the
+      // implementation may apply a default, for example by using the timezone
+      // names that are conventional in North America. If no timezone name can
+      // be identified, the timezone offset is output using the fallback format
+      // +01:01.
+      //
+      if ( !min )
+        switch ( hour ) {
+          case  0: tmp += "GMT"; goto append;
+          case -5: tmp += "EST"; goto append;
+          case -6: tmp += "CST"; goto append;
+          case -7: tmp += "MST"; goto append;
+          case -8: tmp += "PST"; goto append;
+        }
+      // TODO: use Olson timezone names
+      goto fallback;
+
+    case modifier::military_tz:
+      //
+      // Ibid: If the first presentation modifier is Z, then the timezone is
+      // formatted as a military timezone letter, using the convention Z =
+      // +00:00, A = +01:00, B = +02:00, ..., M = +12:00, N = -01:00, O =
+      // -02:00, ... Y = -12:00.
+      //
+      if ( tz.timeZoneNotSet() ) {
+        //
+        // Ibid: The letter J (meaning local time) is used in the case of a
+        // value that does not specify a timezone offset.
+        //
+        tmp += 'J';
+        break;
+      }
+      if ( hour >= -12 && hour <= 12 && !min ) {
+        tmp += time::get_military_tz( hour );
+        break;
+      }
+      //
+      // Ibid: Timezone offsets that have no representation in this system
+      // (for example Indian Standard Time, +05:30) are output as if the
+      // format 01:01 had been requested.
+      //
+      // no break;
+
+fallback:
+      format = "01:01";
+      // no break;
+
+    default:
+      if ( component == 'z' ) {
+        //
+        // Ibid: When the component specifier is z, the output is the same as
+        // for component specifier Z, except that it is prefixed by the
+        // characters GMT or some localized equivalent. The prefix is omitted,
+        // however, in cases where the timezone is identified by name rather
+        // than by a numeric offset from UTC.
+        //
+        tmp = "GMT";
+      }
+
+      if ( mod.second.at_type == modifier::traditional && !hour && !min ) {
+        //
+        // Ibid: If the first presentation modifier is numeric, in any of the
+        // above formats, and the second presentation modifier is t, then a
+        // zero timezone offset (that is, UTC) is output as Z instead of a
+        // signed numeric value.
+        //
+        tmp += 'Z';
+        break;
+      }
+
+      if ( tz.isNegative() )
+        tmp += '-', hour = std::abs( hour );
+      else
+        tmp += '+';
+
+      if ( has_grouping_separators ) {
+        //
+        // Ibid: If the first presentation modifier is numeric with a grouping-
+        // separator (for example 1:01 or 01.01), then the timezone offset is
+        // output in hours and minutes, separated by the grouping separator,
+        // even if the number of minutes is zero: for example +5:00 or +10.30.
+        //
+        int grouping_separators = 0;
+        bool got_digit = false;
+        int hm_width[] = { 0, 0 };      // hour/minute widths
+        utf8_string<zstring const> const u_format( format );
+        utf8_string<zstring> u_tmp( tmp );
+
+        FOR_EACH( utf8_string<zstring const>, i, u_format ) {
+          unicode::code_point const cp = *i;
+          if ( unicode::is_Nd( cp ) ) {
+            got_digit = true;
+            if ( grouping_separators < 2 )
+              ++hm_width[ grouping_separators ];
+            continue;
+          }
+          if ( got_digit && is_grouping_separator( cp ) ) {
+            if ( ++grouping_separators == 1 ) {
+              zstring tmp2( utf8::itou( hour, buf, mod.first.zero ) );
+              tmp += utf8::left_pad( &tmp2, hm_width[0], mod.first.zero );
+            }
+          } else if ( grouping_separators )
+            grouping_separators = 99;
+          u_tmp += cp;
+        }
+
+        if ( hm_width[1] ) {
+          zstring tmp2( utf8::itou( min, buf, mod.first.zero ) );
+          tmp += utf8::left_pad( &tmp2, hm_width[1], mod.first.zero );
+        }
+      } else {
+        utf8_string<zstring const> const u_format( format );
+        utf8_string<zstring const>::size_type const u_size( u_format.size() );
+
+        if ( u_size <= 2 ) {
+          //
+          // Ibid: If the first presentation modifier is numeric and comprises
+          // one or two digits with no grouping-separator (for example 1 or
+          // 01), then the timezone is formatted as a displacement from UTC in
+          // hours, preceded by a plus or minus sign: for example -5 or +03. If
+          // the actual timezone offset is not an integral number of hours,
+          // then the minutes part of the offset is appended, separated by a
+          // colon: for example +10:30 or -1:15.
+          //
+          zstring tmp2( utf8::itou( hour, buf, mod.first.zero ) );
+          tmp += utf8::left_pad( &tmp2, u_size, mod.first.zero );
+          if ( min ) {
+            tmp2 = utf8::itou( min, buf, mod.first.zero );
+            tmp += ':';
+            tmp += utf8::left_pad( &tmp2, 2, mod.first.zero );
+          }
+          break;
+        }
+        if ( u_size <= 4 ) {
+          //
+          // Ibid: If the first presentation modifier is numeric and comprises
+          // three or four digits with no grouping-separator, for example 001
+          // or 0001, then the timezone offset is shown in hours and minutes
+          // with no separator, for example -0500 or +1030.
+          //
+          int const hhmm = hour * 100 + min;
+          zstring tmp2( utf8::itou( hhmm, buf, mod.first.zero ) );
+          tmp += utf8::left_pad( &tmp2, u_size, mod.first.zero );
+          break;
+        }
+      } // else
+  } // switch
+
+append:
+  *dest += tmp;
+}
+
+static void append_weekday( unsigned mday, unsigned mon, unsigned year,
+                            modifier const &mod, zstring *dest ) {
+  int wday = time::calc_wday( mday, mon, year );
+
+  modifier mod_copy( mod );
+  if ( !mod.first.parsed )
+    mod_copy.first.type = modifier::name;
+
+  switch ( mod_copy.first.type ) {
+    case modifier::name:
+    case modifier::Name:
+    case modifier::NAME: {
+      zstring name( locale::get_weekday_name( wday, mod.lang, mod.country ) );
+      utf8_string<zstring> u_name( name );
+      if ( mod.gt_max_width( u_name.size() ) ) {
+        //
+        // XQuery 3.0 F&O: 9.8.4.1: If the full representation of the value
+        // exceeds the specified maximum width, then the processor should
+        // attempt to use an alternative shorter representation that fits
+        // within the maximum width.  Where the presentation modifier is N, n,
+        // or Nn, this is done by abbreviating the name, using either
+        // conventional abbreviations if available, or crude right-truncation
+        // if not.
+        //
+        name = locale::get_weekday_abbr( wday, mod.lang, mod.country );
+        if ( mod.gt_max_width( u_name.size() ) )
+          u_name = u_name.substr( 0, mod.max_width );
+      }
+      mod.append_if_fallback_lang( dest );
+      append_string( name, mod_copy, dest );
+      break;
+    }
+    default: {
+      int const new_wday = calendar::convert_wday_to( wday, mod.cal );
+      if ( mod.cal_is_fallback || new_wday == -1 ) {
+        //
+        // Ibid: If the fallback representation uses a different calendar from
+        // that requested, the output string must identify the calendar
+        // actually used, for example by prefixing the string with [Calendar:
+        // X] (where X is the calendar actually used), localized as appropriate
+        // to the requested language.
+        //
+        ostringstream oss;
+        // TODO: localize "Calendar"
+        oss << "[Calendar: "
+            << ( new_wday == -1 ? calendar::get_default() : mod.cal ) << ']';
+        *dest += oss.str();
+      } else
+        wday = new_wday;
+      append_number( wday, mod_copy, dest );
+    }
+  }
+}
+
+static void append_week_in_year( unsigned mday, unsigned mon, unsigned year,
+                                 modifier const &mod, zstring *dest ) {
+  int week = time::calendar::calc_week_in_year( mday, mon, year, mod.cal );
+  if ( week == -1 ) {
+    week = time::calendar::calc_week_in_year( mday, mon, year, calendar::ISO );
+    ostringstream oss;
+    // TODO: localize "Calendar"
+    oss << "[Calendar: " << calendar::string_of[ calendar::ISO ] << ']';
+    *dest += oss.str();
+  }
+  append_number( week, mod, dest );
+}
+
+static void append_year( int year, modifier const &mod, zstring *s ) {
+  zstring tmp;
+  append_number( year, mod, &tmp );
+
+  if ( mod.first.type == modifier::arabic ) {
+    utf8_string<zstring> u_tmp( tmp );
+    utf8_string<zstring>::size_type const u_size = u_tmp.size();
+    if ( mod.gt_max_width( u_size ) ) {
+      //
+      // XQuery 3.0 F&O: 9.8.4.1: If the full representation of the value
+      // exceeds the specified maximum width, then the processor should attempt
+      // to use an alternative shorter representation that fits within the
+      // maximum width.  ... In the case of the year component, setting
+      // max-width requests omission of high-order digits from the year, for
+      // example, if max-width is set to 2 then the year 2003 will be output as
+      // 03.
+      //
+      u_tmp = u_tmp.substr( u_size - mod.max_width );
+    }
+  }
+  *s += tmp;
+}
+
+static void parse_first_modifier( zstring const &picture_str,
+                                  zstring::const_iterator *i,
+                                  modifier *mod, QueryLoc const &loc ) {
+  zstring::const_iterator &j = *i;
+  ascii::skip_whitespace( picture_str, &j );
+  if ( j == picture_str.end() || *j == ',' ) {
+    //
+    // Assume that the ',' is the start of the width modifier (hence there is
+    // neither a first nor second modifier).
+    //
+    return;
+  }
+
+  utf8_string<zstring const> const u_picture_str( picture_str );
+  utf8_string<zstring const>::const_iterator u( u_picture_str.current( j ) );
+  utf8_string<zstring> u_mod_format( mod->first.format );
+  unicode::code_point cp = *u;
+
+  if ( cp != '#' && is_grouping_separator( cp ) ) {
+    //
+    // XQuery 3.0 F&O: 4.6.1: A grouping-separator-sign must not appear
+    // at the start ... of the decimal-digit-pattern ....
+    //
+    throw XQUERY_EXCEPTION(
+      err::FOFD1340,
+      ERROR_PARAMS(
+        picture_str,
+        ZED( FOFD1340_NoGroupSepAtStart_3 ),
+        unicode::printable_cp( cp )
+      ),
+      ERROR_LOC( loc )
+    );
+  }
+
+  //
+  // Because of:
+  //
+  //    Ibid: if a variable marker contains one or more commas, then the last
+  //    comma is treated as introducing the width modifier, and all others are
+  //    treated as grouping separators.
+  //
+  // we have to count the number of commas in order to know when we've reached
+  // the last one.
+  //
+  int commas = 0;
+  for ( zstring::const_iterator c( *i ); c != picture_str.end(); ++c )
+    if ( *c == ',' )
+      ++commas;
+
+  unicode::code_point zero[2];
+
+  if ( cp == '#' || unicode::is_Nd( cp, &zero[0] ) ) {
+    bool got_grouping_separator = false;
+    bool got_mandatory_digit = cp != '#';
+
+    u_mod_format = *u;
+    while ( ++u != u_picture_str.end() ) {
+      cp = *u;
+      if ( cp == '#' ) {
+        if ( got_mandatory_digit ) {
+          //
+          // Ibid: There may be zero or more optional-digit-signs, and (if
+          // present) these must precede all mandatory-digit-signs.
+          //
+          throw XQUERY_EXCEPTION(
+            err::FOFD1340,
+            ERROR_PARAMS(
+              picture_str,
+              ZED( FOFD1340_NoOptDigitAfterMandatory )
+            ),
+            ERROR_LOC( loc )
+          );
+        }
+        got_grouping_separator = false;
+      } else if ( unicode::is_Nd( cp, &zero[ got_mandatory_digit ] ) ) {
+        if ( got_mandatory_digit ) {
+          if ( zero[1] != zero[0] ) {
+            //
+            // Ibid: All mandatory-digit-signs within the format token must be
+            // from the same digit family, where a digit family is a sequence
+            // of ten consecutive characters in Unicode category Nd, having
+            // digit values 0 through 9.
+            //
+            throw XQUERY_EXCEPTION(
+              err::FOFD1340,
+              ERROR_PARAMS(
+                picture_str,
+                ZED( FOFD1340_DigitNotSameFamily_34 ),
+                unicode::printable_cp( cp ),
+                unicode::printable_cp( zero[1] )
+              ),
+              ERROR_LOC( loc )
+            );
+          }
+          //
+          // Ibid: A format token containing more than one digit, such as 001
+          // or 9999, sets the minimum and maximum width to the number of
+          // digits appearing in the format token.
+          //
+          if ( !mod->min_width )
+            mod->min_width = mod->max_width = 2;
+          else
+            mod->min_width = ++mod->max_width;
+        } else
+          got_mandatory_digit = true;
+        got_grouping_separator = false;
+      } else if ( cp == ';' || cp == ']' )
+        break;
+      else if ( unicode::is_space( cp ) )
+        continue;
+      else if ( is_grouping_separator( cp ) ) {
+        if ( cp == ',' && !--commas ) {
+          //
+          // Ibid: if a variable marker contains one or more commas, then the
+          // last comma is treated as introducing the width modifier, and all
+          // others are treated as grouping separators.
+          //
+          break;
+        }
+        if ( got_grouping_separator ) {
+          //
+          // Ibid: A grouping-separator-sign must not appear ... adjacent to
+          // another grouping-separator-sign.
+          //
+          throw XQUERY_EXCEPTION(
+            err::FOFD1340,
+            ERROR_PARAMS(
+              picture_str,
+              ZED( FOFD1340_NoAdjacentGroupSep_3 ),
+              unicode::printable_cp( cp )
+            ),
+            ERROR_LOC( loc )
+          );
+        }
+        got_grouping_separator = true;
+        mod->first.has_grouping_separators = true;
+      } else
+        break;
+
+      u_mod_format += cp;
+    } // while
+    if ( got_grouping_separator ) {
+      //
+      // Ibid: A grouping-separator-sign must not appear at the ... end of the
+      // decimal-digit-pattern ....
+      //
+      throw XQUERY_EXCEPTION(
+        err::FOFD1340,
+        ERROR_PARAMS(
+          picture_str,
+          ZED( FOFD1340_NoGroupSepAtEnd_3 ),
+          unicode::printable_cp( cp )
+        ),
+        ERROR_LOC( loc )
+      );
+    }
+    if ( !got_mandatory_digit ) {
+      //
+      // Ibid: There must be at least one mandatory-digit-sign.
+      //
+      throw XQUERY_EXCEPTION(
+        err::FOFD1340,
+        ERROR_PARAMS( picture_str, ZED( FOFD1340_MustBeOneMandatoryDigit ) ),
+        ERROR_LOC( loc )
+      );
+    }
+    mod->first.zero = zero[0];
+    j = u.base();
+  } else {
+    switch ( *j++ ) {
+      case 'A':
+        mod->first.type = modifier::ALPHA;
+        break;
+      case 'a':
+        mod->first.type = modifier::alpha;
+        break;
+      case 'I':
+        mod->first.type = modifier::ROMAN;
+        break;
+      case 'i':
+        mod->first.type = modifier::roman;
+        break;
+      case 'N':
+        if ( j != picture_str.end() && *j == 'n' )
+          mod->first.type = modifier::Name, ++j;
+        else
+          mod->first.type = modifier::NAME;
+        break;
+      case 'n':
+        mod->first.type = modifier::name;
+        break;
+      case 'W':
+        if ( j != picture_str.end() && *j == 'w' )
+          mod->first.type = modifier::Words, ++j;
+        else
+          mod->first.type = modifier::WORDS;
+        break;
+      case 'w':
+        mod->first.type = modifier::words;
+        break;
+      case 'Z':
+        mod->first.type = modifier::military_tz;
+        break;
+      default:
+        //
+        // Ibid: If an implementation does not support a numbering sequence
+        // represented by the given token, it must use a format token of 1.
+        //
+        mod->first.type = modifier::arabic;
+    } // switch
+  }
+  mod->first.parsed = true;
+}
+
+static void parse_second_modifier( zstring const &picture_str,
+                                   zstring::const_iterator *i, modifier *mod,
+                                   QueryLoc const &loc ) {
+  zstring::const_iterator &j = *i;
+  ascii::skip_whitespace( picture_str, &j );
+  if ( j == picture_str.end() )
+    return;
+  switch ( *j ) {
+    case 'c': mod->second.co_type = modifier::cardinal   ; break;
+    case 'o': mod->second.co_type = modifier::ordinal    ; break;
+    case 'a': mod->second.at_type = modifier::alphabetic ; ++j; return;
+    case 't': mod->second.at_type = modifier::traditional; ++j; return;
+    default : return;
+  }
+  if ( ++j == picture_str.end() )
+    return;
+  if ( *j == '(' ) {
+    while ( true ) {
+      if ( ++j == picture_str.end() )
+        throw XQUERY_EXCEPTION(
+          err::FOFD1340,
+          ERROR_PARAMS( picture_str, ZED( CharExpected_3 ), ')' ),
+          ERROR_LOC( loc )
+        );
+      if ( *j == ')' )
+        break;
+      mod->second.co_string += *j;
+    } 
+    ++j;
+  }
+}
+
+static void parse_width_modifier( zstring const &picture_str,
+                                  zstring::const_iterator *i, modifier *mod,
+                                  QueryLoc const &loc ) {
+  zstring::const_iterator &j = *i;
+
+  ascii::skip_whitespace( picture_str, &j );
+  if ( j == picture_str.end() || (*j != ',' && *j != ';') )
+    return;
+  ascii::skip_whitespace( picture_str, &++j );
+  if ( j == picture_str.end() )
+    goto bad_width_modifier;
+  if ( *j == '*' ) {
+    mod->min_width = 0;
+    ++j;
+  } else {
+    try {
+      mod->min_width = static_cast<modifier::width_type>(
+        ztd::atoull( j, picture_str.end(), &j )
+      );
+    }
+    catch ( std::exception const& ) {
+      goto bad_width_modifier;
+    }
+  }
+
+  mod->max_width = 0;
+
+  ascii::skip_whitespace( picture_str, &j );
+  if ( j == picture_str.end() || *j != '-' )
+    return;
+  ascii::skip_whitespace( picture_str, &++j );
+  if ( j == picture_str.end() )
+    goto bad_width_modifier;
+  if ( *j == '*' )
+    ++j;
+  else {
+    try {
+      mod->max_width = static_cast<modifier::width_type>(
+        ztd::atoull( j, picture_str.end(), &j )
+      );
+    }
+    catch ( std::exception const& ) {
+      goto bad_width_modifier;
+    }
+  }
+
+  return;
+
+bad_width_modifier:
+  throw XQUERY_EXCEPTION(
+    err::FOFD1340,
+    ERROR_PARAMS( picture_str, ZED( FOFD1340_BadWidthModifier ) ),
+    ERROR_LOC( loc )
+  );
+}
+
+static int get_data_type( char component ) {
+  switch ( component ) {
+    case 'D': return DateTime::DAY_DATA;
+    case 'd': return DateTime::DAY_DATA;
+    case 'E': return DateTime::YEAR_DATA;
+    case 'F': return DateTime::DAY_DATA;
+    case 'f': return DateTime::FRACSECONDS_DATA;
+    case 'H': return DateTime::HOUR_DATA;
+    case 'h': return DateTime::HOUR_DATA;
+    case 'm': return DateTime::MINUTE_DATA;
+    case 'M': return DateTime::MONTH_DATA;
+    case 'P': return DateTime::HOUR_DATA;
+    case 's': return DateTime::SECONDS_DATA;
+    case 'W': return DateTime::DAY_DATA;
+    case 'w': return DateTime::DAY_DATA;
+    case 'Y': return DateTime::YEAR_DATA;
+    default : return -1;
+  }
+}
+
+bool FnFormatDateTimeIterator::nextImpl( store::Item_t& result,
+                                         PlanState &planState ) const {
+  zstring picture_str, result_str, item_str;
+  xs_dateTime dateTime;
+  calendar::type cal = calendar::unknown;
+  iso639_1::type lang = iso639_1::unknown;
+  iso3166_1::type country = iso3166_1::unknown;
+  bool cal_is_fallback = false, lang_is_fallback = false;
+  bool in_variable_marker;
+  store::Item_t item;
+  PlanIteratorState *state;
+
+  DEFAULT_STACK_INIT( PlanIteratorState, state, planState);
+
+  if ( !consumeNext( item, theChildren[0].getp(), planState ) ) {
+    // Got the empty sequence -- return same
+    STACK_PUSH( false, state );
+  } else {
+    dateTime = item->getDateTimeValue();
+    consumeNext( item, theChildren[1].getp(), planState );
+    item->getStringValue2( picture_str );
+
+    if ( theChildren.size() > 2 ) {
+      consumeNext( item, theChildren[2].getp(), planState );
+      if ( !locale::parse( item->getStringValue(), &lang, &country ) ||
+           !locale::is_supported( lang, country ) ) {
+        lang = iso639_1::unknown;
+        lang_is_fallback = true;
+      }
+
+      consumeNext( item, theChildren[3].getp(), planState );
+      item->getStringValue2( item_str );
+      // TODO: handle calendar being a QName.
+      cal = calendar::find( item_str );
+      if ( !cal )
+        cal_is_fallback = true;
+
+      consumeNext( item, theChildren[4].getp(), planState );
+      item->getStringValue2( item_str );
+      // TODO: do something with place
+    }
+
+    if ( !cal ) {
+      //
+      // XQuery 3.0 F&O: 9.8.4.3: If the $calendar argument is omitted or is
+      // set to an empty sequence then the default calendar defined in the
+      // dynamic context is used.
+      //
+      cal = planState.theLocalDynCtx->get_calendar();
+    }
+
+    if ( !lang ) {
+      //
+      // Ibid: If the $language argument is omitted or is set to an empty
+      // sequence, or if it is set to an invalid value or a value that the
+      // implementation does not recognize, then the processor uses the default
+      // language defined in the dynamic context.
+      //
+      planState.theLocalDynCtx->get_locale( &lang, &country );
+    }
+
+    char component;
+    in_variable_marker = false;
+
+    FOR_EACH( zstring, i, picture_str ) {
+      if ( !in_variable_marker ) {
+        switch ( *i ) {
+          case '[':
+            if ( ztd::peek( picture_str, i ) == '[' )
+              ++i;
+            else {
+              component = 0;
+              in_variable_marker = true;
+              continue;
+            }
+            break;
+          case ']':
+            if ( ztd::peek( picture_str, i ) == ']' )
+              ++i;
+            break;
+        }
+        result_str += *i;
+        continue;
+      }
+
+      if ( ascii::is_space( *i ) )
+        continue;                       // ignore all whitespace
+
+      switch ( *i ) {
+        case ']':
+          if ( !component )
+            throw XQUERY_EXCEPTION(
+              err::FOFD1340,
+              ERROR_PARAMS( picture_str, ZED( FOFD1340_NoComponent ) ),
+              ERROR_LOC( loc )
+            );
+          component = 0;
+          in_variable_marker = false;
+          continue;
+        case 'C':
+        case 'D':
+        case 'd':
+        case 'E':
+        case 'F':
+        case 'f':
+        case 'H':
+        case 'h':
+        case 'M':
+        case 'm':
+        case 'P':
+        case 's':
+        case 'W':
+        case 'w':
+        case 'Y':
+        case 'Z':
+        case 'z':
+#if 0
+          if ( component )
+            throw XQUERY_EXCEPTION(
+              err::FOFD1340,
+              ERROR_PARAMS(
+                picture_str, ZED( FOFD1340_MultipleComponent_3 ), *i
+              ),
+              ERROR_LOC( loc )
+            );
+#endif
+          component = *i;
+          break;
+        default:
+          throw XQUERY_EXCEPTION(
+            err::FOFD1340,
+            ERROR_PARAMS( picture_str, ZED( FOFD1340_BadComponent_3 ), *i ),
+            ERROR_LOC( loc )
+          );
+      } // switch
+      if ( ++i == picture_str.end() )
+        goto eos;
+
+      modifier mod;
+      mod.lang = lang;
+      mod.lang_is_fallback = lang_is_fallback;
+      mod.country = country;
+      mod.cal = cal;
+      mod.cal_is_fallback = cal_is_fallback;
+
+      if ( *i != ']' ) {
+        parse_first_modifier( picture_str, &i, &mod, loc );
+        if ( i == picture_str.end() )
+          goto eos;
+        if ( *i != ']' ) {
+          parse_second_modifier( picture_str, &i, &mod, loc );
+          if ( i == picture_str.end() )
+            goto eos;
+          parse_width_modifier( picture_str, &i, &mod, loc );
+          if ( i == picture_str.end() )
+            goto eos;
+        }
+      }
+      if ( *i == ']' )
+        --i;
+
+      int const data_type = get_data_type( component );
+      if ( data_type != -1 && !DateTime::FACET_MEMBERS[facet_type][data_type] )
+        throw XQUERY_EXCEPTION(
+          err::FOFD1350, ERROR_PARAMS( component ), ERROR_LOC( loc )
+        );
+
+      switch ( component ) {
+        case 'C': { // calendar
+          modifier mod_copy( mod );
+          if ( !mod.first.parsed )
+            mod_copy.first.type = modifier::name;
+          append_string( "gregorian", mod_copy, &result_str );
+          break;
+        }
+        case 'D':
+          append_number( dateTime.getDay(), mod, &result_str );
+          break;
+        case 'd':
+          append_number( dateTime.getDayOfYear(), mod, &result_str );
+          break;
+        case 'E': { // era
+          modifier mod_copy( mod );
+          if ( !mod.first.parsed )
+            mod_copy.first.type = modifier::name;
+          int const year = dateTime.getYear();
+          zstring const era( year > 0 ? "ad" : year < 0 ? "bc" : "" );
+          append_string( era, mod_copy, &result_str );
+          break;
+        }
+        case 'F': {
+          modifier mod_copy( mod );
+          if ( !mod.first.parsed )
+            mod_copy.first.type = modifier::name;
+          append_weekday(
+            dateTime.getDay(), dateTime.getMonth() - 1, dateTime.getYear(),
+            mod_copy, &result_str
+          );
+          break;
+        }
+        case 'f':
+          append_fractional_seconds(
+            dateTime.getFractionalSeconds(), mod, &result_str
+          );
+          break;
+        case 'H': // hour (24 hours)
+          append_number( dateTime.getHours(), mod, &result_str );
+          break;
+        case 'h': // hour (12 hours)
+          // Convert hour from:  0 1 ... 12 13 ... 23
+          //                to: 12 1 ... 12  1 ... 11
+          append_number(
+            1 + (11 + dateTime.getHours()) % 12, mod, &result_str
+          );
+          break;
+        case 'M':
+          append_month( dateTime.getMonth() - 1, mod, &result_str );
+          break;
+        case 'm': {
+          modifier mod_copy( mod );
+          mod_copy.set_default_width( 2 );
+          append_number( dateTime.getMinutes(), mod_copy, &result_str );
+          break;
+        }
+        case 'P': {
+          modifier mod_copy( mod );
+          if ( !mod.first.parsed )
+            mod_copy.first.type = modifier::name;
+          append_string(
+            locale::get_time_ampm( dateTime.getHours() >= 12, lang, country ),
+            mod_copy, &result_str
+          );
+          break;
+        }
+        case 's': {
+          modifier mod_copy( mod );
+          mod_copy.set_default_width( 2 );
+          append_number( dateTime.getIntSeconds(), mod_copy, &result_str );
+          break;
+        }
+        case 'W':
+          append_week_in_year(
+            dateTime.getDay(), dateTime.getMonth() - 1, dateTime.getYear(),
+            mod, &result_str
+          );
+          break;
+        case 'w':
+          append_number( dateTime.getWeekInMonth(), mod, &result_str );
+          break;
+        case 'Y':
+          append_year( std::abs( dateTime.getYear() ), mod, &result_str );
+          break;
+        case 'Z':
+        case 'z':
+          append_timezone(
+            component, dateTime.getTimezone(), mod, &result_str
+          );
+          break;
+      } // switch
+    } // for
+
+    if ( in_variable_marker )
+eos:  throw XQUERY_EXCEPTION(
+        err::FOFD1340,
+        ERROR_PARAMS( picture_str, ZED( CharExpected_3 ), ']' ),
+        ERROR_LOC( loc )
+      );
+
+    STACK_PUSH( GENV_ITEMFACTORY->createString( result, result_str ), state );
+  }
+
+  STACK_END( state );
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+} // namespace zorba
+/* vim:set et sw=2 ts=2: */

=== added file 'src/runtime/durations_dates_times/format_dateTime.h'
--- src/runtime/durations_dates_times/format_dateTime.h	1970-01-01 00:00:00 +0000
+++ src/runtime/durations_dates_times/format_dateTime.h	2013-03-20 21:54:22 +0000
@@ -0,0 +1,81 @@
+/*
+ * 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_RUNTIME_FORMAT_DATETIME_H
+#define ZORBA_RUNTIME_FORMAT_DATETIME_H
+
+#include "common/shared_types.h"
+#include "zorbatypes/datetime.h"
+
+#include "runtime/base/binarybase.h"
+#include "runtime/base/unarybase.h"
+#include "runtime/base/narybase.h"
+
+namespace zorba {
+
+///////////////////////////////////////////////////////////////////////////////
+
+// XQuery 3.0 DateTime formatting
+class FnFormatDateTimeIterator :
+  public NaryBaseIterator<FnFormatDateTimeIterator,PlanIteratorState>
+{
+
+public:
+  SERIALIZABLE_CLASS(FnFormatDateTimeIterator);
+
+  SERIALIZABLE_CLASS_CONSTRUCTOR2T(
+  FnFormatDateTimeIterator,
+  NaryBaseIterator<FnFormatDateTimeIterator, PlanIteratorState >);
+
+  void serialize( ::zorba::serialization::Archiver &ar )
+  {
+    serialize_baseclass(ar,
+    (NaryBaseIterator<FnFormatDateTimeIterator, PlanIteratorState >*)this);
+
+    SERIALIZE_ENUM(DateTime::FACET_TYPE, facet_type);
+  }
+
+public:
+  FnFormatDateTimeIterator(
+        static_context *sctx,
+        QueryLoc const &loc,
+        std::vector<PlanIter_t> &aChildren,
+        DateTime::FACET_TYPE a_facet_type = DateTime::DATETIME_FACET)
+    :
+    NaryBaseIterator<FnFormatDateTimeIterator, PlanIteratorState>(sctx, loc, aChildren),
+    facet_type(a_facet_type)
+  {
+  }
+
+  void accept( PlanIterVisitor& ) const;
+
+  bool nextImpl( store::Item_t&, PlanState& ) const;
+
+private:
+  DateTime::FACET_TYPE facet_type;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+
+} // namespace zorba
+
+#endif /* ZORBA_RUNTIME_FORMAT_DATETIME_H */
+/*
+ * Local variables:
+ * mode: c++
+ * End:
+ */
+/* vim:set et sw=2 ts=2: */

=== modified file 'src/runtime/visitors/printer_visitor_impl.cpp'
--- src/runtime/visitors/printer_visitor_impl.cpp	2013-03-05 12:34:19 +0000
+++ src/runtime/visitors/printer_visitor_impl.cpp	2013-03-20 21:54:22 +0000
@@ -46,6 +46,7 @@
 #include "runtime/core/arithmetic_impl.h"
 #include "runtime/sequences/SequencesImpl.h"
 #include "runtime/durations_dates_times/DurationsDatesTimesImpl.h"
+#include "runtime/durations_dates_times/format_dateTime.h"
 #ifdef ZORBA_WITH_DEBUGGER
 #include "runtime/debug/debug_iterator.h"
 #endif

=== modified file 'src/unit_tests/CMakeLists.txt'
--- src/unit_tests/CMakeLists.txt	2013-02-26 04:12:43 +0000
+++ src/unit_tests/CMakeLists.txt	2013-03-20 21:54:22 +0000
@@ -21,6 +21,7 @@
   test_mem_sizeof.cpp
   test_parameters.cpp
   test_string.cpp
+  test_time.cpp
   test_time_parse.cpp
   test_uri.cpp
   test_uuid.cpp

=== added file 'src/unit_tests/test_time.cpp'
--- src/unit_tests/test_time.cpp	1970-01-01 00:00:00 +0000
+++ src/unit_tests/test_time.cpp	2013-03-20 21:54:22 +0000
@@ -0,0 +1,118 @@
+/*
+ * 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/ascii_util.h"
+#include "util/stl_util.h"
+#include "util/time_util.h"
+#include "zorbatypes/zstring.h"
+
+using namespace std;
+using namespace zorba;
+using namespace zorba::time;
+
+///////////////////////////////////////////////////////////////////////////////
+
+static int failures;
+static int test_no;
+
+static bool assert_true( int no, char const *expr, int line, bool result ) {
+  if ( !result ) {
+    cout << '#' << no << " FAILED, line " << line << ": " << expr << endl;
+    ++failures;
+  }
+  return result;
+}
+
+#define ASSERT_TRUE( NO, EXPR ) assert_true( NO, #EXPR, __LINE__, !!(EXPR) )
+
+///////////////////////////////////////////////////////////////////////////////
+
+static void test_calc_week_in_year() {
+  struct test_type {
+    unsigned mday, mon, year;
+    time::calendar::type cal;
+    int expected;
+  };
+  static test_type const test[] = {
+    /*  1 */ {  1, time::jan, 2013, calendar::AD,  1 },
+    /*  2 */ {  2, time::jan, 2013, calendar::AD,  1 },
+    /*  3 */ {  3, time::jan, 2013, calendar::AD,  1 },
+    /*  4 */ {  4, time::jan, 2013, calendar::AD,  1 },
+    /*  5 */ {  5, time::jan, 2013, calendar::AD,  1 },
+    /*  6 */ {  6, time::jan, 2013, calendar::AD,  2 },
+    /*  7 */ { 28, time::dec, 2013, calendar::AD, 52 },
+    /*  8 */ { 31, time::dec, 2013, calendar::AD, 53 },
+
+    /*  9 */ {  1, time::jan, 2013, calendar::ISO,  1 },
+    /* 10 */ {  2, time::jan, 2013, calendar::ISO,  1 },
+    /* 11 */ {  3, time::jan, 2013, calendar::ISO,  1 },
+    /* 12 */ {  4, time::jan, 2013, calendar::ISO,  1 },
+    /* 13 */ {  5, time::jan, 2013, calendar::ISO,  1 },
+    /* 14 */ {  6, time::jan, 2013, calendar::ISO,  1 },
+    /* 15 */ {  7, time::jan, 2013, calendar::ISO,  2 },
+
+    // Test cases taken from http://en.wikipedia.org/wiki/ISO_week_date
+    /* 16 */ {  1, time::jan, 2005, calendar::ISO, 53 },
+    /* 17 */ {  2, time::jan, 2005, calendar::ISO, 53 },
+    /* 18 */ { 31, time::dec, 2005, calendar::ISO, 52 },
+    /* 19 */ {  1, time::jan, 2007, calendar::ISO,  1 },
+    /* 20 */ { 30, time::dec, 2007, calendar::ISO, 52 },
+    /* 21 */ { 31, time::dec, 2007, calendar::ISO,  1 },
+    /* 22 */ {  1, time::jan, 2008, calendar::ISO,  1 },
+    /* 23 */ { 28, time::dec, 2008, calendar::ISO, 52 },
+    /* 24 */ { 29, time::dec, 2008, calendar::ISO,  1 },
+    /* 25 */ { 30, time::dec, 2008, calendar::ISO,  1 },
+    /* 26 */ { 31, time::dec, 2008, calendar::ISO,  1 },
+    /* 27 */ { 31, time::dec, 2009, calendar::ISO, 53 },
+    /* 28 */ {  1, time::jan, 2010, calendar::ISO, 53 },
+    /* 29 */ {  2, time::jan, 2010, calendar::ISO, 53 },
+    /* 30 */ {  3, time::jan, 2010, calendar::ISO, 53 },
+    /* 31 */ {  4, time::jan, 2010, calendar::ISO,  1 },
+
+    {  0 },
+  };
+
+  for ( test_type const *t = test; t->mday; ++t ) {
+    int w = calendar::calc_week_in_year( t->mday, t->mon, t->year, t->cal );
+    ++test_no;
+    ASSERT_TRUE( test_no,  w == t->expected );
+  }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+namespace zorba {
+namespace UnitTests {
+
+int test_time( int, char*[] ) {
+
+  test_calc_week_in_year();
+
+  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	2013-02-26 04:12:43 +0000
+++ src/unit_tests/unit_test_list.h	2013-03-20 21:54:22 +0000
@@ -40,6 +40,7 @@
   int test_mem_sizeof( int, char*[] );
   int test_parameters( int, char*[] );
   int test_string( int, char*[] );
+  int test_time( int, char*[] );
   int test_time_parse( int, char*[] );
 
 #ifdef ZORBA_WITH_FILE_ACCESS

=== modified file 'src/unit_tests/unit_tests.cpp'
--- src/unit_tests/unit_tests.cpp	2013-02-26 04:12:43 +0000
+++ src/unit_tests/unit_tests.cpp	2013-03-20 21:54:22 +0000
@@ -55,6 +55,7 @@
   libunittests["json_parser"] = test_json_parser;
   libunittests["parameters"] = test_parameters;
   libunittests["string"] = test_string;
+  libunittests["time"] = test_time;
   libunittests["time_parse"] = test_time_parse;
 
 #ifndef ZORBA_NO_FULL_TEXT

=== modified file 'src/util/ascii_util.h'
--- src/util/ascii_util.h	2013-03-18 17:12:00 +0000
+++ src/util/ascii_util.h	2013-03-20 21:54:22 +0000
@@ -22,6 +22,7 @@
 #include <cctype>
 #include <cstddef>
 #include <cstring>
+#include <iterator>
 
 // local
 #include "omanip.h"
@@ -1147,9 +1148,62 @@
   *pos = trim_start_whitespace( s + *pos, s_len - *pos ) - s;
 }
 
+/**
+ * Skips any consecutive whitespace chars that are found at a given starting
+ * position within a given string.
+ *
+ * @tparam StringType The string type.
+ * @param s The string.
+ * @param i A pointer to the iterator to advance past the whitespace.
+ * On return, \a *i is updated with the position of the 1st non-whitespace
+ * char.
+ */
+template<class StringType> inline
+void skip_whitespace( StringType const &s,
+                      typename StringType::const_iterator *i ) {
+  typename StringType::difference_type const d = *i - s.begin();
+  char const *const sd = s.data() + d;
+  std::advance( *i, trim_start_whitespace( sd, s.size() - d ) - sd );
+}
+
 ////////// Miscellaneous //////////////////////////////////////////////////////
 
 /**
+ * Pads a string to the left with a given character until the string is the
+ * given width.
+ *
+ * @param s The string to pad.
+ * @param width The width to pad to.
+ * @param c The character to pad with.
+ * @return Returns \c *s.
+ */
+template<class StringType> inline
+StringType& left_pad( StringType *s, typename StringType::size_type width,
+                      char c ) {
+  typedef typename StringType::size_type size_type;
+  if ( s->size() < width )
+    s->insert( static_cast<size_type>( 0 ), width - s->size(), c );
+  return *s;
+}
+
+/**
+ * Pads a string to the right with a given character until the string is the
+ * given width.
+ *
+ * @param s The string to pad.
+ * @param width The width to pad to.
+ * @param c The character to pad with.
+ * @return Returns \c *s.
+ */
+template<class StringType> inline
+StringType& right_pad( StringType *s, typename StringType::size_type width,
+                       char c ) {
+  if ( s->size() < width )
+    s->append( width - s->size(), c );
+  return *s;
+}
+
+/**
  * Prints the given character in a printable way: if \c is_print(c) is \c true,
  * prints \a c as-is; otherwise prints \c #x followed by the hexadecimal value
  * of the character.

=== modified file 'src/util/stream_util.cpp'
--- src/util/stream_util.cpp	2013-02-12 03:55:18 +0000
+++ src/util/stream_util.cpp	2013-03-20 21:54:22 +0000
@@ -53,5 +53,38 @@
 
 ///////////////////////////////////////////////////////////////////////////////
 
+ostream& roman( ostream &o, unsigned n ) {
+  //
+  // Based on http://rosettacode.org/wiki/Roman_numerals/Encode#C.2B.2B
+  //
+  struct roman_data {
+    unsigned value;
+    char const *numeral[2];
+  };
+  static roman_data const data[] = {
+    1000, {  "m",  "M" },
+     900, { "cm", "CM" },
+     500, {  "d",  "D" },
+     400, { "cd", "CD" },
+     100, {  "c",  "C" },
+      90, { "xc", "XC" },
+      50, {  "l",  "L" },
+      40, { "xl", "XL" },
+      10, {  "x",  "X" },
+       9, { "ix", "IX" },
+       5, {  "v",  "V" },
+       4, { "iv", "IV" },
+       1, {  "i",  "I" },
+       0, {    0,    0 }
+  };
+  bool const uc = !!(o.flags() & ios::uppercase);
+  for ( roman_data const *r = data; r->value > 0; ++r )
+    for ( ; n >= r->value; n -= r->value )
+      o << r->numeral[ uc ];
+  return o;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
 } // namespace zorba
 /* vim:set et sw=2 ts=2: */

=== modified file 'src/util/stream_util.h'
--- src/util/stream_util.h	2013-02-12 03:55:18 +0000
+++ src/util/stream_util.h	2013-03-20 21:54:22 +0000
@@ -20,6 +20,7 @@
 
 #include <iostream>
 
+#include "omanip.h"
 #include "string_util.h"
 
 namespace zorba {
@@ -61,6 +62,21 @@
 
 ///////////////////////////////////////////////////////////////////////////////
 
+/**
+ * Emits an integer as Roman numerals to the given ostream.  By default,
+ * numerals are emitted in lower-case.  To emit in upper-case, set the
+ * \c uppercase format flag on the stream.
+ *
+ * @param o The ostream to emit to.
+ * @param n The integer to emit.
+ * @return Returns \a o.
+ */
+std::ostream& roman( std::ostream &o, unsigned n );
+
+DEF_OMANIP1( roman, unsigned )
+
+///////////////////////////////////////////////////////////////////////////////
+
 } // namespace zorba
 
 #endif /* ZORBA_STREAM_UTIL_H */

=== modified file 'src/util/time_util.cpp'
--- src/util/time_util.cpp	2013-02-13 01:57:47 +0000
+++ src/util/time_util.cpp	2013-03-20 21:54:22 +0000
@@ -16,7 +16,9 @@
 
 #include "stdafx.h"
 
+#include <algorithm>
 #include <cassert>
+#include <cstring>
 #ifdef WIN32
 # include <windows.h>
 # include <time.h>                      /* for gmtime_s() */
@@ -33,11 +35,135 @@
 // local
 #include "time_util.h"
 
+#define DEF_END(CHAR_ARRAY)                             \
+  static char const *const *const end =                 \
+    CHAR_ARRAY + sizeof( CHAR_ARRAY ) / sizeof( char* )
+
+#define FIND(WHAT) \
+  static_cast<type>( find_index( string_of, end, WHAT ) )
+
+using namespace std;
+
+/**
+ * A less-verbose way to use std::lower_bound.
+ */
+inline int find_index( char const *const *begin, char const *const *end,
+                       char const *s ) {
+  char const *const *const entry =
+    ::lower_bound( begin, end, s, less<char const*>() );
+  return entry != end && ::strcmp( s, *entry ) == 0 ? entry - begin : 0;
+}
+
 namespace zorba {
 namespace time {
 
 ///////////////////////////////////////////////////////////////////////////////
 
+namespace iso8601 {
+  /**
+   * Weekday values as used by the ISO 8601 specification.
+   */
+  enum weekday {
+    mon = 1,
+    tue = 2,
+    wed = 3,
+    thu = 4,
+    fri = 5,
+    sat = 6,
+    sun = 7
+  };
+}
+
+namespace calendar {
+
+char const *const string_of[] = {
+  "#UNKNOWN",
+  "AD",   // Anno Domini (Christian Era)
+  "AH",   // Anno Hegirae (Muhammedan Era)
+  "AM",   // Anno Mundi (Jewish)
+  "AME",  // Mauludi Era (solar years since Mohammed's birth)
+  "AP",   // Anno Persici
+  "AS",   // Aji Saka Era (Java)
+  "BE",   // Buddhist Era
+  "CB",   // Cooch Behar Era
+  "CE",   // Common Era
+  "CL",   // Chinese Lunar Era
+  "CS",   // Chula Sakarat Era
+  "EE",   // Ethiopian Era
+  "FE",   // Fasli Era
+  "ISO",  // ISO 8601 calendar
+  "JE",   // Japanese
+  "KE",   // Khalsa Era (Sikh calendar)
+  "KY",   // Kali Yuga
+  "ME",   // Malabar Era
+  "MS",   // Monarchic Solar Era
+  "OS",   // Old Style (Julian)
+  "RS",   // Rattanakosin (Bangkok) Era
+  "SE",   // Saka Era
+  "SH",   // Mohammedan Solar Era (Iran)
+  "SS",   // Saka Samvat
+  "TE",   // Tripurabda Era
+  "VE",   // Vikrama Era
+  "VS"    // Vikrama Samvat Era
+};
+
+int calc_week_in_year( unsigned mday, unsigned mon, unsigned year, type cal ) {
+  int yday = time::calc_yday( mday, mon, year );
+  int jan1_wday = time::calc_wday( 1, time::jan, year );
+
+  switch ( cal ) {
+    case AD:
+      return (jan1_wday + yday) / 7 + 1;
+    case ISO: {
+      // Based on http://www.personal.ecu.edu/mccartyr/ISOwdALG.txt
+      ++yday; // code assumes [1-366]
+      jan1_wday = convert_wday_to( jan1_wday, cal );
+
+      if ( jan1_wday > iso8601::thu && jan1_wday + yday <= 8 ) {
+        // date falls in week 52 or 53 of the previous year
+        return  52
+              + (jan1_wday == iso8601::fri ||
+                (jan1_wday == iso8601::sat && time::is_leap_year( year - 1 )));
+      }
+      int const wday =
+        convert_wday_to( time::calc_wday( mday, mon, year ), cal );
+      if ( time::days_in_year( year ) - yday < 4 - wday ) {
+        // date falls in week 1 of the next year
+        return 1;
+      }
+      return  (yday + (7 - wday) + (jan1_wday - 1)) / 7
+            - (jan1_wday > iso8601::thu);
+    }
+    default:
+      return -1;
+  }
+}
+
+int convert_wday_from( unsigned wday, type from ) {
+  switch ( from ) {
+    case AD : return static_cast<int>( wday );
+    case ISO: return wday == iso8601::sun ? time::sun : wday;
+    default : return -1;
+  }
+}
+
+int convert_wday_to( unsigned wday, type to ) {
+  switch ( to ) {
+    case AD : return static_cast<int>( wday );
+    case ISO: return wday == time::sun ? iso8601::sun : wday;
+    default : return -1;
+  }
+}
+
+type find( char const *calendar ) {
+  DEF_END( string_of );
+  return FIND( calendar );
+}
+
+} // namespace calendar
+
+///////////////////////////////////////////////////////////////////////////////
+
 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
@@ -48,7 +174,7 @@
 
 bool calc_mday_mon( unsigned yday, unsigned *mday, unsigned *mon,
                     unsigned year ) {
-  assert( yday < 365 + is_leap_year( year ) );
+  assert( yday < days_in_year( year ) );
 
   unsigned const *const ym = yday_mon[ is_leap_year( year ) ];
   for ( unsigned m = 1; m <= 12; ++m ) 
@@ -107,26 +233,26 @@
  * @param year Year.
  * @return Returns the weekday where 0 = Sunday.
  */
-unsigned calc_wday( unsigned mday, unsigned mon, unsigned year ) {
+int 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;
+  int const a = (14 - mon) / 12;
+  int const y = year - a;
+  int 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 ) {
+int 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;
+  return (int)yday_mon[ is_leap_year( year ) ][ mon ] + mday - 1;
 }
 
-unsigned days_in_month( unsigned mon, unsigned year ) {
-  static unsigned const days[] = {
+int days_in_month( unsigned mon, unsigned year ) {
+  static int const days[] = {
     31, //  0: Jan
     28, //  1: Feb
     31, //  2: Mar
@@ -141,7 +267,7 @@
     31  // 11: Dec
   };
   assert( mon < 12 );
-  return days[ mon ] + (mon == 1 /* Feb */ && is_leap_year( year ));
+  return days[ mon ] + (mon == feb && is_leap_year( year ));
 }
 
 void get_epoch( sec_type *sec, usec_type *usec ) {
@@ -202,6 +328,17 @@
 #endif /* WIN32 */
 }
 
+char get_military_tz( int hour ) {
+  hour %= 24;
+  if ( hour > 12 )
+    hour -= 24;
+  else if ( hour < -12 )
+    hour += 24;
+  if ( hour >= 0 && hour <= 12 )
+    return "ZABCDEFGHIKLM" [ hour ];    // no 'J' here (it means "no timezone")
+  return " NOPQRSTUVWXY" [ -hour ];
+}
+
 ///////////////////////////////////////////////////////////////////////////////
 
 } // namespace time

=== modified file 'src/util/time_util.h'
--- src/util/time_util.h	2013-02-13 01:57:47 +0000
+++ src/util/time_util.h	2013-03-20 21:54:22 +0000
@@ -25,7 +25,9 @@
 
 // Zorba
 #include <zorba/config.h>
+#include <zorba/time.h>
 #include "cxx_util.h"
+#include "string_util.h"
 
 #ifndef TM_YEAR_BASE
 # define TM_YEAR_BASE 1900
@@ -36,14 +38,22 @@
 
 ///////////////////////////////////////////////////////////////////////////////
 
+/**
+ * A type to hold a number of seconds (at least since epoch).
+ */
 typedef time_t sec_type;
 
+/**
+ * A type to hold a number of microseconds.
+ */
 #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
@@ -71,12 +81,129 @@
 ///////////////////////////////////////////////////////////////////////////////
 
 /**
+ * XQuery 3.0 F&O: 9.8.4.3: The calendars listed below were known to be in use
+ * during the last hundred years.
+ */
+namespace calendar {
+  extern char const* const string_of[];
+
+  /**
+   * Emits a calendar::type to an ostream.
+   *
+   * @param o The ostream to emit to.
+   * @param t The type to emit.
+   * @return Returns \a o.
+   */
+  inline std::ostream& operator<<( std::ostream &o, type t ) {
+    return o << string_of[ t ];
+  }
+
+  /**
+   * Calculates the week number for the given date and calendar.
+   *
+   * @param mday The month day [1-31].
+   * @param mon The month [0-11].
+   * @param year The year.
+   * @param cal The calendar.
+   * @return Returns the week [1-53] or -1 if it is unknown how to perform the
+   * calculation for \a cal.
+   */
+  int calc_week_in_year( unsigned mday, unsigned mon, unsigned year, type cal );
+
+  /**
+   * Converts a weekday number from a given calendar to the Unix interpretation
+   * [0-6] where 0 = Sunday.
+   *
+   * @param wday The weekday to convert where the meaning of the value is
+   * determined by \a from.
+   * @param from The calendar designator to convert \a wday from.
+   * @return Returns \a wday converted to \a to or -1 if it is unknown how to
+   * perform the conversion.
+   */
+  int convert_wday_from( unsigned wday, type from );
+
+  /**
+   * Converts a Unix weekday number to a specific calendar.
+   *
+   * @param wday The weekday to convert: [0-6] where 0 = Sunday.
+   * @param to The calendar designator to convert \a wday to.
+   * @return Returns \a wday converted to \a to or -1 if it is unknown how to
+   * perform the conversion.
+   */
+  int convert_wday_to( unsigned wday, type to );
+
+  /**
+   * Finds a calendar designator from the given string.
+   *
+   * @param calendar The calendar designator to find.  It is presumed to be in
+   * upper-case.
+   * @return Returns said enumeration or \c unknown.
+   */
+  type find( char const *calendar );
+
+  //
+  // Template version of find().
+  //
+  template<class StringType> inline
+  typename std::enable_if<
+    ztd::has_c_str<StringType,char const* (StringType::*)() const>::value,
+    type
+  >::type
+  find( StringType const &country ) {
+    return find( country.c_str() );
+  } 
+
+  /**
+   * Gets the default calendar to use.
+   *
+   * @return Returns said calendar.
+   */
+  inline type get_default() {
+    return AD; // i.e., the Gregorian calendar
+  }
+
+} // namespace calendar
+
+///////////////////////////////////////////////////////////////////////////////
+
+/**
+ * Month (<code>mod</code>) values as used by the \c tm structure.
+ */
+enum month {
+  jan = 0,
+  feb = 1,
+  mar = 2,
+  apr = 3,
+  may = 4,
+  jun = 5,
+  jul = 6,
+  aug = 7,
+  sep = 8,
+  oct = 9,
+  nov = 10,
+  dec = 11
+};
+
+/**
+ * Weekday (<code>wday</code>) values as used by the \c tm structure.
+ */
+enum weekday {
+  sun = 0,
+  mon = 1,
+  tue = 2,
+  wed = 3,
+  thu = 4,
+  fri = 5,
+  sat = 6
+};
+
+/**
  * 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
+ * @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
+ * @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
@@ -88,31 +215,31 @@
 /**
  * Calculates the weekday for the given date.
  *
- * @param mday The month day (1-31).
- * @param mon The month (0-11).
+ * @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.
+ * @return Returns the weekday [0-6] where 0 = Sunday.
  */
-unsigned calc_wday( unsigned mday, unsigned mon, unsigned year );
+int 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 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.
+ * @return Returns the day of the year [0-365] where 0 = January 1.
  */
-unsigned calc_yday( unsigned mday, unsigned mon, unsigned year );
+int calc_yday( unsigned mday, unsigned mon, unsigned year );
 
 /**
  * Gets the number of days in the given month.
  *
- * @param mon The month (0-11).
+ * @param mon The month [0-11].
  * @param year The year.
- * @return Returns said number of days (1-31).
+ * @return Returns said number of days, one of: 28, 29, 30, or 31.
  */
-unsigned days_in_month( unsigned mon, unsigned year );
+int days_in_month( unsigned mon, unsigned year );
 
 /**
  * Gets the number of seconds and microseconds since epoch.
@@ -150,6 +277,14 @@
 void get_localtime( ztm *tm, sec_type when = 0 );
 
 /**
+ * Gets the military timezone letter code for the given GMT hour offset.
+ *
+ * @param hour The number of hours offset from GMT.
+ * @return Returns one of ABCDEFGHIKLMNOPQRSTUVWXYZ (no J).
+ */
+char get_military_tz( int hour );
+
+/**
  * Checks whether the given year is a leap year.
  *
  * @param year The year to check.
@@ -160,10 +295,20 @@
 }
 
 /**
+ * Gets the number of days in the given year.
+ *
+ * @param year The year.
+ * @return Returns said number of days, either: 365 or 366.
+ */
+inline int days_in_year( unsigned year ) {
+  return 365 + is_leap_year( year );
+}
+
+/**
  * Checks whether the given day of the month is valid.
  *
- * @param mday The month day (1-31).
- * @param mon The month (0-11).
+ * @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.
  */
@@ -174,9 +319,9 @@
 /**
  * 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 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.
  */
@@ -188,9 +333,9 @@
 /**
  * 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 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.
  */

=== modified file 'src/util/unicode_util.cpp'
--- src/util/unicode_util.cpp	2013-02-07 17:24:36 +0000
+++ src/util/unicode_util.cpp	2013-03-20 21:54:22 +0000
@@ -28,6 +28,7 @@
 # include <unicode/ustring.h>
 #endif /* ZORBA_NO_ICU */
 
+#include "ascii_util.h"
 #include "cxx_util.h"
 #include "unicode_util.h"
 #include "utf8_util.h"
@@ -2205,6 +2206,23 @@
   return is_case<upper>( c );
 }
 
+ostream& printable_cp( ostream &o, code_point cp ) {
+  if ( ascii::is_print( cp ) )
+    o << static_cast<char>( cp );
+  else
+    switch ( cp ) {
+      case '\n': o << "\\n"; break;
+      case '\r': o << "\\r"; break;
+      case '\t': o << "\\t"; break;
+      default: {
+        ios::fmtflags const old_flags = o.flags();
+        o << "#x" << uppercase << hex << static_cast<uint32_t>( cp );
+        o.flags( old_flags );
+      }
+    }
+  return o;
+}
+
 code_point to_lower( code_point c ) {
   return to_case<lower>( c );
 }

=== modified file 'src/util/unicode_util.h'
--- src/util/unicode_util.h	2013-02-28 11:15:32 +0000
+++ src/util/unicode_util.h	2013-03-20 21:54:22 +0000
@@ -32,6 +32,7 @@
 # include <unicode/unistr.h>
 #endif /* ZORBA_NO_ICU */
 
+#include "omanip.h"
 #include "stl_util.h"
 
 namespace zorba {
@@ -426,6 +427,22 @@
   return c >= 0x10000 && c <= 0x10FFFF;
 }
 
+////////// Miscellaneous //////////////////////////////////////////////////////
+
+/**
+ * Prints the given code-point in a printable way: if \c ascii::is_print(c) is
+ * \c true, prints \a c as-is; otherwise prints \c #x followed by the
+ * hexadecimal value of the character.
+ *
+ * @param o The ostream to print to.
+ * @param cp The \c code-point to print.
+ * @return Returns \a o.
+ */
+std::ostream& printable_cp( std::ostream &o, code_point cp );
+
+// An ostream manipulator version of the above.
+DEF_OMANIP1( printable_cp, code_point )
+
 ///////////////////////////////////////////////////////////////////////////////
 
 } // namespace unicode

=== modified file 'src/util/utf8_string.h'
--- src/util/utf8_string.h	2013-02-07 17:24:36 +0000
+++ src/util/utf8_string.h	2013-03-20 21:54:22 +0000
@@ -207,8 +207,12 @@
   typedef typename StringType::const_pointer const_storage_pointer;
   typedef typename StringType::reference storage_reference;
   typedef typename StringType::const_reference const_storage_reference;
+
   typedef typename StringType::iterator storage_iterator;
   typedef typename StringType::const_iterator const_storage_iterator;
+  typedef typename StringType::reverse_iterator storage_reverse_iterator;
+  typedef typename StringType::const_reverse_iterator
+    const_storage_reverse_iterator;
 
   typedef typename utf8::iterator<storage_iterator> iterator;
   typedef typename utf8::iterator<const_storage_iterator> const_iterator;
@@ -1005,6 +1009,16 @@
   }
 
   /**
+   * Returns a read-only iterator positioned at the same byte as the given
+   * iterator of the string.
+   * 
+   * @return Returns said iterator.
+   */
+  const_iterator current( const_storage_iterator const &i ) const {
+    return const_iterator( i );
+  }
+
+  /**
    * Returns a read-only reverse iterator positioned at the first character
    * (not byte) of the string.
    * 
@@ -1024,6 +1038,17 @@
     return const_reverse_iterator( begin() );
   }
 
+  /**
+   * Returns a read-only reverse iterator positioned at the same byte as the
+   * given reverse iterator of the string.
+   * 
+   * @return Returns said iterator.
+   */
+  const_reverse_iterator
+  current( const_storage_reverse_iterator const &i ) const {
+    return const_reverse_iterator( i );
+  }
+
   ////////// miscellaneous ////////////////////////////////////////////////////
 
   /**

=== modified file 'src/util/utf8_util.cpp'
--- src/util/utf8_util.cpp	2013-02-07 17:24:36 +0000
+++ src/util/utf8_util.cpp	2013-03-20 21:54:22 +0000
@@ -15,6 +15,9 @@
  */
 #include "stdafx.h"
 
+#include <algorithm>
+#include <cstring>
+
 #ifndef ZORBA_NO_ICU
 #include <unicode/ustring.h>
 #endif /* ZORBA_NO_ICU */
@@ -144,6 +147,35 @@
   return len;
 }
 
+storage_type* itou( unsigned long long n, storage_type *buf,
+                    unicode::code_point zero ) {
+  storage_type *s = buf;
+  encoded_char_type utf8_digit[10];     // cache of UTF-8 bytes for each digit
+  size_type utf8_size[10];              // number of UTF-8 bytes for each digit
+
+  std::fill( utf8_size, utf8_size + 10, 0 );
+  do {
+    unsigned long long const n_prev = n;
+    n /= 10;
+    unsigned const digit = n_prev - n * 10;
+    if ( !utf8_size[ digit ] )          // didn't cache previously: cache now
+      utf8_size[ digit ] = encode( zero + digit, utf8_digit[ digit ] );
+    //
+    // Copy the UTF-8 bytes into buf backwards so when we reverse the entire
+    // buffer later (to reverse the digit order to put them the right way
+    // around), we can treat buf as a simple string and ignore multi-byte UTF-8
+    // character boundaries.
+    //
+    for ( size_type i = utf8_size[ digit ]; i; )
+      *s++ = utf8_digit[ digit ][ --i ];
+
+  } while ( n );
+
+  *s = '\0';
+  std::reverse( buf, s );
+  return buf;
+}
+
 size_type length( storage_type const *begin, storage_type const *end ) {
   size_type len = 0;
   while ( begin < end && *begin ) {

=== modified file 'src/util/utf8_util.h'
--- src/util/utf8_util.h	2013-02-07 17:24:36 +0000
+++ src/util/utf8_util.h	2013-03-20 21:54:22 +0000
@@ -306,6 +306,31 @@
   std::copy( u.begin(), u.end(), std::back_inserter( *c ) );
 }
 
+////////// Integer-to-string conversion ///////////////////////////////////////
+
+/**
+ * A type that can hold the largest possible C string equivalent of the largest
+ * possible integral value using any Unicode numeric range within the Nd
+ * ("Number, Decimal Digit") category.
+ */
+typedef storage_type itou_buf_type[
+  (sizeof( encoded_char_type ) - 1 /* subtract null */) * 20 + 1 /* add null */
+];
+
+/**
+ * Converts an <code>unsigned long long</code> to a UTF-8 encoded string.
+ *
+ * @param n The <code>unsigned long long</code> to convert.
+ * @param buf The buffer for the result.  The caller must ensure it's of
+ * sufficient size.
+ * @param zero The Unicode code-point of the zero at the start of a 10
+ * code-point range [zero,zero+9] for the digits to use in the Nd ("Number,
+ * Decimal Digit") category.
+ * @return Returns \a buf for convenience.
+ */
+storage_type* itou( unsigned long long n, storage_type *buf,
+                    unicode::code_point zero );
+
 ////////// Encoding conversion ////////////////////////////////////////////////
 
 #ifndef ZORBA_NO_ICU
@@ -737,6 +762,48 @@
 ////////// Miscellaneous //////////////////////////////////////////////////////
 
 /**
+ * Pads a string to the left with a given code-point until the string is the
+ * given width.
+ *
+ * @param s The string to pad.
+ * @param width The width to pad to.
+ * @param cp The code-point to pad with.
+ * @return Returns \c *s.
+ */
+template<class StringType> inline
+StringType& left_pad( StringType *s, typename StringType::size_type width,
+                      unicode::code_point cp ) {
+  typedef typename utf8_stringify<StringType>::type u_type;
+  typedef typename u_type::size_type u_size_type;
+  u_type u( *s );
+  u_size_type const u_size( u.size() );
+  if ( u_size < width )
+    u.insert( static_cast<size_type>( 0 ), width - u_size, cp );
+  return *s;
+}
+
+/**
+ * Pads a string to the right with a given code-point until the string is the
+ * given width.
+ *
+ * @param s The string to pad.
+ * @param width The width to pad to.
+ * @param cp The code-point to pad with.
+ * @return Returns \c *s.
+ */
+template<class StringType> inline
+StringType& right_pad( StringType *s, typename StringType::size_type width,
+                       unicode::code_point cp ) {
+  typedef typename utf8_stringify<StringType>::type u_type;
+  typedef typename u_type::size_type u_size_type;
+  u_type u( *s );
+  u_size_type const u_size( u.size() );
+  if ( u_size < width )
+    u.append( width - u_size, cp );
+  return *s;
+}
+
+/**
  * Reverses the characters in a string.
  *
  * @tparam InputStringType The input string type.

=== modified file 'src/zorbatypes/datetime.h'
--- src/zorbatypes/datetime.h	2013-03-12 17:03:31 +0000
+++ src/zorbatypes/datetime.h	2013-03-20 21:54:22 +0000
@@ -250,16 +250,10 @@
    */
   static int parseGDay(const char* str, ascii::size_type strlen, DateTime& dt);
 
-  static int getDayOfWeek(int year, int month, int day);
-
   static int getDayOfYear(int year, int month, int day);
 
-  static int getWeekInYear(int year, int month, int day);
-
   static int getWeekInMonth(int year, int month, int day);
 
-  static bool isLeapYear(int year);  
-
 protected:
   static int parse_date(
         const char* str,
@@ -361,11 +355,8 @@
    *  with the index being 0 based, with 0 being Sunday, 1 Monday, etc. If the give 
    *  DateTime does not have a Date or DateTime facet, the function will return -1.
    */ 
-  int getDayOfWeek() const;
   int getDayOfYear() const;
-  int getWeekInYear() const;
   int getWeekInMonth() const;
-  bool isLeapYear() const;
       
 protected:
   Duration* toDayTimeDuration() const;

=== modified file 'src/zorbatypes/datetime/datetimetype.cpp'
--- src/zorbatypes/datetime/datetimetype.cpp	2013-03-12 17:03:31 +0000
+++ src/zorbatypes/datetime/datetimetype.cpp	2013-03-20 21:54:22 +0000
@@ -39,6 +39,7 @@
 #include "zorbatypes/datetime/parse.h"
 
 #include "util/ascii_util.h"
+#include "util/time_util.h"
 
 
 namespace zorba
@@ -47,7 +48,7 @@
 static const char separators[] = { '-', '-', 'T', ':', ':', '.'};
 
 static const char min_length[] = { 4, 2, 2, 2, 2, 2, 0};
-  
+
 
 const int DateTime::FACET_MEMBERS[][8] = 
 {
@@ -79,7 +80,7 @@
 
   for (int i = YEAR_DATA; i <= DAY_DATA; i++)
     data[i] = 1;
-  
+
   for (int i = HOUR_DATA; i <= FRACSECONDS_DATA; i++)
     data[i] = 0;
 
@@ -158,10 +159,10 @@
   dt.data[MINUTE_DATA] = std::abs(minutes);
   dt.data[SECONDS_DATA] = std::floor(std::fabs(seconds));
   dt.data[FRACSECONDS_DATA] = round(frac(std::fabs(seconds)) * FRAC_SECONDS_UPPER_LIMIT);
-  
+
   if (tz != NULL)
     dt.the_time_zone = *tz;
-  
+
   return 0;
 }
 
@@ -185,7 +186,7 @@
   dt.data[MINUTE_DATA] = std::abs(minutes);
   dt.data[SECONDS_DATA] = std::abs(seconds);
   dt.data[FRACSECONDS_DATA] = std::abs(fractional_seconds);
-      
+
   if (tz != NULL)
     dt.the_time_zone = *tz;
 
@@ -211,7 +212,7 @@
 
   if (tz != NULL)
     dt.the_time_zone = *tz;
-  
+
   return 0;
 }
 
@@ -231,10 +232,10 @@
   dt.data[MINUTE_DATA] = std::abs(minutes);
   dt.data[SECONDS_DATA] = std::floor(std::fabs(seconds));
   dt.data[FRACSECONDS_DATA] = round(frac(std::fabs(seconds)) * FRAC_SECONDS_UPPER_LIMIT);
-      
+
   if (tz != NULL)
     dt.the_time_zone = *tz;
-  
+
   return 0;
 }
 
@@ -352,7 +353,7 @@
   ascii::skip_whitespace(str, len, &pos);
 
   dt.facet = DATETIME_FACET;
-  
+
   if (parse_date(str,
                  len,
                  pos,
@@ -363,7 +364,7 @@
 
   if (pos == len || str[pos++] != 'T')
     return 1;
-  
+
   if (parse_time(str,
                  len,
                  pos,
@@ -372,7 +373,7 @@
                  dt.data[SECONDS_DATA],
                  dt.data[FRACSECONDS_DATA]))
     return 1;
-    
+
   ascii::size_type savepos = pos;
 
   ascii::skip_whitespace(str, len, &pos);
@@ -387,7 +388,7 @@
                                      dt.the_time_zone))
       return 1;
   }
-  
+
   if (dt.data[HOUR_DATA] == 24)
   {
     dt.data[HOUR_DATA] = 0;
@@ -408,7 +409,7 @@
   ascii::skip_whitespace(str, len, &pos);
 
   dt.facet = DATE_FACET;
-  
+
   if (parse_date(str,
                  len,
                  pos,
@@ -429,7 +430,7 @@
     if (0 != TimeZone::parseTimeZone(str + pos, len - pos, dt.the_time_zone))
       return 1;
   }
-  
+
   return 0;
 }
 
@@ -441,14 +442,14 @@
   ascii::skip_whitespace(str, len, &pos);
 
   dt.facet = TIME_FACET;
-  
+
   if (parse_time(str, len, pos,
                  dt.data[HOUR_DATA],
                  dt.data[MINUTE_DATA],
                  dt.data[SECONDS_DATA],
                  dt.data[FRACSECONDS_DATA]))
     return 1;
-    
+
   ascii::size_type savepos = pos;
 
   ascii::skip_whitespace(str, len, &pos);
@@ -461,7 +462,7 @@
     if (0 != TimeZone::parseTimeZone(str + pos, len - pos, dt.the_time_zone))
       return 1;
   }
-  
+
   if (dt.data[HOUR_DATA] == 24)
     dt.data[HOUR_DATA] = 0;
 
@@ -476,11 +477,11 @@
   zstring temp;
 
   // GYearMonth of form: '-'? yyyy '-' mm zzzzzz?
-  
+
   ascii::skip_whitespace(str, len, &pos);
 
   dt.facet = GYEARMONTH_FACET;
-  
+
   if (str[pos] == '-')
   {
     temp.append(str + pos, (8 < len - pos ? 8 : len - pos));
@@ -500,7 +501,7 @@
                  dt.data[MONTH_DATA],
                  dt.data[DAY_DATA]))
     return 1;
-  
+
   pos += 7;
 
   ascii::size_type savepos = pos;
@@ -527,11 +528,11 @@
   zstring temp;
 
   // GYear of form: '-'? yyyy zzzzzz?
-  
+
   ascii::skip_whitespace(str, len, &pos);
 
   dt.facet = GYEAR_FACET;
-  
+
   temp.reserve(12);
 
   if (str[pos] == '-')
@@ -553,7 +554,7 @@
                  dt.data[MONTH_DATA],
                  dt.data[DAY_DATA]))
     return 1;
-  
+
   pos += 4;
 
   ascii::size_type savepos = pos;
@@ -581,11 +582,11 @@
 
   // GMonth of form: --MM zzzzzz?
   // preceding - is not allowed.
-  
+
   ascii::skip_whitespace(str, len, &pos);
 
   dt.facet = GMONTH_FACET;
-  
+
   if (str[pos++] != '-')
     return 1;
 
@@ -601,7 +602,7 @@
                  dt.data[MONTH_DATA],
                  dt.data[DAY_DATA]))
     return 1;
-  
+
   pos += 3;
 
   ascii::size_type savepos = pos;
@@ -633,10 +634,10 @@
   ascii::skip_whitespace(str, len, &pos);
 
   dt.facet = GMONTHDAY_FACET;
-  
+
   if (str[pos++] != '-')
     return 1;
-  
+
   temp.reserve(12);
   temp = "0004";
   temp.append(str + pos, 6); // Year 4 to make it a leap year, to allow the MonthDay of 29 February
@@ -650,7 +651,7 @@
     return 1;
 
   dt.data[YEAR_DATA] = 1;
-  
+
   pos += 6;
 
   ascii::size_type savepos = pos;
@@ -678,17 +679,17 @@
 
   // GDay of form: ---DD zzzzzz?
   // preceding - is not allowed.
-  
+
   ascii::skip_whitespace(str, len, &pos);
 
   dt.facet = GDAY_FACET;
-  
-  if (str[pos++] != '-')
-    return 1;
-
-  if (str[pos++] != '-')
-    return 1;
-  
+
+  if (str[pos++] != '-')
+    return 1;
+
+  if (str[pos++] != '-')
+    return 1;
+
   temp = "0001-01";
   temp.append(str + pos, 3);
 
@@ -699,7 +700,7 @@
                  dt.data[MONTH_DATA],
                  dt.data[DAY_DATA]))
     return 1;
-  
+
   pos += 3;
 
   ascii::size_type savepos = pos;
@@ -730,7 +731,7 @@
 {
   bool is_negative = false;
   ascii::size_type temp_pos;
-  
+
   if (pos == len)
     return 1;
 
@@ -765,18 +766,18 @@
   // Parse day
   if (pos == len || parse_long(str, len, pos, day, 2, 2))
     return 1;
-  
+
   // Validate the date
   // year may not be 0
   if (year == 0)
     return 1;
-  
+
   if (month < 1 || month > 12)
     return 1;
 
   if (day < 1 || day > get_last_day(year, month))
     return 1;
-  
+
   return 0;
 }
 
@@ -793,7 +794,7 @@
 {
   if (position == len)
     return 1;
-  
+
   // Parse hour
   if (position == len || parse_long(str, len, position, hour, 2, 2))
     return 1;
@@ -811,7 +812,7 @@
   // Parse seconds
   if (position == len || parse_long(str, len, position, seconds, 2, 2))
     return 1;
-  
+
   if (position < len && str[position] == '.')
   {
     double temp_frac_seconds;
@@ -830,19 +831,19 @@
   // Validate the time
   if (hour > 24)
     return 1;
-  
+
   if (minute > 59)
     return 1;
 
   if (hour == 24 && minute != 0)
     return 1;
-  
+
   if (seconds > 59)
     return 1;
 
   if (hour == 24 && (seconds != 0 || frac_seconds != 0))
     return 1;
-  
+
   return 0;
 }
 
@@ -871,18 +872,18 @@
 zstring DateTime::toString() const
 {
   zstring result;
-  
+
   // output sign
   if (FACET_MEMBERS[facet][0])
     if (data[YEAR_DATA] < 0)
       result.append("-", 1);
-  
+
   // output preceding '-' for Gregorian dates, when needed
   if (facet == GMONTH_FACET || facet == GMONTHDAY_FACET)
     result.append("--", 2);
   if (facet == GDAY_FACET)
     result.append("---", 3);
-  
+
   for (int i=0; i<=5; i++)
   {
     if (FACET_MEMBERS[facet][i])
@@ -892,12 +893,12 @@
         result.push_back(separators[i]);
     }
   }
-  
+
   if (FACET_MEMBERS[facet][FRACSECONDS_DATA] && (data[FRACSECONDS_DATA] != 0))
   {
     int temp;
     result.append(".", 1);
-    
+
     // print leading 0s, if any
     temp = FRAC_SECONDS_UPPER_LIMIT / 10;
     while (temp > data[FRACSECONDS_DATA] && temp > 0)
@@ -905,17 +906,17 @@
       result.append("0", 1);
       temp /= 10;
     }
-    
+
     // strip trailing 0s, if any
     temp = data[FRACSECONDS_DATA];
     while (temp%10 == 0 && temp > 0)
       temp = temp / 10;
-    
+
     result.append(ztd::to_string(temp));
   }
-  
+
   result.append(the_time_zone.toString());
-  
+
   return result;
 }
 
@@ -984,7 +985,7 @@
   assert(data[SECONDS_DATA] >= 0);
   return data[SECONDS_DATA];
 }
-  
+
 
 int DateTime::getFractionalSeconds() const
 {
@@ -1003,21 +1004,21 @@
 {
   return !the_time_zone.timeZoneNotSet();
 }
-  
-  
+
+
 int DateTime::compare(const DateTime* dt, long timezone_seconds) const
 {
   std::auto_ptr<DateTime> d1_t;
   std::auto_ptr<DateTime> d2_t;
-  
+
   d1_t.reset(normalizeTimeZone(timezone_seconds));
   d2_t.reset(dt->normalizeTimeZone(timezone_seconds));
-    
+
   if (d1_t->data[YEAR_DATA] < d2_t->data[YEAR_DATA])
     return -1;
   else if (d1_t->data[YEAR_DATA] > d2_t->data[YEAR_DATA])
     return 1;
-  
+
   // compare the rest of the data
   if (d1_t->data[YEAR_DATA] < 0 && d2_t->data[YEAR_DATA] < 0)
   {
@@ -1039,7 +1040,7 @@
         return 1;
     }
   }
-  
+
   return 0;
 }
 
@@ -1048,7 +1049,7 @@
 {
   uint32_t hval = 0;
   std::auto_ptr<DateTime> dt(normalizeTimeZone(implicit_timezone_seconds));
-  
+
   hval = hashfun::h32<int>((int)dt->facet, hval);
   hval = hashfun::h32<int>(dt->data[YEAR_DATA], hval);
   hval = hashfun::h32<int>(dt->data[MONTH_DATA], hval);
@@ -1057,9 +1058,9 @@
   hval = hashfun::h32<int>(dt->data[MINUTE_DATA], hval);
   hval = hashfun::h32<int>(dt->data[SECONDS_DATA], hval);
   hval = hashfun::h32<int>(dt->data[FRACSECONDS_DATA], hval);
-  
+
   hval = dt->the_time_zone.hash(hval);
-  
+
   return hval;
 }
 
@@ -1086,13 +1087,13 @@
                                                data[MONTH_DATA],
                                                data[DAY_DATA])-1,
                          0, 0, 0, 0);
-    
+
     Duration remainder(Duration::DAYTIMEDURATION_FACET, false, 0, 0, 0,
                               data[HOUR_DATA],
                               data[MINUTE_DATA],
                               data[SECONDS_DATA],
                               data[FRACSECONDS_DATA]);
-    
+
     return days + remainder;
   }
 }
@@ -1106,7 +1107,7 @@
 
   // For the algorithm, see XML Schema 2 spec, Appendix E
   // http://www.w3.org/TR/xmlschema-2/#adding-durations-to-dateTimes
-  
+
   months = modulo<int>(data[MONTH_DATA] + d.getMonths() - 1, 12) + 1;
 
   years = data[YEAR_DATA] + d.getYears() +
@@ -1118,7 +1119,7 @@
   int_seconds = modulo<int>(total_seconds, 60);
 
   frac_seconds = modulo<int>(temp_frac_seconds, DateTime::FRAC_SECONDS_UPPER_LIMIT);
-  
+
   minutes = data[MINUTE_DATA] + d.getMinutes() + quotient<int>(total_seconds, 60);
 
   hours = data[HOUR_DATA] + d.getHours() + quotient<int>(minutes, 60);
@@ -1155,7 +1156,7 @@
     years += quotient<int>(months + carry-1, 12);
     months = modulo<int>(months + carry -1, 12) + 1;
   }
-  
+
   if (data[YEAR_DATA] > 0 && d.isNegative() && years <= 0)
     years--;
   if (data[YEAR_DATA] < 0 && !d.isNegative() && years >= 0)
@@ -1167,7 +1168,7 @@
                                int_seconds, frac_seconds, &the_time_zone,
                                *new_dt))
     assert(0);
-  
+
   new_dt->facet = facet;
   if (adjust_facet)
     new_dt->adjustToFacet();
@@ -1199,13 +1200,13 @@
 {
   DateTime* dt;
   Duration d;
-  
+
   if( the_time_zone.timeZoneNotSet() )
   {
     // validate timezone value (-14 .. +14 H)
     if (tz_seconds > 14*3600 || tz_seconds < -14*3600)
       throw InvalidTimezoneException( tz_seconds );
-    
+
     d = Duration(Duration::DAYTIMEDURATION_FACET,
                  (tz_seconds < 0), 0, 0, 0, 0, 0, tz_seconds, 0);
   }
@@ -1214,10 +1215,10 @@
     if (0 != Duration::fromTimezone(the_time_zone, d))
       assert(0);
   }
-  
+
   dt = subtractDuration(d, false); // do not adjust to facet
   dt->the_time_zone = TimeZone(0);
-  
+
   return dt;
 }
 
@@ -1227,7 +1228,7 @@
   std::auto_ptr<Duration> dtduration;
   std::auto_ptr<Duration> context_tz;
   std::auto_ptr<DateTime> dt;
-  
+
   // validate timezone value (-14 .. +14 H)
   if (tz_seconds > 14*3600 || tz_seconds < -14*3600)
     throw InvalidTimezoneException( tz_seconds );
@@ -1236,7 +1237,7 @@
   context_tz = std::auto_ptr<Duration>(new Duration(Duration::DAYTIMEDURATION_FACET, (tz_seconds<0), 0, 0, 0, 0, 0, tz_seconds, 0));
 
   dt = std::auto_ptr<DateTime>(new DateTime(*this));
-  
+
   // If $arg does not have a timezone component and $timezone is not the empty sequence,
   // then the result is $arg with $timezone as the timezone component.
   if (the_time_zone.timeZoneNotSet())
@@ -1274,9 +1275,9 @@
 
   // A dynamic error is raised [err:FODT0003] if $timezone is less than -PT14H
   // or greater than PT14H or if does not contain an integral number of minutes.
-  
+
   dt = std::auto_ptr<DateTime>(new DateTime(*this));
-  
+
   if (d == NULL)
   {
     if (!the_time_zone.timeZoneNotSet())
@@ -1291,7 +1292,7 @@
         d->getHours()*3600 + d->getMinutes()*60 > 14*3600 ||
         d->getHours()*3600 + d->getMinutes()*60 < -14*3600)
       throw InvalidTimezoneException( d->getHours()*3600 + d->getMinutes()*60 );
-        
+
     // If $arg does not have a timezone component and $timezone is not the
     // empty sequence, then the result is $arg with $timezone as the timezone
     // component.
@@ -1385,79 +1386,18 @@
 }
 
 
-int DateTime::getDayOfWeek(int year, int month, int day)
-{
-  if (month < 3)
-  {
-    month = month + 12;
-    year = year - 1;
-  }
-  
-  return (day
-      + (2 * month)
-      + int(6 * (month + 1) / 10)
-      + year
-      + int(year / 4)
-      - int(year / 100)
-      + int(year / 400)
-      + 1                     // CalendarSystem, 1 for Gregorian
-         ) % 7;
-}
-
-
-int DateTime::getWeekInYear(int year, int month, int day)
-{
-  int day_of_year = DateTime::getDayOfYear(year, month, day);
-  int year_first_day_of_week = DateTime::getDayOfWeek(year, 1, 1);
-
-  if (year_first_day_of_week > 4 && (year_first_day_of_week + day_of_year) <= 8)
-    return getWeekInYear(year-1, 12, 31);
-  
-  return ((day_of_year + year_first_day_of_week - 2) / 7) + year_first_day_of_week < 5 ? 1 : 0;
-}
-
-
 int DateTime::getDayOfYear(int year, int month, int day)
 {
-  static const int days[] = {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365};
-
   if (month > 12)
     return -1;
-  
-  if (isLeapYear(year) && month >= 3)
-    day++;
-  
-  return days[month-1] + day;
-}
-
-
-bool DateTime::isLeapYear(int year)
-{
-  if (((year%4 == 0) && (year%100 != 0))
-        ||
-        (year%400 == 0))
-    return true;
-  else
-    return false;
+  return time::calc_yday( day, month, year );
 }
 
 
 int DateTime::getWeekInMonth(int year, int month, int day)
 {
-  int first_day_of_week = DateTime::getDayOfWeek(year, month, 1);
-  return ((day + first_day_of_week - 2) / 7) + (first_day_of_week < 5 ? 1 : 0);
-}
-
-
-bool DateTime::isLeapYear() const
-{
-  return isLeapYear(data[YEAR_DATA]);
-}
-
-
-int DateTime::getDayOfWeek() const
-{  
-	return getDayOfWeek(data[YEAR_DATA], data[MONTH_DATA], data[DAY_DATA]);
+  int const wday = time::calc_wday(1, month-1, year);
+  return ((day + wday - 2) / 7) + (wday < 5 ? 1 : 0);
 }
 
 
@@ -1467,12 +1407,6 @@
 }
 
 
-int DateTime::getWeekInYear() const
-{
-  return getWeekInYear(data[YEAR_DATA], data[MONTH_DATA], data[DAY_DATA]);
-}
-
-
 int DateTime::getWeekInMonth() const
 {
   return getWeekInMonth(data[YEAR_DATA], data[MONTH_DATA], data[DAY_DATA]);

=== modified file 'src/zorbautils/locale.cpp'
--- src/zorbautils/locale.cpp	2013-03-18 05:13:50 +0000
+++ src/zorbautils/locale.cpp	2013-03-20 21:54:22 +0000
@@ -169,6 +169,8 @@
   LPCWSTR wlocale_name;
   unique_ptr<WCHAR[]> wlocale_name_ptr;
 
+  if ( !country )
+    country = iso3166_1::get_default( lang );
   if ( lang && country ) {
     wlocale_name_ptr = get_wlocale_name( lang, country );
     wlocale_name = wlocale_name_ptr.get();
@@ -278,6 +280,8 @@
 static zstring get_locale_info( nl_item item, iso639_1::type lang,
                                 iso3166_1::type country ) {
   if ( lang ) {
+    if ( !country )
+      country = iso3166_1::get_default( lang );
     if ( locale_t const loc = get_unix_locale_t( lang, country ) ) {
       char const *const info = nl_langinfo_l( item, loc );
       ::freelocale( loc );
@@ -549,6 +553,205 @@
   return FIND( country );
 }
 
+type get_default( iso639_1::type lang ) {
+  //
+  // In cases where a language maps to multiple countries, if the language is
+  // the official language of a single country, that country is the one the
+  // language is mapped to.
+  //
+  static type const lang_to_country[] = {
+    unknown,
+    DJ     , // aa: Afar => Djibouti
+    GE     , // ab: Abkhazian => Georgia
+    IR     , // ae: Avestan => Iran
+    ZA     , // af: Afrikaans => South Africa
+    GH     , // ak: Akan => Ghana
+    ET     , // am: Amharic => Ethiopia
+    ES     , // an: Aragonese => Spain
+    unknown, // ar: Arabic => (maps to multiple countries)
+    IN_    , // as: Assamese => India
+    AZ     , // av: Avaric => Azerbaijan
+    BO     , // ay: Aymara => Bolivia
+    AZ     , // az: Azerbaijani => Azerbaijan
+    RU     , // ba: Bashkir => Russian Federation
+    RU     , // be: Byelorussian => Russian Federation
+    BG     , // bg: Bulgarian => Bulgaria
+    IN_    , // bh: Bihari => India
+    VU     , // bi: Bislama => Vanuatu
+    ML     , // bm: Bambara => Mali
+    BD     , // bn: Bengali; Bangla => Bangladesh
+    CN     , // bo: Tibetan => China
+    FR     , // br: Breton => France
+    BA     , // bs: Bosnian => Bosnia
+    AD     , // ca: Catalan => Andorra
+    RU     , // ce: Chechen => Russian Federation
+    MP     , // ch: Chamorro => Northern Mariana Islands
+    FR     , // co: Corsican => France
+    US     , // cr: Cree => United States
+    CZ     , // cs: Czech => Czech Republic
+    RU     , // cu: Church Slavic; Church Slavonic => Russian Federation
+    RU     , // cv: Chuvash => Russian Federation
+    GB     , // cy: Welsh => United Kingdom
+    DK     , // da: Danish => Denmark
+    DE     , // de: German => Germany
+    MV     , // dv: Divehi => Maldives
+    PK     , // dz: Bhutani => Pakistan
+    unknown, // ee: Ewe => (maps to multiple countries)
+    GR     , // el: Greek => Greece
+    GB     , // en: English => United Kingdom
+    unknown, // eo: Esperanto => (constructed language)
+    ES     , // es: Spanish => Spain
+    EE     , // et: Estonian => Estonia
+    ES     , // eu: Basque => Spain
+    IR     , // fa: Persian => Iran
+    unknown, // ff: Fulah => (maps to multiple countries)
+    FI     , // fi: Finnish => Finland
+    FJ     , // fj: Fiji => Fiji
+    FO     , // fo: Faroese => Faroe Islands
+    FR     , // fr: French => France
+    NL     , // fy: Frisian => Netherlands
+    IE     , // ga: Irish => Ireland
+    GB     , // gd: Scots Gaelic => United Kingdom
+    ES     , // gl: Galician => Spain
+    PY     , // gn: Guarani => Paraguay
+    IN_    , // gu: Gujarati => India
+    IM     , // gv: Manx => Isle of Man
+    unknown, // ha: Hausa => (maps to multiple languages)
+    IL     , // he: Hebrew => Israel
+    IN_    , // hi: Hindi => India
+    PG     , // ho: Hiri Motu => Papua New Guinea
+    HR     , // hr: Croatian => Croatia
+    HT     , // ht: Haitian Creole => Haiti
+    HU     , // hu: Hungarian => Hungary
+    AM     , // hy: Armenian => Armenia
+    unknown, // hz: Herero => (maps to multiple countries)
+    unknown, // ia: Interlingua => (constructed language)
+    ID     , // id: Indonesian => Indonesia
+    unknown, // ie: Interlingue => (constructed language)
+    NG     , // ig: Igbo => Nigeria
+    CN     , // ii: Nuosu => China
+    US     , // ik: Inupiak => United States
+    unknown, // io: Ido => (constructed language)
+    IS     , // is: Icelandic => Island
+    IT     , // it: Italian => Italy
+    CA     , // iu: Inuktitut => Canada
+    JP     , // ja: Japanese => Japan
+    ID     , // jv: Javanese => Indonesia
+    GE     , // ka: Georgian => Georgia
+    unknown, // kg: Kongo => (maps to multiple countries)
+    KE     , // ki: Gikuyu => Kenya
+    unknown, // kj: Kuanyama => (maps to multiple countries)
+    KZ     , // kk: Kazakh => Kazakhstan
+    GL     , // kl: Greenlandic => Greenland
+    KH     , // km: Cambodian => Cambodia
+    IN_    , // kn: Kannada => India
+    KR     , // ko: Korean => Korea
+    unknown, // kr: Kanuri => (maps to multiple countries)
+    IN_    , // ks: Kashmiri => India
+    IQ     , // ku: Kurdish => Iraq
+    RU     , // kv: Komi => Russian Federation
+    GB     , // kw: Cornish => United Kingdom
+    KG     , // ky: Kirghiz => Kyrgyzstan
+    unknown, // la: Latin => (maps to multiple countries)
+    LU     , // lb: Letzeburgesch => Luxembourg
+    UG     , // lg: Ganda => Uganda
+    NL     , // li: Limburgan; Limburger; Limburgish => Netherands
+    unknown, // ln: Lingala => (maps to multiple countries)
+    LA     , // lo: Laotian => Lao
+    LT     , // lt: Lithuanian => Lithuania
+    CD     , // lu: Luba-Katanga => Democratic Republic of the Congo
+    LV     , // lv: Latvian => Latvia
+    MG     , // mg: Malagasy => Madagascar
+    MH     , // mh: Marshallese => Marshall Islands
+    NZ     , // mi: Maori => New Zealand
+    MK     , // mk: Macedonian => Macedonia
+    IN_    , // ml: Malayalam => India
+    MN     , // mn: Mongolian => Mongolia
+    MD     , // mo: Moldavian => Moldova
+    IN_    , // mr: Marathi => India
+    MY     , // ms: Malay => Malaysia
+    MT     , // mt: Maltese => Malta
+    MM     , // my: Burmese => Myanmar (Burma)
+    NR     , // na: Nauru => Nauru
+    NO     , // nb: Norwegian Bokmal => Norway
+    ZW     , // nd: Ndebele, North => Zimbabwe
+    NP     , // ne: Nepali => Nepal
+    NA     , // ng: Ndonga => Namibia
+    NL     , // nl: Dutch => Netherlands
+    NO     , // nn: Norwegian Nynorsk => Norway
+    NO     , // no: Norwegian => Norway
+    ZA     , // nr: Ndebele, South => South Africa
+    US     , // nv: Navajo; Navaho => United States
+    MW     , // ny: Chichewa; Chewa; Nyanja => Malawi
+    unknown, // oc: Occitan => (maps to multiple countries)
+    CA     , // oj: Ojibwa => Canada
+    unknown, // om: Oromo => (maps to multiple countries)
+    IN_    , // or: Oriya => India
+    unknown, // os: Ossetian; Ossetic => (maps to multiple countries)
+    PK     , // pa: Panjabi; Punjabi => Pakistan
+    unknown, // pi: Pali => (maps to multiple countries)
+    PL     , // pl: Polish => Poland
+    AF     , // ps: Pashto, Pushto => Afghanistan
+    PT     , // pt: Portuguese => Portugal
+    unknown, // qu: Quechua => (maps to multiple countries)
+    CH     , // rm: Romansh => Switzerland
+    BI     , // rn: Kirundi => Burundi
+    RO     , // ro: Romanian => Romania
+    RU     , // ru: Russian => Russian Federation
+    RW     , // rw: Kinyarwanda => Rwanda
+    IN_    , // sa: Sanskrit => India
+    IT     , // sc: Sardinian => Italy
+    PK     , // sd: Sindhi => Pakistan
+    NO     , // se: Northern Sami => Norway
+    CF     , // sg: Sangho => Central African Republic
+    RS     , // sh: Serbo-Croatian => Serbia
+    LK     , // si: Sinhalese => Sri Lanka
+    SK     , // sk: Slovak => Slovakia
+    SI     , // sl: Slovenian => Slovenia
+    AS     , // sm: Samoan => American Samoa
+    ZW     , // sn: Shona => Zimbabwe
+    SO     , // so: Somali => Somalia
+    AL     , // sq: Albanian => Albania
+    RS     , // sr: Serbian => Serbia
+    SZ     , // ss: Siswati => Swaziland
+    LS     , // st: Sesotho => Lesotho
+    SD     , // su: Sundanese => Sudan
+    SE     , // sv: Swedish => Sweden
+    KE     , // sw: Swahili => Kenya
+    IN_    , // ta: Tamil => India
+    IN_    , // te: Telugu => India
+    TJ     , // tg: Tajik => Tajikistan
+    TH     , // th: Thai => Thailand
+    ER     , // ti: Tigrinya => Eritrea
+    TM     , // tk: Turkmen => Turkmenistan
+    PH     , // tl: Tagalog => Philippines
+    ZA     , // tn: Setswana => South Africa
+    TO     , // to: Tonga => Tonga
+    TR     , // tr: Turkish => Turkey
+    ZA     , // ts: Tsonga => South Africa
+    RU     , // tt: Tatar => Russian Federation
+    GH     , // tw: Twi => Ghana
+    PF     , // ty: Tahitian => French Polynesia
+    CN     , // ug: Uighur => China
+    UA     , // uk: Ukrainian => Ukrain
+    PK     , // ur: Urdu => Pakistan
+    UZ     , // uz: Uzbek => Uzbekistan
+    ZA     , // ve: Venda => South Africa
+    VN     , // vi: Vietnamese => Viet Nam
+    DE     , // vo: Volapuk => Germany
+    BE     , // wa: Walloon => Belgium
+    SN     , // wo: Wolof => Senegal
+    ZA     , // xh: Xhosa => South Africa
+    IL     , // yi: Yiddish => Israel
+    NG     , // yo: Yoruba => Nigeria
+    CN     , // za: Zhuang => China
+    CN     , // zh: Chinese => China
+    ZA     , // zu: Zulu => South Africa
+  };
+  assert( lang < iso639_1::NUM_ENTRIES );
+  return lang_to_country[ lang ];
+}
+
 } // namespace iso3166_1
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -1302,6 +1505,8 @@
 }
 
 bool is_supported( iso639_1::type lang, iso3166_1::type country ) {
+  if ( !country )
+    country = iso3166_1::get_default( lang );
 #ifdef WIN32
   unique_ptr<WCHAR[]> const wlocale_name( get_wlocale_name( lang, country ) );
   return Zorba_IsValidLocaleName( wlocale_name.get() );

=== modified file 'src/zorbautils/locale.h'
--- src/zorbautils/locale.h	2013-03-08 04:26:02 +0000
+++ src/zorbautils/locale.h	2013-03-20 21:54:22 +0000
@@ -62,6 +62,15 @@
       find( StringType const &country ) {
         return find( country.c_str() );
       }
+
+      /**
+       * Gets the "default" country that speaks the given language.
+       *
+       * @param lang The language to get the default country for.
+       * @return Returns said country or \c unknown.
+       */
+      type get_default( iso639_1::type lang );
+
     } // namespace iso3166_1
 
     /////////////////////////////////////////////////////////////////////////// 

=== modified file 'test/fots/CMakeLists.txt'
--- test/fots/CMakeLists.txt	2013-03-20 06:58:59 +0000
+++ test/fots/CMakeLists.txt	2013-03-20 21:54:22 +0000
@@ -158,37 +158,8 @@
 EXPECTED_FOTS_FAILURE (fn-environment-variable environment-variable-005 0)
 EXPECTED_FOTS_FAILURE (fn-environment-variable environment-variable-006 0)
 EXPECTED_FOTS_FAILURE (fn-environment-variable environment-variable-007 0)
-EXPECTED_FOTS_FAILURE (fn-format-date format-date-001d 0)
-EXPECTED_FOTS_FAILURE (fn-format-date format-date-001g 0)
 EXPECTED_FOTS_FAILURE (fn-format-date format-date-005 0)
 EXPECTED_FOTS_FAILURE (fn-format-date format-date-006 0)
-EXPECTED_FOTS_FAILURE (fn-format-date format-date-007a 0)
-EXPECTED_FOTS_FAILURE (fn-format-date format-date-007b 0)
-EXPECTED_FOTS_FAILURE (fn-format-date format-date-007c 0)
-EXPECTED_FOTS_FAILURE (fn-format-date format-date-008a 0)
-EXPECTED_FOTS_FAILURE (fn-format-date format-date-008b 0)
-EXPECTED_FOTS_FAILURE (fn-format-date format-date-008c 0)
-EXPECTED_FOTS_FAILURE (fn-format-date format-date-009 0)
-EXPECTED_FOTS_FAILURE (fn-format-date format-date-010 0)
-EXPECTED_FOTS_FAILURE (fn-format-date format-date-014 0)
-EXPECTED_FOTS_FAILURE (fn-format-date format-date-015 0)
-EXPECTED_FOTS_FAILURE (fn-format-date format-date-016 0)
-EXPECTED_FOTS_FAILURE (fn-format-date format-date-017 0)
-EXPECTED_FOTS_FAILURE (fn-format-date format-date-018 0)
-EXPECTED_FOTS_FAILURE (fn-format-date format-date-019 0)
-EXPECTED_FOTS_FAILURE (fn-format-date format-date-020 0)
-EXPECTED_FOTS_FAILURE (fn-format-date format-date-021 0)
-EXPECTED_FOTS_FAILURE (fn-format-date format-date-022 0)
-EXPECTED_FOTS_FAILURE (fn-format-date format-date-023 0)
-EXPECTED_FOTS_FAILURE (fn-format-date format-date-024 0)
-EXPECTED_FOTS_FAILURE (fn-format-date format-date-025 0)
-EXPECTED_FOTS_FAILURE (fn-format-date format-date-026 0)
-EXPECTED_FOTS_FAILURE (fn-format-date format-date-027 0)
-EXPECTED_FOTS_FAILURE (fn-format-date format-date-en117 0)
-EXPECTED_FOTS_FAILURE (fn-format-date format-date-en118 0)
-EXPECTED_FOTS_FAILURE (fn-format-date format-date-en123 0)
-EXPECTED_FOTS_FAILURE (fn-format-date format-date-en124 0)
-EXPECTED_FOTS_FAILURE (fn-format-date format-date-en125 0)
 EXPECTED_FOTS_FAILURE (fn-format-date format-date-en126 0)
 EXPECTED_FOTS_FAILURE (fn-format-date format-date-en127 0)
 EXPECTED_FOTS_FAILURE (fn-format-date format-date-en128 0)
@@ -198,34 +169,9 @@
 EXPECTED_FOTS_FAILURE (fn-format-date format-date-en132 0)
 EXPECTED_FOTS_FAILURE (fn-format-date format-date-en133 0)
 EXPECTED_FOTS_FAILURE (fn-format-date format-date-en134 0)
-EXPECTED_FOTS_FAILURE (fn-format-date format-date-en141 0)
-EXPECTED_FOTS_FAILURE (fn-format-date format-date-en151 0)
-EXPECTED_FOTS_FAILURE (fn-format-dateTime format-dateTime-001d 0)
-EXPECTED_FOTS_FAILURE (fn-format-dateTime format-dateTime-001g 0)
-EXPECTED_FOTS_FAILURE (fn-format-dateTime format-dateTime-002g 0)
-EXPECTED_FOTS_FAILURE (fn-format-dateTime format-dateTime-002h 0)
-EXPECTED_FOTS_FAILURE (fn-format-dateTime format-dateTime-002i 0)
-EXPECTED_FOTS_FAILURE (fn-format-dateTime format-dateTime-003d 0)
-EXPECTED_FOTS_FAILURE (fn-format-dateTime format-dateTime-003g 0)
-EXPECTED_FOTS_FAILURE (fn-format-dateTime format-dateTime-003m 0)
-EXPECTED_FOTS_FAILURE (fn-format-dateTime format-dateTime-003n 0)
-EXPECTED_FOTS_FAILURE (fn-format-dateTime format-dateTime-003p 0)
 EXPECTED_FOTS_FAILURE (fn-format-dateTime format-dateTime-005 0)
 EXPECTED_FOTS_FAILURE (fn-format-dateTime format-dateTime-006 0)
-EXPECTED_FOTS_FAILURE (fn-format-dateTime format-dateTime-009 0)
-EXPECTED_FOTS_FAILURE (fn-format-dateTime format-dateTime-010 0)
 EXPECTED_FOTS_FAILURE (fn-format-dateTime format-dateTime-011 0)
-EXPECTED_FOTS_FAILURE (fn-format-dateTime format-dateTime-012 0)
-EXPECTED_FOTS_FAILURE (fn-format-dateTime format-dateTime-013p 0)
-EXPECTED_FOTS_FAILURE (fn-format-dateTime format-dateTime-013s 0)
-EXPECTED_FOTS_FAILURE (fn-format-dateTime format-dateTime-013u 0)
-EXPECTED_FOTS_FAILURE (fn-format-dateTime format-dateTime-014 0)
-EXPECTED_FOTS_FAILURE (fn-format-dateTime format-dateTime-015 0)
-EXPECTED_FOTS_FAILURE (fn-format-dateTime format-dateTime-016 0)
-EXPECTED_FOTS_FAILURE (fn-format-dateTime format-dateTime-017 0)
-EXPECTED_FOTS_FAILURE (fn-format-dateTime format-dateTime-018 0)
-EXPECTED_FOTS_FAILURE (fn-format-dateTime format-dateTime-en141 0)
-EXPECTED_FOTS_FAILURE (fn-format-dateTime format-dateTime-en151 0)
 EXPECTED_FOTS_FAILURE (fn-format-integer format-integer-030 0)
 EXPECTED_FOTS_FAILURE (fn-format-integer format-integer-031 0)
 EXPECTED_FOTS_FAILURE (fn-format-integer format-integer-033 0)
@@ -265,18 +211,6 @@
 EXPECTED_FOTS_FAILURE (fn-format-number numberformat86 0)
 EXPECTED_FOTS_FAILURE (fn-format-number numberformat87 0)
 EXPECTED_FOTS_FAILURE (fn-format-number numberformat88 0)
-EXPECTED_FOTS_FAILURE (fn-format-time format-time-002g 0)
-EXPECTED_FOTS_FAILURE (fn-format-time format-time-002h 0)
-EXPECTED_FOTS_FAILURE (fn-format-time format-time-002i 0)
-EXPECTED_FOTS_FAILURE (fn-format-time format-time-013p 0)
-EXPECTED_FOTS_FAILURE (fn-format-time format-time-013s 0)
-EXPECTED_FOTS_FAILURE (fn-format-time format-time-013u 0)
-EXPECTED_FOTS_FAILURE (fn-format-time format-time-014 0)
-EXPECTED_FOTS_FAILURE (fn-format-time format-time-015 0)
-EXPECTED_FOTS_FAILURE (fn-format-time format-time-016 0)
-EXPECTED_FOTS_FAILURE (fn-format-time format-time-017 0)
-EXPECTED_FOTS_FAILURE (fn-format-time format-time-018 0)
-EXPECTED_FOTS_FAILURE (fn-format-time format-time-816err 0)
 EXPECTED_FOTS_FAILURE (fn-generate-id generate-id-001 0)
 EXPECTED_FOTS_FAILURE (fn-generate-id generate-id-002 0)
 EXPECTED_FOTS_FAILURE (fn-generate-id generate-id-003 0)

=== removed file 'test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/FormatDateFuncYearMonth1.xml.res'
--- test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/FormatDateFuncYearMonth1.xml.res	2013-02-07 17:24:36 +0000
+++ test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/FormatDateFuncYearMonth1.xml.res	1970-01-01 00:00:00 +0000
@@ -1,1 +0,0 @@
-true
\ No newline at end of file

=== removed file 'test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/FormatDateFuncYearMonth2.xml.res'
--- test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/FormatDateFuncYearMonth2.xml.res	2013-02-07 17:24:36 +0000
+++ test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/FormatDateFuncYearMonth2.xml.res	1970-01-01 00:00:00 +0000
@@ -1,1 +0,0 @@
-true
\ No newline at end of file

=== added file 'test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-D.xml.res'
--- test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-D.xml.res	1970-01-01 00:00:00 +0000
+++ test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-D.xml.res	2013-03-20 21:54:22 +0000
@@ -0,0 +1,1 @@
+true

=== added file 'test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-D01.xml.res'
--- test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-D01.xml.res	1970-01-01 00:00:00 +0000
+++ test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-D01.xml.res	2013-03-20 21:54:22 +0000
@@ -0,0 +1,1 @@
+true

=== added file 'test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-D1o.xml.res'
--- test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-D1o.xml.res	1970-01-01 00:00:00 +0000
+++ test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-D1o.xml.res	2013-03-20 21:54:22 +0000
@@ -0,0 +1,1 @@
+true

=== added file 'test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-DW-1.xml.res'
--- test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-DW-1.xml.res	1970-01-01 00:00:00 +0000
+++ test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-DW-1.xml.res	2013-03-20 21:54:22 +0000
@@ -0,0 +1,1 @@
+true

=== added file 'test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-DWo-1.xml.res'
--- test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-DWo-1.xml.res	1970-01-01 00:00:00 +0000
+++ test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-DWo-1.xml.res	2013-03-20 21:54:22 +0000
@@ -0,0 +1,1 @@
+true

=== added file 'test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-DWw.xml.res'
--- test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-DWw.xml.res	1970-01-01 00:00:00 +0000
+++ test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-DWw.xml.res	2013-03-20 21:54:22 +0000
@@ -0,0 +1,1 @@
+true

=== added file 'test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-DWwo.xml.res'
--- test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-DWwo.xml.res	1970-01-01 00:00:00 +0000
+++ test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-DWwo.xml.res	2013-03-20 21:54:22 +0000
@@ -0,0 +1,1 @@
+true

=== added file 'test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-Dw-2.xml.res'
--- test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-Dw-2.xml.res	1970-01-01 00:00:00 +0000
+++ test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-Dw-2.xml.res	2013-03-20 21:54:22 +0000
@@ -0,0 +1,1 @@
+true

=== added file 'test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-Dwo-2.xml.res'
--- test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-Dwo-2.xml.res	1970-01-01 00:00:00 +0000
+++ test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-Dwo-2.xml.res	2013-03-20 21:54:22 +0000
@@ -0,0 +1,1 @@
+true

=== added file 'test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-FN-1.xml.res'
--- test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-FN-1.xml.res	1970-01-01 00:00:00 +0000
+++ test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-FN-1.xml.res	2013-03-20 21:54:22 +0000
@@ -0,0 +1,1 @@
+true

=== added file 'test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-FN-3.xml.res'
--- test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-FN-3.xml.res	1970-01-01 00:00:00 +0000
+++ test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-FN-3.xml.res	2013-03-20 21:54:22 +0000
@@ -0,0 +1,1 @@
+true

=== added file 'test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-FNn-1.xml.res'
--- test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-FNn-1.xml.res	1970-01-01 00:00:00 +0000
+++ test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-FNn-1.xml.res	2013-03-20 21:54:22 +0000
@@ -0,0 +1,1 @@
+true

=== added file 'test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-FNn-2.xml.res'
--- test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-FNn-2.xml.res	1970-01-01 00:00:00 +0000
+++ test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-FNn-2.xml.res	2013-03-20 21:54:22 +0000
@@ -0,0 +1,1 @@
+true

=== added file 'test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-Fn-2.xml.res'
--- test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-Fn-2.xml.res	1970-01-01 00:00:00 +0000
+++ test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-Fn-2.xml.res	2013-03-20 21:54:22 +0000
@@ -0,0 +1,1 @@
+true

=== added file 'test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-Fn-4.xml.res'
--- test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-Fn-4.xml.res	1970-01-01 00:00:00 +0000
+++ test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-Fn-4.xml.res	2013-03-20 21:54:22 +0000
@@ -0,0 +1,1 @@
+true

=== renamed file 'test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/FormatDateFuncMonthDefault.xml.res' => 'test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-M.xml.res'
--- test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/FormatDateFuncMonthDefault.xml.res	2013-02-07 17:24:36 +0000
+++ test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-M.xml.res	2013-03-20 21:54:22 +0000
@@ -1,1 +1,1 @@
-true
\ No newline at end of file
+true

=== renamed file 'test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/FormatDateFuncMonthNumber.xml.res' => 'test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-M01.xml.res'
--- test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/FormatDateFuncMonthNumber.xml.res	2013-02-07 17:24:36 +0000
+++ test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-M01.xml.res	2013-03-20 21:54:22 +0000
@@ -1,1 +1,1 @@
-true
\ No newline at end of file
+true

=== renamed file 'test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/FormatDateFuncMonthUpperCase.xml.res' => 'test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-MN-1.xml.res'
--- test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/FormatDateFuncMonthUpperCase.xml.res	2013-02-07 17:24:36 +0000
+++ test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-MN-1.xml.res	2013-03-20 21:54:22 +0000
@@ -1,1 +1,1 @@
-true
\ No newline at end of file
+true

=== renamed file 'test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/FormatDateFuncMonthTitleCase.xml.res' => 'test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-MNn.xml.res'
--- test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/FormatDateFuncMonthTitleCase.xml.res	2013-02-07 17:24:36 +0000
+++ test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-MNn.xml.res	2013-03-20 21:54:22 +0000
@@ -1,1 +1,1 @@
-true
\ No newline at end of file
+true

=== renamed file 'test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/FormatDateFuncMonthLowerCase.xml.res' => 'test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-Mn-2.xml.res'
--- test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/FormatDateFuncMonthLowerCase.xml.res	2013-02-07 17:24:36 +0000
+++ test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-Mn-2.xml.res	2013-03-20 21:54:22 +0000
@@ -1,1 +1,1 @@
-true
\ No newline at end of file
+true

=== renamed file 'test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/FormatDateFuncYearMaxWidth.xml.res' => 'test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-Y-2-2.xml.res'
--- test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/FormatDateFuncYearMaxWidth.xml.res	2013-02-07 17:24:36 +0000
+++ test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-Y-2-2.xml.res	2013-03-20 21:54:22 +0000
@@ -1,1 +1,1 @@
-true
\ No newline at end of file
+true

=== renamed file 'test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/FormatDateFuncReflexivity.xml.res' => 'test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-Y-M01-D01.xml.res'
--- test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/FormatDateFuncReflexivity.xml.res	2013-02-07 17:24:36 +0000
+++ test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-Y-M01-D01.xml.res	2013-03-20 21:54:22 +0000
@@ -1,1 +1,1 @@
-true
\ No newline at end of file
+true

=== added file 'test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-Y-Thai-1.xml.res'
--- test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-Y-Thai-1.xml.res	1970-01-01 00:00:00 +0000
+++ test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-Y-Thai-1.xml.res	2013-03-20 21:54:22 +0000
@@ -0,0 +1,1 @@
+true

=== added file 'test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-Y-Thai-2.xml.res'
--- test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-Y-Thai-2.xml.res	1970-01-01 00:00:00 +0000
+++ test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-Y-Thai-2.xml.res	2013-03-20 21:54:22 +0000
@@ -0,0 +1,1 @@
+true

=== renamed file 'test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/FormatDateFuncYearDefault.xml.res' => 'test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-Y.xml.res'
--- test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/FormatDateFuncYearDefault.xml.res	2013-02-07 17:24:36 +0000
+++ test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-Y.xml.res	2013-03-20 21:54:22 +0000
@@ -1,1 +1,1 @@
-true
\ No newline at end of file
+true

=== added file 'test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-YI-1.xml.res'
--- test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-YI-1.xml.res	1970-01-01 00:00:00 +0000
+++ test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-YI-1.xml.res	2013-03-20 21:54:22 +0000
@@ -0,0 +1,1 @@
+true

=== added file 'test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-Yi-2.xml.res'
--- test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-Yi-2.xml.res	1970-01-01 00:00:00 +0000
+++ test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-Yi-2.xml.res	2013-03-20 21:54:22 +0000
@@ -0,0 +1,1 @@
+true

=== renamed file 'test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/FormatDateFuncYearDefaultExtraChars.xml.res' => 'test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-chars.xml.res'
--- test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/FormatDateFuncYearDefaultExtraChars.xml.res	2013-02-07 17:24:36 +0000
+++ test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-chars.xml.res	2013-03-20 21:54:22 +0000
@@ -1,1 +1,1 @@
-true
\ No newline at end of file
+true

=== renamed file 'test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/FormatDateFuncMonthNumberSpaces.xml.res' => 'test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-whitespace.xml.res'
--- test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/FormatDateFuncMonthNumberSpaces.xml.res	2013-02-07 17:24:36 +0000
+++ test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-whitespace.xml.res	2013-03-20 21:54:22 +0000
@@ -1,1 +1,1 @@
-true
\ No newline at end of file
+true

=== renamed file 'test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/FormatDateTimeFuncReflexivity.xml.res' => 'test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-dateTime-01.xml.res'
--- test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/FormatDateTimeFuncReflexivity.xml.res	2013-02-07 17:24:36 +0000
+++ test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-dateTime-01.xml.res	2013-03-20 21:54:22 +0000
@@ -1,1 +1,1 @@
-true
\ No newline at end of file
+true

=== added file 'test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-time-H-1.xml.res'
--- test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-time-H-1.xml.res	1970-01-01 00:00:00 +0000
+++ test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-time-H-1.xml.res	2013-03-20 21:54:22 +0000
@@ -0,0 +1,1 @@
+true

=== added file 'test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-time-P-1.xml.res'
--- test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-time-P-1.xml.res	1970-01-01 00:00:00 +0000
+++ test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-time-P-1.xml.res	2013-03-20 21:54:22 +0000
@@ -0,0 +1,1 @@
+true

=== added file 'test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-time-P-2.xml.res'
--- test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-time-P-2.xml.res	1970-01-01 00:00:00 +0000
+++ test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-time-P-2.xml.res	2013-03-20 21:54:22 +0000
@@ -0,0 +1,1 @@
+true

=== added file 'test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-time-P-3.xml.res'
--- test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-time-P-3.xml.res	1970-01-01 00:00:00 +0000
+++ test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-time-P-3.xml.res	2013-03-20 21:54:22 +0000
@@ -0,0 +1,1 @@
+true

=== added file 'test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-time-Z0-1.xml.res'
--- test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-time-Z0-1.xml.res	1970-01-01 00:00:00 +0000
+++ test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-time-Z0-1.xml.res	2013-03-20 21:54:22 +0000
@@ -0,0 +1,1 @@
+true

=== added file 'test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-time-Z0-2.xml.res'
--- test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-time-Z0-2.xml.res	1970-01-01 00:00:00 +0000
+++ test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-time-Z0-2.xml.res	2013-03-20 21:54:22 +0000
@@ -0,0 +1,1 @@
+true

=== added file 'test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-time-Z0000.xml.res'
--- test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-time-Z0000.xml.res	1970-01-01 00:00:00 +0000
+++ test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-time-Z0000.xml.res	2013-03-20 21:54:22 +0000
@@ -0,0 +1,1 @@
+true

=== added file 'test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-time-Z00_00.xml.res'
--- test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-time-Z00_00.xml.res	1970-01-01 00:00:00 +0000
+++ test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-time-Z00_00.xml.res	2013-03-20 21:54:22 +0000
@@ -0,0 +1,1 @@
+true

=== added file 'test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-time-Z00_00t-1.xml.res'
--- test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-time-Z00_00t-1.xml.res	1970-01-01 00:00:00 +0000
+++ test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-time-Z00_00t-1.xml.res	2013-03-20 21:54:22 +0000
@@ -0,0 +1,1 @@
+true

=== added file 'test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-time-Z00_00t-2.xml.res'
--- test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-time-Z00_00t-2.xml.res	1970-01-01 00:00:00 +0000
+++ test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-time-Z00_00t-2.xml.res	2013-03-20 21:54:22 +0000
@@ -0,0 +1,1 @@
+true

=== added file 'test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-time-Z0_00.xml.res'
--- test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-time-Z0_00.xml.res	1970-01-01 00:00:00 +0000
+++ test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-time-Z0_00.xml.res	2013-03-20 21:54:22 +0000
@@ -0,0 +1,1 @@
+true

=== added file 'test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-time-ZN-CST.xml.res'
--- test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-time-ZN-CST.xml.res	1970-01-01 00:00:00 +0000
+++ test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-time-ZN-CST.xml.res	2013-03-20 21:54:22 +0000
@@ -0,0 +1,1 @@
+true

=== added file 'test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-time-ZN-EST.xml.res'
--- test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-time-ZN-EST.xml.res	1970-01-01 00:00:00 +0000
+++ test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-time-ZN-EST.xml.res	2013-03-20 21:54:22 +0000
@@ -0,0 +1,1 @@
+true

=== added file 'test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-time-ZN-GMT.xml.res'
--- test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-time-ZN-GMT.xml.res	1970-01-01 00:00:00 +0000
+++ test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-time-ZN-GMT.xml.res	2013-03-20 21:54:22 +0000
@@ -0,0 +1,1 @@
+true

=== added file 'test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-time-ZN-MST.xml.res'
--- test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-time-ZN-MST.xml.res	1970-01-01 00:00:00 +0000
+++ test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-time-ZN-MST.xml.res	2013-03-20 21:54:22 +0000
@@ -0,0 +1,1 @@
+true

=== added file 'test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-time-ZN-PST.xml.res'
--- test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-time-ZN-PST.xml.res	1970-01-01 00:00:00 +0000
+++ test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-time-ZN-PST.xml.res	2013-03-20 21:54:22 +0000
@@ -0,0 +1,1 @@
+true

=== added file 'test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-time-ZZ-1.xml.res'
--- test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-time-ZZ-1.xml.res	1970-01-01 00:00:00 +0000
+++ test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-time-ZZ-1.xml.res	2013-03-20 21:54:22 +0000
@@ -0,0 +1,1 @@
+true

=== added file 'test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-time-ZZ-2.xml.res'
--- test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-time-ZZ-2.xml.res	1970-01-01 00:00:00 +0000
+++ test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-time-ZZ-2.xml.res	2013-03-20 21:54:22 +0000
@@ -0,0 +1,1 @@
+true

=== added file 'test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-time-h-2.xml.res'
--- test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-time-h-2.xml.res	1970-01-01 00:00:00 +0000
+++ test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-time-h-2.xml.res	2013-03-20 21:54:22 +0000
@@ -0,0 +1,1 @@
+true

=== added file 'test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-time-z.xml.res'
--- test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-time-z.xml.res	1970-01-01 00:00:00 +0000
+++ test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-time-z.xml.res	2013-03-20 21:54:22 +0000
@@ -0,0 +1,1 @@
+true

=== removed file 'test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/FormatDateFuncYearMonth1.xq'
--- test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/FormatDateFuncYearMonth1.xq	2013-02-07 17:24:36 +0000
+++ test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/FormatDateFuncYearMonth1.xq	1970-01-01 00:00:00 +0000
@@ -1,1 +0,0 @@
-fn:format-date(xs:date("2010-12-31"), "[Y][M]") eq "201012"

=== removed file 'test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/FormatDateFuncYearMonth2.xq'
--- test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/FormatDateFuncYearMonth2.xq	2013-02-07 17:24:36 +0000
+++ test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/FormatDateFuncYearMonth2.xq	1970-01-01 00:00:00 +0000
@@ -1,1 +0,0 @@
-fn:format-date(xs:date("2010-12-31"), "[Y].[M]") eq "2010.12"
\ No newline at end of file

=== added file 'test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-date-BadComponent.spec'
--- test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-date-BadComponent.spec	1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-date-BadComponent.spec	2013-03-20 21:54:22 +0000
@@ -0,0 +1,1 @@
+Error: http://www.w3.org/2005/xqt-errors:FOFD1340

=== added file 'test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-date-BadComponent.xq'
--- test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-date-BadComponent.xq	1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-date-BadComponent.xq	2013-03-20 21:54:22 +0000
@@ -0,0 +1,1 @@
+fn:format-date( xs:date("2012-01-02"), "[A]" )

=== added file 'test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-date-CharExpected-1.spec'
--- test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-date-CharExpected-1.spec	1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-date-CharExpected-1.spec	2013-03-20 21:54:22 +0000
@@ -0,0 +1,1 @@
+Error: http://www.w3.org/2005/xqt-errors:FOFD1340

=== added file 'test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-date-CharExpected-1.xq'
--- test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-date-CharExpected-1.xq	1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-date-CharExpected-1.xq	2013-03-20 21:54:22 +0000
@@ -0,0 +1,1 @@
+fn:format-date( xs:date("2012-01-02"), "[Y" )

=== added file 'test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-date-D.xq'
--- test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-date-D.xq	1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-date-D.xq	2013-03-20 21:54:22 +0000
@@ -0,0 +1,2 @@
+(: Default presentation modifier for D is 1, so a number should be the result :)
+fn:format-date( xs:date("2010-12-03"), "[D]" ) eq "3"

=== added file 'test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-date-D01.xq'
--- test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-date-D01.xq	1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-date-D01.xq	2013-03-20 21:54:22 +0000
@@ -0,0 +1,2 @@
+(: D as a 2-digit number :)
+fn:format-date( xs:date("2010-12-03"), "[D01]" ) eq "03"

=== added file 'test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-date-DW-1.xq'
--- test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-date-DW-1.xq	1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-date-DW-1.xq	2013-03-20 21:54:22 +0000
@@ -0,0 +1,1 @@
+fn:format-date( xs:date("2010-12-31"), "[DW]", "en-US", (), () ) eq "THIRTY ONE"

=== added file 'test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-date-DWw.xq'
--- test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-date-DWw.xq	1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-date-DWw.xq	2013-03-20 21:54:22 +0000
@@ -0,0 +1,1 @@
+fn:format-date( xs:date("2010-12-31"), "[DWw]", "en-US", (), () ) eq "Thirty One"

=== added file 'test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-date-Dw-2.xq'
--- test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-date-Dw-2.xq	1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-date-Dw-2.xq	2013-03-20 21:54:22 +0000
@@ -0,0 +1,1 @@
+fn:format-date( xs:date("2010-12-31"), "[Dw]", "en-US", (), () ) eq "thirty one"

=== added file 'test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-date-FN-1.xq'
--- test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-date-FN-1.xq	1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-date-FN-1.xq	2013-03-20 21:54:22 +0000
@@ -0,0 +1,1 @@
+fn:format-date( xs:date("1967-11-18"), "[FN]", "en-US", (), () ) eq "SATURDAY"

=== added file 'test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-date-FN-3.xq'
--- test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-date-FN-3.xq	1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-date-FN-3.xq	2013-03-20 21:54:22 +0000
@@ -0,0 +1,1 @@
+fn:format-date( xs:date("1967-11-18"), "[FN]", "de-DE", (), () ) eq "SAMSTAG"

=== added file 'test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-date-FNn-1.xq'
--- test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-date-FNn-1.xq	1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-date-FNn-1.xq	2013-03-20 21:54:22 +0000
@@ -0,0 +1,1 @@
+fn:format-date( xs:date("1967-11-18"), "[FNn]", "en-US", (), () ) eq "Saturday"

=== added file 'test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-date-FNn-2.xq'
--- test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-date-FNn-2.xq	1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-date-FNn-2.xq	2013-03-20 21:54:22 +0000
@@ -0,0 +1,1 @@
+fn:format-date( xs:date("1967-11-18"), "[FNn]", "de-DE", (), () ) eq "Samstag"

=== added file 'test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-date-Fn-2.xq'
--- test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-date-Fn-2.xq	1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-date-Fn-2.xq	2013-03-20 21:54:22 +0000
@@ -0,0 +1,1 @@
+fn:format-date( xs:date("1967-11-18"), "[Fn]", "en-US", (), () ) eq "saturday"

=== added file 'test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-date-Fn-4.xq'
--- test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-date-Fn-4.xq	1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-date-Fn-4.xq	2013-03-20 21:54:22 +0000
@@ -0,0 +1,1 @@
+fn:format-date( xs:date("1967-11-18"), "[Fn]", "de-DE", (), () ) eq "samstag"

=== renamed file 'test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/FormatDateFuncMonthDefault.xq' => 'test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-date-M.xq'
--- test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/FormatDateFuncMonthDefault.xq	2013-02-07 17:24:36 +0000
+++ test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-date-M.xq	2013-03-20 21:54:22 +0000
@@ -1,2 +1,2 @@
-(: Default Presentation Modifier for M is 1, so a number should be the result :)
-fn:format-date(xs:date("2010-12-31"), "[M]") eq "12"
+(: Default presentation modifier for M is 1, so a number should be the result :)
+fn:format-date( xs:date("2010-12-31"), "[M]" ) eq "12"

=== renamed file 'test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/FormatDateFuncMonthNumber.xq' => 'test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-date-M01.xq'
--- test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/FormatDateFuncMonthNumber.xq	2013-02-07 17:24:36 +0000
+++ test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-date-M01.xq	2013-03-20 21:54:22 +0000
@@ -1,2 +1,2 @@
-(: M as number on 2 digits :)
-fn:format-date(xs:date("2010-12-31"), "[M01]") eq "12"
+(: M as a 2-digit number :)
+fn:format-date(xs:date("2010-01-31"), "[M01]") eq "01"

=== renamed file 'test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/FormatDateFuncMonthUpperCase.xq' => 'test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-date-MN-1.xq'
--- test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/FormatDateFuncMonthUpperCase.xq	2013-02-07 17:24:36 +0000
+++ test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-date-MN-1.xq	2013-03-20 21:54:22 +0000
@@ -1,2 +1,2 @@
 (: M as word in upper case :)
-fn:format-date(xs:date("2010-12-31"), "[MN]") eq "DECEMBER"
+fn:format-date( xs:date("2010-12-31"), "[MN]", "en-US", (), () ) eq "DECEMBER"

=== renamed file 'test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/FormatDateFuncMonthTitleCase.xq' => 'test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-date-MNn.xq'
--- test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/FormatDateFuncMonthTitleCase.xq	2013-02-07 17:24:36 +0000
+++ test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-date-MNn.xq	2013-03-20 21:54:22 +0000
@@ -1,2 +1,2 @@
 (: M as word in title case :)
-fn:format-date(xs:date("2010-12-31"), "[MNn]") eq "December"
+fn:format-date( xs:date("2010-12-31"), "[MNn]", "en-US", (), () ) eq "December"

=== renamed file 'test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/FormatDateFuncMonthLowerCase.xq' => 'test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-date-Mn-2.xq'
--- test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/FormatDateFuncMonthLowerCase.xq	2013-02-07 17:24:36 +0000
+++ test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-date-Mn-2.xq	2013-03-20 21:54:22 +0000
@@ -1,2 +1,2 @@
 (: M as word in lower case :)
-fn:format-date(xs:date("2010-12-31"), "[Mn]") eq "december"
+fn:format-date( xs:date("2010-12-31"), "[Mn]", "en-US", (), () ) eq "december"

=== added file 'test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-date-NoAdjacentGroupSep.spec'
--- test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-date-NoAdjacentGroupSep.spec	1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-date-NoAdjacentGroupSep.spec	2013-03-20 21:54:22 +0000
@@ -0,0 +1,1 @@
+Error: http://www.w3.org/2005/xqt-errors:FOFD1340

=== added file 'test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-date-NoAdjacentGroupSep.xq'
--- test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-date-NoAdjacentGroupSep.xq	1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-date-NoAdjacentGroupSep.xq	2013-03-20 21:54:22 +0000
@@ -0,0 +1,1 @@
+fn:format-date( xs:date("2012-01-02"), "[Y00''00]" )

=== added file 'test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-date-NoComponent.spec'
--- test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-date-NoComponent.spec	1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-date-NoComponent.spec	2013-03-20 21:54:22 +0000
@@ -0,0 +1,1 @@
+Error: http://www.w3.org/2005/xqt-errors:FOFD1340

=== added file 'test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-date-NoComponent.xq'
--- test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-date-NoComponent.xq	1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-date-NoComponent.xq	2013-03-20 21:54:22 +0000
@@ -0,0 +1,1 @@
+fn:format-date( xs:date("2012-01-02"), "[]" )

=== added file 'test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-date-NoGroupSepAtEnd.spec'
--- test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-date-NoGroupSepAtEnd.spec	1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-date-NoGroupSepAtEnd.spec	2013-03-20 21:54:22 +0000
@@ -0,0 +1,1 @@
+Error: http://www.w3.org/2005/xqt-errors:FOFD1340

=== added file 'test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-date-NoGroupSepAtEnd.xq'
--- test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-date-NoGroupSepAtEnd.xq	1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-date-NoGroupSepAtEnd.xq	2013-03-20 21:54:22 +0000
@@ -0,0 +1,1 @@
+fn:format-date( xs:date("2012-01-02"), "[Y00']" )

=== added file 'test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-date-NoGroupSepAtStart.spec'
--- test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-date-NoGroupSepAtStart.spec	1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-date-NoGroupSepAtStart.spec	2013-03-20 21:54:22 +0000
@@ -0,0 +1,1 @@
+Error: http://www.w3.org/2005/xqt-errors:FOFD1340

=== added file 'test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-date-NoGroupSepAtStart.xq'
--- test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-date-NoGroupSepAtStart.xq	1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-date-NoGroupSepAtStart.xq	2013-03-20 21:54:22 +0000
@@ -0,0 +1,1 @@
+fn:format-date( xs:date("2012-01-02"), "[Y']" )

=== added file 'test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-date-NoOptDigitAfterMandatory.spec'
--- test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-date-NoOptDigitAfterMandatory.spec	1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-date-NoOptDigitAfterMandatory.spec	2013-03-20 21:54:22 +0000
@@ -0,0 +1,1 @@
+Error: http://www.w3.org/2005/xqt-errors:FOFD1340

=== added file 'test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-date-NoOptDigitAfterMandatory.xq'
--- test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-date-NoOptDigitAfterMandatory.xq	1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-date-NoOptDigitAfterMandatory.xq	2013-03-20 21:54:22 +0000
@@ -0,0 +1,1 @@
+fn:format-date( xs:date("2012-01-02"), "[Y0#]" )

=== renamed file 'test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/FormatDateFuncYearMaxWidth.xq' => 'test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-date-Y-2-2.xq'
--- test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/FormatDateFuncYearMaxWidth.xq	2013-02-07 17:24:36 +0000
+++ test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-date-Y-2-2.xq	2013-03-20 21:54:22 +0000
@@ -1,2 +1,2 @@
-(: if max-width is set to 2 then the year 2003 will be output as 03 :)
-fn:format-date(xs:date("2010-12-31"), "[Y,2-2]") eq "10"
+(: If max-width is set to 2, then the year 2003 will be output as 03 :)
+fn:format-date( xs:date("2003-12-31"), "[Y,2-2]" ) eq "03"

=== renamed file 'test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/FormatDateFuncReflexivity.xq' => 'test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-date-Y-M01-D01.xq'
--- test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/FormatDateFuncReflexivity.xq	2013-02-07 17:24:36 +0000
+++ test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-date-Y-M01-D01.xq	2013-03-20 21:54:22 +0000
@@ -1,3 +1,3 @@
-let $date := xs:date("2010-12-31")
-let $newDate := xs:date(fn:format-date($date, "[Y]-[M01]-[D01]"))
-return $date eq $newDate
+let $old := xs:date( "2010-12-31" )
+let $new := xs:date( fn:format-date( $old, "[Y]-[M01]-[D01]" ) )
+return $new eq $old

=== added file 'test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-date-Y-Thai-1.xq'
--- test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-date-Y-Thai-1.xq	1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-date-Y-Thai-1.xq	2013-03-20 21:54:22 +0000
@@ -0,0 +1,1 @@
+fn:format-date( xs:date("2003-09-07"), "[Y๐๐๐๑]" ) eq "๒๐๐๓"

=== added file 'test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-date-Y-Thai-2.xq'
--- test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-date-Y-Thai-2.xq	1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-date-Y-Thai-2.xq	2013-03-20 21:54:22 +0000
@@ -0,0 +1,1 @@
+fn:format-date( xs:date("2003-09-07"), "[Y๐๑]" ) eq "๐๓"

=== renamed file 'test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/FormatDateFuncYearDefault.xq' => 'test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-date-Y.xq'
--- test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/FormatDateFuncYearDefault.xq	2013-02-07 17:24:36 +0000
+++ test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-date-Y.xq	2013-03-20 21:54:22 +0000
@@ -1,2 +1,1 @@
-(: Default Presentation Modifier for Y is 1, so a number should be the result :)
-fn:format-date(xs:date("2010-12-31"), "[Y]") eq "2010"
+fn:format-date( xs:date("2010-12-31"), "[Y]" ) eq "2010"

=== added file 'test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-date-YI-1.xq'
--- test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-date-YI-1.xq	1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-date-YI-1.xq	2013-03-20 21:54:22 +0000
@@ -0,0 +1,1 @@
+fn:format-date( xs:date("1967-11-18"), "[YI]" ) eq "MCMLXVII"

=== added file 'test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-date-Yi-2.xq'
--- test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-date-Yi-2.xq	1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-date-Yi-2.xq	2013-03-20 21:54:22 +0000
@@ -0,0 +1,1 @@
+fn:format-date( xs:date("1967-11-18"), "[Yi]" ) eq "mcmlxvii"

=== renamed file 'test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/FormatDateFuncYearDefaultExtraChars.xq' => 'test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-date-chars.xq'
--- test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/FormatDateFuncYearDefaultExtraChars.xq	2013-02-07 17:24:36 +0000
+++ test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-date-chars.xq	2013-03-20 21:54:22 +0000
@@ -1,2 +1,2 @@
-(: Default Presentation Modifier for M is 1, so a number should be the result :)
-fn:format-date(xs:date("2010-12-31"), "[Y]. this should also come in the output") eq "2010. this should also come in the output"
+(: extra chars passed through as-as :)
+fn:format-date( xs:date("2010-12-31"), "extra [Y] chars" ) eq "extra 2010 chars"

=== renamed file 'test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/FormatDateFuncMonthNumberSpaces.xq' => 'test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-date-whitespace.xq'
--- test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/FormatDateFuncMonthNumberSpaces.xq	2013-02-07 17:24:36 +0000
+++ test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-date-whitespace.xq	2013-03-20 21:54:22 +0000
@@ -1,6 +1,6 @@
-(: whitespaces in variable markers are ignored :)
-fn:format-date(xs:date("2010-12-31"), "[
+(: Whitespace in variable markers should be ignored :)
+fn:format-date( xs:date("2010-12-31"), "[
  M	 
 	01
-  ]")
-eq "12"
\ No newline at end of file
+  ]" )
+eq "12"

=== renamed file 'test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/FormatDateTimeFuncReflexivity.xq' => 'test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-dateTime-01.xq'
--- test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/FormatDateTimeFuncReflexivity.xq	2013-02-07 17:24:36 +0000
+++ test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-dateTime-01.xq	2013-03-20 21:54:22 +0000
@@ -1,3 +1,3 @@
-let $dateTime := xs:dateTime("2010-11-12T13:14:15.167")
-let $newDateTime := xs:dateTime(fn:format-dateTime($dateTime, "[Y]-[M01]-[D01]T[H01]:[m01]:[s01].[f001]"))
-return $dateTime eq $newDateTime 
+let $old := xs:dateTime( "2010-11-12T13:14:15.167" )
+let $new := xs:dateTime( fn:format-dateTime( $old, "[Y]-[M01]-[D01]T[H01]:[m01]:[s01].[f001]" ) )
+return $new eq $old 

=== added file 'test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-time-H-1.xq'
--- test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-time-H-1.xq	1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-time-H-1.xq	2013-03-20 21:54:22 +0000
@@ -0,0 +1,1 @@
+fn:format-time( xs:time("21:14:00"), "[H]" ) eq "21"

=== added file 'test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-time-P-1.xq'
--- test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-time-P-1.xq	1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-time-P-1.xq	2013-03-20 21:54:22 +0000
@@ -0,0 +1,1 @@
+fn:format-time( xs:time("09:14:00"), "[P]", "en-US", (), () ) eq "am"

=== added file 'test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-time-P-2.xq'
--- test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-time-P-2.xq	1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-time-P-2.xq	2013-03-20 21:54:22 +0000
@@ -0,0 +1,1 @@
+fn:format-time( xs:time("21:14:00"), "[P]", "en-US", (), () ) eq "pm"

=== added file 'test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-time-P-3.xq'
--- test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-time-P-3.xq	1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-time-P-3.xq	2013-03-20 21:54:22 +0000
@@ -0,0 +1,1 @@
+fn:format-time( xs:time("21:14:00"), "[PN]", "en-US", (), () ) eq "PM"

=== added file 'test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-time-Z0-1.xq'
--- test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-time-Z0-1.xq	1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-time-Z0-1.xq	2013-03-20 21:54:22 +0000
@@ -0,0 +1,1 @@
+fn:format-time( xs:time("09:14:00-08:00"), "[Z0]" ) eq "-8"

=== added file 'test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-time-Z0-2.xq'
--- test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-time-Z0-2.xq	1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-time-Z0-2.xq	2013-03-20 21:54:22 +0000
@@ -0,0 +1,1 @@
+fn:format-time( xs:time("09:14:00-08:30"), "[Z0]" ) eq "-8:30"

=== added file 'test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-time-Z0000.xq'
--- test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-time-Z0000.xq	1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-time-Z0000.xq	2013-03-20 21:54:22 +0000
@@ -0,0 +1,1 @@
+fn:format-time( xs:time("09:14:00-08:30"), "[Z0000]" ) eq "-0830"

=== added file 'test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-time-Z00_00.xq'
--- test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-time-Z00_00.xq	1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-time-Z00_00.xq	2013-03-20 21:54:22 +0000
@@ -0,0 +1,1 @@
+fn:format-time( xs:time("09:14:00-08:30"), "[Z00:00]" ) eq "-08:30"

=== added file 'test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-time-Z00_00t-1.xq'
--- test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-time-Z00_00t-1.xq	1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-time-Z00_00t-1.xq	2013-03-20 21:54:22 +0000
@@ -0,0 +1,1 @@
+fn:format-time( xs:time("09:14:00-08:30"), "[Z00:00t]" ) eq "-08:30"

=== added file 'test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-time-Z00_00t-2.xq'
--- test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-time-Z00_00t-2.xq	1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-time-Z00_00t-2.xq	2013-03-20 21:54:22 +0000
@@ -0,0 +1,1 @@
+fn:format-time( xs:time("09:14:00+00:00"), "[Z00:00t]" ) eq "Z"

=== added file 'test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-time-Z0_00.xq'
--- test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-time-Z0_00.xq	1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-time-Z0_00.xq	2013-03-20 21:54:22 +0000
@@ -0,0 +1,1 @@
+fn:format-time( xs:time("09:14:00-08:30"), "[Z0:00]" ) eq "-8:30"

=== added file 'test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-time-ZN-CST.xq'
--- test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-time-ZN-CST.xq	1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-time-ZN-CST.xq	2013-03-20 21:54:22 +0000
@@ -0,0 +1,1 @@
+fn:format-time( xs:time("09:14:00-06:00"), "[ZN]" ) eq "CST"

=== added file 'test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-time-ZN-EST.xq'
--- test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-time-ZN-EST.xq	1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-time-ZN-EST.xq	2013-03-20 21:54:22 +0000
@@ -0,0 +1,1 @@
+fn:format-time( xs:time("09:14:00-05:00"), "[ZN]" ) eq "EST"

=== added file 'test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-time-ZN-GMT.xq'
--- test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-time-ZN-GMT.xq	1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-time-ZN-GMT.xq	2013-03-20 21:54:22 +0000
@@ -0,0 +1,1 @@
+fn:format-time( xs:time("09:14:00+00:00"), "[ZN]" ) eq "GMT"

=== added file 'test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-time-ZN-MST.xq'
--- test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-time-ZN-MST.xq	1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-time-ZN-MST.xq	2013-03-20 21:54:22 +0000
@@ -0,0 +1,1 @@
+fn:format-time( xs:time("09:14:00-07:00"), "[ZN]" ) eq "MST"

=== added file 'test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-time-ZN-PST.xq'
--- test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-time-ZN-PST.xq	1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-time-ZN-PST.xq	2013-03-20 21:54:22 +0000
@@ -0,0 +1,1 @@
+fn:format-time( xs:time("09:14:00-08:00"), "[ZN]" ) eq "PST"

=== added file 'test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-time-ZZ-1.xq'
--- test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-time-ZZ-1.xq	1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-time-ZZ-1.xq	2013-03-20 21:54:22 +0000
@@ -0,0 +1,1 @@
+fn:format-time( xs:time("09:14:00-08:00"), "[ZZ]" ) eq "U"

=== added file 'test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-time-ZZ-2.xq'
--- test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-time-ZZ-2.xq	1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-time-ZZ-2.xq	2013-03-20 21:54:22 +0000
@@ -0,0 +1,1 @@
+fn:format-time( xs:time("09:14:00-08:30"), "[ZZ]" ) eq "-08:30"

=== added file 'test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-time-h-2.xq'
--- test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-time-h-2.xq	1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-time-h-2.xq	2013-03-20 21:54:22 +0000
@@ -0,0 +1,1 @@
+fn:format-time( xs:time("21:14:00"), "[h]" ) eq "9"

=== added file 'test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-time-z.xq'
--- test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-time-z.xq	1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-time-z.xq	2013-03-20 21:54:22 +0000
@@ -0,0 +1,1 @@
+fn:format-time( xs:time("09:14:00-08:00"), "[z]" ) eq "GMT-08:00"


Follow ups