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

Proposed by Paul J. Lucas
Status: Merged
Approved by: Matthias Brantner
Approved revision: 11331
Merged at revision: 11302
Proposed branch: lp:~zorba-coders/zorba/bug-1123162
Merge into: lp:zorba
Diff against target: 5539 lines (+2779/-934)
156 files modified
ChangeLog (+3/-0)
include/zorba/dynamic_context.h (+15/-0)
include/zorba/locale.h (+1/-1)
include/zorba/pregenerated/diagnostic_list.h (+2/-2)
include/zorba/time.h (+68/-0)
modules/org/expath/ns/file.xq.src/file.cpp (+1/-1)
modules/w3c/pregenerated/xqt-errors.xq (+5/-5)
modules/xqxq/xqxq.xq.src/xqxq.cpp (+1/-1)
src/api/dynamiccontextimpl.cpp (+11/-0)
src/api/dynamiccontextimpl.h (+6/-0)
src/context/dynamic_context.cpp (+2/-0)
src/context/dynamic_context.h (+10/-0)
src/diagnostics/diagnostic_en.xml (+39/-9)
src/diagnostics/pregenerated/diagnostic_list.cpp (+4/-4)
src/diagnostics/pregenerated/dict_en.cpp (+12/-2)
src/diagnostics/pregenerated/dict_zed_keys.h (+10/-0)
src/functions/func_durations_dates_times_impl.cpp (+1/-0)
src/runtime/CMakeLists.txt (+1/-0)
src/runtime/durations_dates_times/DurationsDatesTimesImpl.cpp (+0/-560)
src/runtime/durations_dates_times/DurationsDatesTimesImpl.h (+5/-46)
src/runtime/durations_dates_times/format_dateTime.cpp (+1377/-0)
src/runtime/durations_dates_times/format_dateTime.h (+81/-0)
src/runtime/visitors/printer_visitor_impl.cpp (+1/-0)
src/unit_tests/CMakeLists.txt (+1/-0)
src/unit_tests/test_time.cpp (+118/-0)
src/unit_tests/unit_test_list.h (+1/-0)
src/unit_tests/unit_tests.cpp (+1/-0)
src/util/ascii_util.h (+54/-0)
src/util/stream_util.cpp (+31/-0)
src/util/stream_util.h (+14/-0)
src/util/time_util.cpp (+152/-14)
src/util/time_util.h (+170/-25)
src/util/unicode_util.cpp (+18/-0)
src/util/unicode_util.h (+17/-0)
src/util/utf8_string.h (+25/-0)
src/util/utf8_util.cpp (+32/-0)
src/util/utf8_util.h (+67/-0)
src/zorbatypes/datetime.h (+0/-9)
src/zorbatypes/datetime/datetimetype.cpp (+85/-151)
src/zorbautils/locale.cpp (+205/-0)
src/zorbautils/locale.h (+9/-0)
test/fots/CMakeLists.txt (+0/-66)
test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/FormatDateFuncYearMonth1.xml.res (+0/-1)
test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/FormatDateFuncYearMonth2.xml.res (+0/-1)
test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-D.xml.res (+1/-0)
test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-D01.xml.res (+1/-0)
test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-D1o.xml.res (+1/-0)
test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-DW-1.xml.res (+1/-0)
test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-DWo-1.xml.res (+1/-0)
test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-DWw.xml.res (+1/-0)
test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-DWwo.xml.res (+1/-0)
test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-Dw-2.xml.res (+1/-0)
test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-Dwo-2.xml.res (+1/-0)
test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-FN-1.xml.res (+1/-0)
test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-FN-3.xml.res (+1/-0)
test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-FNn-1.xml.res (+1/-0)
test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-FNn-2.xml.res (+1/-0)
test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-Fn-2.xml.res (+1/-0)
test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-Fn-4.xml.res (+1/-0)
test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-M.xml.res (+1/-1)
test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-M01.xml.res (+1/-1)
test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-MN-1.xml.res (+1/-1)
test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-MNn.xml.res (+1/-1)
test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-Mn-2.xml.res (+1/-1)
test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-Y-2-2.xml.res (+1/-1)
test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-Y-M01-D01.xml.res (+1/-1)
test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-Y-Thai-1.xml.res (+1/-0)
test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-Y-Thai-2.xml.res (+1/-0)
test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-Y.xml.res (+1/-1)
test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-YI-1.xml.res (+1/-0)
test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-Yi-2.xml.res (+1/-0)
test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-chars.xml.res (+1/-1)
test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-whitespace.xml.res (+1/-1)
test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-dateTime-01.xml.res (+1/-1)
test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-time-H-1.xml.res (+1/-0)
test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-time-P-1.xml.res (+1/-0)
test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-time-P-2.xml.res (+1/-0)
test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-time-P-3.xml.res (+1/-0)
test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-time-Z0-1.xml.res (+1/-0)
test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-time-Z0-2.xml.res (+1/-0)
test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-time-Z0000.xml.res (+1/-0)
test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-time-Z00_00.xml.res (+1/-0)
test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-time-Z00_00t-1.xml.res (+1/-0)
test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-time-Z00_00t-2.xml.res (+1/-0)
test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-time-Z0_00.xml.res (+1/-0)
test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-time-ZN-CST.xml.res (+1/-0)
test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-time-ZN-EST.xml.res (+1/-0)
test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-time-ZN-GMT.xml.res (+1/-0)
test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-time-ZN-MST.xml.res (+1/-0)
test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-time-ZN-PST.xml.res (+1/-0)
test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-time-ZZ-1.xml.res (+1/-0)
test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-time-ZZ-2.xml.res (+1/-0)
test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-time-h-2.xml.res (+1/-0)
test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-time-z.xml.res (+1/-0)
test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/FormatDateFuncYearMonth1.xq (+0/-1)
test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/FormatDateFuncYearMonth2.xq (+0/-1)
test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-date-BadComponent.spec (+1/-0)
test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-date-BadComponent.xq (+1/-0)
test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-date-CharExpected-1.spec (+1/-0)
test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-date-CharExpected-1.xq (+1/-0)
test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-date-D.xq (+2/-0)
test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-date-D01.xq (+2/-0)
test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-date-DW-1.xq (+1/-0)
test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-date-DWw.xq (+1/-0)
test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-date-Dw-2.xq (+1/-0)
test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-date-FN-1.xq (+1/-0)
test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-date-FN-3.xq (+1/-0)
test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-date-FNn-1.xq (+1/-0)
test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-date-FNn-2.xq (+1/-0)
test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-date-Fn-2.xq (+1/-0)
test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-date-Fn-4.xq (+1/-0)
test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-date-M.xq (+2/-2)
test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-date-M01.xq (+2/-2)
test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-date-MN-1.xq (+1/-1)
test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-date-MNn.xq (+1/-1)
test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-date-Mn-2.xq (+1/-1)
test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-date-NoAdjacentGroupSep.spec (+1/-0)
test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-date-NoAdjacentGroupSep.xq (+1/-0)
test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-date-NoComponent.spec (+1/-0)
test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-date-NoComponent.xq (+1/-0)
test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-date-NoGroupSepAtEnd.spec (+1/-0)
test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-date-NoGroupSepAtEnd.xq (+1/-0)
test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-date-NoGroupSepAtStart.spec (+1/-0)
test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-date-NoGroupSepAtStart.xq (+1/-0)
test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-date-NoOptDigitAfterMandatory.spec (+1/-0)
test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-date-NoOptDigitAfterMandatory.xq (+1/-0)
test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-date-Y-2-2.xq (+2/-2)
test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-date-Y-M01-D01.xq (+3/-3)
test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-date-Y-Thai-1.xq (+1/-0)
test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-date-Y-Thai-2.xq (+1/-0)
test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-date-Y.xq (+1/-2)
test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-date-YI-1.xq (+1/-0)
test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-date-Yi-2.xq (+1/-0)
test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-date-chars.xq (+2/-2)
test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-date-whitespace.xq (+4/-4)
test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-dateTime-01.xq (+3/-3)
test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-time-H-1.xq (+1/-0)
test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-time-P-1.xq (+1/-0)
test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-time-P-2.xq (+1/-0)
test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-time-P-3.xq (+1/-0)
test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-time-Z0-1.xq (+1/-0)
test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-time-Z0-2.xq (+1/-0)
test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-time-Z0000.xq (+1/-0)
test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-time-Z00_00.xq (+1/-0)
test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-time-Z00_00t-1.xq (+1/-0)
test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-time-Z00_00t-2.xq (+1/-0)
test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-time-Z0_00.xq (+1/-0)
test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-time-ZN-CST.xq (+1/-0)
test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-time-ZN-EST.xq (+1/-0)
test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-time-ZN-GMT.xq (+1/-0)
test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-time-ZN-MST.xq (+1/-0)
test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-time-ZN-PST.xq (+1/-0)
test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-time-ZZ-1.xq (+1/-0)
test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-time-ZZ-2.xq (+1/-0)
test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-time-h-2.xq (+1/-0)
test/rbkt/Queries/zorba/durationdatetime/FormatDateTimeFunc/format-time-z.xq (+1/-0)
To merge this branch: bzr merge lp:~zorba-coders/zorba/bug-1123162
Reviewer Review Type Date Requested Status
Matthias Brantner Approve
Sorin Marian Nasoi Approve
Nicolae Brinza Approve
Paul J. Lucas Approve
Review via email: mp+154529@code.launchpad.net

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.

Description of the change

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.

To post a comment you must log in.
Revision history for this message
Paul J. Lucas (paul-lucas) :
review: Approve
Revision history for this message
Zorba Build Bot (zorba-buildbot) wrote :
Revision history for this message
Zorba Build Bot (zorba-buildbot) wrote :

The attempt to merge lp:~zorba-coders/zorba/bug-1123162 into lp:zorba failed. Below is the output from the failed tests.

CMake Error at /home/ceej/zo/testing/zorbatest/tester/TarmacLander.cmake:275 (message):
  Validation queue job bug-1123162-2013-03-20T22-17-21.086Z is finished. The
  final status was:

  Undetermined, probably an error - please email <email address hidden> with the
  number of this job!

Error in read script: /home/ceej/zo/testing/zorbatest/tester/TarmacLander.cmake

Revision history for this message
Chris Hillery (ceejatec) wrote :

Sorry, I killed this merge, because until https://code.launchpad.net/~zorba-coders/zorba/fix-import-fots/+merge/154533 is merged the RQ won't even run the FOTS tests.

Revision history for this message
Zorba Build Bot (zorba-buildbot) wrote :
Revision history for this message
Zorba Build Bot (zorba-buildbot) wrote :

The attempt to merge lp:~zorba-coders/zorba/bug-1123162 into lp:zorba failed. Below is the output from the failed tests.

CMake Error at /home/ceej/zo/testing/zorbatest/tester/TarmacLander.cmake:275 (message):
  Validation queue job bug-1123162-2013-03-21T01-18-27.061Z is finished. The
  final status was:

  16 tests did not succeed - changes not commited.

Error in read script: /home/ceej/zo/testing/zorbatest/tester/TarmacLander.cmake

Revision history for this message
Zorba Build Bot (zorba-buildbot) wrote :
Revision history for this message
Zorba Build Bot (zorba-buildbot) wrote :

Validation queue job bug-1123162-2013-03-21T16-03-16.698Z is finished. The final status was:

All tests succeeded!

Revision history for this message
Zorba Build Bot (zorba-buildbot) wrote :

Voting does not meet specified criteria. Required: Approve > 1, Disapprove < 1, Needs Fixing < 1, Pending < 1, Needs Information < 1, Resubmit < 1. Got: 1 Approve.

Revision history for this message
Nicolae Brinza (nbrinza) :
review: Approve
Revision history for this message
Sorin Marian Nasoi (sorin.marian.nasoi) :
review: Approve
Revision history for this message
Matthias Brantner (matthias-brantner) :
review: Approve
Revision history for this message
Zorba Build Bot (zorba-buildbot) wrote :
Revision history for this message
Zorba Build Bot (zorba-buildbot) wrote :

Validation queue job bug-1123162-2013-03-21T18-59-27.283Z is finished. The final status was:

All tests succeeded!

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'ChangeLog'
2--- ChangeLog 2013-03-20 22:28:21 +0000
3+++ ChangeLog 2013-03-21 16:00:34 +0000
4@@ -14,6 +14,8 @@
5 * In store API, added ability to specify a stream's originating URI (file)
6 for streamable strings and base64Binary.
7 * Added millis-to-dateTime() function in datetime module.
8+ * Added setCalendar(), getCalendar(), setLocale(), and getLocale() to
9+ DynamicContext class in C++ API.
10 * fn:trace outputs "empty-sequence()" if the input is the empty-sequence.
11 * Allow multiple default function namespaces.
12 * Added xqxq:variable-value function.
13@@ -33,6 +35,7 @@
14 * Fixed bug #1095889 (Improve error message for xml-parsing error).
15 * Fixed bug in index join rule (no index join if inner clause has positional var).
16 * Fixed bug in index join rule (copy var ids after cloning index domain expr).
17+ * Fixed bug #1123162 (FOTS: formatting dates and times failures)
18 * Added missing wrapper expressions around some variable references.
19 * Fixed bug in the throwing of error XQTY0086 during node construction.
20 * Fixed bug #1148335 (where-clause expression was not always reset when it should be)
21
22=== modified file 'include/zorba/dynamic_context.h'
23--- include/zorba/dynamic_context.h 2013-03-08 04:26:02 +0000
24+++ include/zorba/dynamic_context.h 2013-03-21 16:00:34 +0000
25@@ -22,6 +22,7 @@
26
27 #include <zorba/config.h>
28 #include <zorba/locale.h>
29+#include <zorba/time.h>
30 #include <zorba/api_shared_types.h>
31 #include <zorba/static_context_consts.h>
32 #include <zorba/xmldatamanager.h>
33@@ -268,6 +269,20 @@
34 getLocale( locale::iso639_1::type *aLang,
35 locale::iso3166_1::type *aCountry ) const = 0;
36
37+ /** \brief Sets the calendar.
38+ *
39+ * @param aCalendar The calendar to use.
40+ */
41+ virtual void
42+ setCalendar( time::calendar::type aCalendar ) = 0;
43+
44+ /** \brief Gets the current calendar.
45+ *
46+ * @return the current calendar.
47+ */
48+ virtual time::calendar::type
49+ getCalendar() const = 0;
50+
51 /** \brief Add a name-value pair to this context.
52 * The value can be accessed in the evaluate method
53 * of external functions (see ContextualExternalFunction).
54
55=== modified file 'include/zorba/locale.h'
56--- include/zorba/locale.h 2013-03-08 04:26:02 +0000
57+++ include/zorba/locale.h 2013-03-21 16:00:34 +0000
58@@ -263,7 +263,7 @@
59 BZ, ///< Belize
60 CA, ///< Canada
61 CC, ///< Cocos Islands
62- CD, ///< Congo
63+ CD, ///< Congo, the Democratic Republic of the
64 CF, ///< Central African Republic
65 CG, ///< Congo
66 CH, ///< Switzerland
67
68=== modified file 'include/zorba/pregenerated/diagnostic_list.h'
69--- include/zorba/pregenerated/diagnostic_list.h 2013-03-06 10:37:33 +0000
70+++ include/zorba/pregenerated/diagnostic_list.h 2013-03-21 16:00:34 +0000
71@@ -192,9 +192,9 @@
72
73 extern ZORBA_DLL_PUBLIC XQueryErrorCode XTDE1310;
74
75-extern ZORBA_DLL_PUBLIC XQueryErrorCode XTDE1340;
76+extern ZORBA_DLL_PUBLIC XQueryErrorCode FOFD1340;
77
78-extern ZORBA_DLL_PUBLIC XQueryErrorCode XTDE1350;
79+extern ZORBA_DLL_PUBLIC XQueryErrorCode FOFD1350;
80
81 #if !defined(ZORBA_NO_FULL_TEXT)
82 extern ZORBA_DLL_PUBLIC XQueryErrorCode FTST0008;
83
84=== added file 'include/zorba/time.h'
85--- include/zorba/time.h 1970-01-01 00:00:00 +0000
86+++ include/zorba/time.h 2013-03-21 16:00:34 +0000
87@@ -0,0 +1,68 @@
88+/*
89+ * Copyright 2006-2008 The FLWOR Foundation.
90+ *
91+ * Licensed under the Apache License, Version 2.0 (the "License");
92+ * you may not use this file except in compliance with the License.
93+ * You may obtain a copy of the License at
94+ *
95+ * http://www.apache.org/licenses/LICENSE-2.0
96+ *
97+ * Unless required by applicable law or agreed to in writing, software
98+ * distributed under the License is distributed on an "AS IS" BASIS,
99+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
100+ * See the License for the specific language governing permissions and
101+ * limitations under the License.
102+ */
103+
104+#ifndef ZORBA_TIME_API_H
105+#define ZORBA_TIME_API_H
106+
107+namespace zorba {
108+namespace time {
109+
110+///////////////////////////////////////////////////////////////////////////////
111+
112+/**
113+ * XQuery 3.0 F&O: 9.8.4.3: The calendars listed below were known to be in use
114+ * during the last hundred years.
115+ */
116+namespace calendar {
117+ enum type {
118+ unknown,
119+ AD, ///< Anno Domini (Christian Era)
120+ AH, ///< Anno Hegirae (Muhammedan Era)
121+ AM, ///< Anno Mundi (Jewish Calendar)
122+ AME, ///< Mauludi Era (solar years since Mohammed's birth)
123+ AP, ///< Anno Persici
124+ AS, ///< Aji Saka Era (Java)
125+ BE, ///< Buddhist Era
126+ CB, ///< Cooch Behar Era
127+ CE, ///< Common Era
128+ CL, ///< Chinese Lunar Era
129+ CS, ///< Chula Sakarat Era
130+ EE, ///< Ethiopian Era
131+ FE, ///< Fasli Era
132+ ISO, ///< ISO 8601 calendar
133+ JE, ///< Japanese Calendar
134+ KE, ///< Khalsa Era (Sikh calendar)
135+ KY, ///< Kali Yuga
136+ ME, ///< Malabar Era
137+ MS, ///< Monarchic Solar Era
138+ OS, ///< Old Style (Julian Calendar)
139+ RS, ///< Rattanakosin (Bangkok) Era
140+ SE, ///< Saka Era
141+ SH, ///< Mohammedan Solar Era (Iran)
142+ SS, ///< Saka Samvat
143+ TE, ///< Tripurabda Era
144+ VE, ///< Vikrama Era
145+ VS ///< Vikrama Samvat Era
146+ };
147+
148+} // namespace calendar
149+
150+///////////////////////////////////////////////////////////////////////////////
151+
152+} // namespace time
153+} // namespace zorba
154+#endif /* ZORBA_TIME_API_H */
155+/* vim:set et sw=2 ts=2: */
156
157=== modified file 'modules/org/expath/ns/file.xq.src/file.cpp'
158--- modules/org/expath/ns/file.xq.src/file.cpp 2013-03-06 02:54:03 +0000
159+++ modules/org/expath/ns/file.xq.src/file.cpp 2013-03-21 16:00:34 +0000
160@@ -657,7 +657,7 @@
161 int
162 LastModifiedFunction::getGmtOffset()
163 {
164- time_t t = time(0);
165+ time_t t = ::time(0);
166 struct tm* data;
167 data = localtime(&t);
168 data->tm_isdst = 0;
169
170=== modified file 'modules/w3c/pregenerated/xqt-errors.xq'
171--- modules/w3c/pregenerated/xqt-errors.xq 2013-03-06 10:37:33 +0000
172+++ modules/w3c/pregenerated/xqt-errors.xq 2013-03-21 16:00:34 +0000
173@@ -861,17 +861,17 @@
174 :
175 : @see http://www.w3.org/2005/xqt-errors
176 :)
177-declare variable $err:XTDE1340 as xs:QName := fn:QName($err:NS, "err:XTDE1340");
178+declare variable $err:FOFD1340 as xs:QName := fn:QName($err:NS, "err:FOFD1340");
179
180 (:~
181 :
182- : It is a non-recoverable dynamic error if a component specifier within the
183- : picture refers to components that are not available in the given type of
184- : \c $value.
185+ : It is a non-recoverable dynamic error if a component specifier within
186+ : the picture refers to components that are not available in the given
187+ : type of $value.
188 :
189 : @see http://www.w3.org/2005/xqt-errors
190 :)
191-declare variable $err:XTDE1350 as xs:QName := fn:QName($err:NS, "err:XTDE1350");
192+declare variable $err:FOFD1350 as xs:QName := fn:QName($err:NS, "err:FOFD1350");
193
194 (:~
195 :
196
197=== modified file 'modules/xqxq/xqxq.xq.src/xqxq.cpp'
198--- modules/xqxq/xqxq.xq.src/xqxq.cpp 2013-02-22 17:09:54 +0000
199+++ modules/xqxq/xqxq.xq.src/xqxq.cpp 2013-03-21 16:00:34 +0000
200@@ -238,7 +238,7 @@
201 :
202 theModule(aModule)
203 {
204- srand(time(NULL));
205+ srand(::time(NULL));
206 }
207
208
209
210=== modified file 'src/api/dynamiccontextimpl.cpp'
211--- src/api/dynamiccontextimpl.cpp 2013-03-08 04:26:02 +0000
212+++ src/api/dynamiccontextimpl.cpp 2013-03-21 16:00:34 +0000
213@@ -691,6 +691,17 @@
214 /****************************************************************************//**
215
216 ********************************************************************************/
217+void DynamicContextImpl::setCalendar( time::calendar::type aCalendar ) {
218+ theCtx->set_calendar( aCalendar );
219+}
220+
221+time::calendar::type DynamicContextImpl::getCalendar() const {
222+ return theCtx->get_calendar();
223+}
224+
225+/****************************************************************************//**
226+
227+********************************************************************************/
228 bool DynamicContextImpl::addExternalFunctionParam(
229 const String& aName,
230 void* aValue)
231
232=== modified file 'src/api/dynamiccontextimpl.h'
233--- src/api/dynamiccontextimpl.h 2013-03-08 04:26:02 +0000
234+++ src/api/dynamiccontextimpl.h 2013-03-21 16:00:34 +0000
235@@ -151,6 +151,12 @@
236 getLocale( locale::iso639_1::type *aLang,
237 locale::iso3166_1::type *aCountry ) const;
238
239+ virtual void
240+ setCalendar( time::calendar::type aCalendar );
241+
242+ virtual time::calendar::type
243+ getCalendar() const;
244+
245 virtual bool
246 addExternalFunctionParam(const String& aName, void* aValue);
247
248
249=== modified file 'src/context/dynamic_context.cpp'
250--- src/context/dynamic_context.cpp 2013-03-12 17:03:31 +0000
251+++ src/context/dynamic_context.cpp 2013-03-21 16:00:34 +0000
252@@ -137,6 +137,7 @@
253 reset_current_date_time();
254 theLang = locale::get_host_lang();
255 theCountry = locale::get_host_country();
256+ theCalendar = time::calendar::get_default();
257 }
258 else
259 {
260@@ -145,6 +146,7 @@
261 theDefaultCollectionUri = parent->theDefaultCollectionUri;
262 theLang = parent->theLang;
263 theCountry = parent->theCountry;
264+ theCalendar = parent->theCalendar;
265 }
266 }
267
268
269=== modified file 'src/context/dynamic_context.h'
270--- src/context/dynamic_context.h 2013-03-12 17:03:31 +0000
271+++ src/context/dynamic_context.h 2013-03-21 16:00:34 +0000
272@@ -18,6 +18,7 @@
273 #define ZORBA_DYNAMIC_CONTEXT_H
274
275 #include <zorba/external_function_parameter.h>
276+#include <zorba/time.h>
277
278 #include "zorbautils/hashmap_zstring.h"
279 #include "zorbautils/hashmap_itemp.h"
280@@ -141,6 +142,7 @@
281
282 locale::iso639_1::type theLang;
283 locale::iso3166_1::type theCountry;
284+ time::calendar::type theCalendar;
285
286 public:
287 double theDocLoadingUserTime;
288@@ -189,6 +191,14 @@
289 *country = theCountry;
290 }
291
292+ void set_calendar( time::calendar::type calendar ) {
293+ theCalendar = calendar;
294+ }
295+
296+ time::calendar::type get_calendar() const {
297+ return theCalendar;
298+ }
299+
300 const std::vector<VarValue>& get_variables() const { return theVarValues; }
301
302 void add_variable(ulong varid, store::Item_t& value);
303
304=== modified file 'src/diagnostics/diagnostic_en.xml'
305--- src/diagnostics/diagnostic_en.xml 2013-03-16 20:44:27 +0000
306+++ src/diagnostics/diagnostic_en.xml 2013-03-21 16:00:34 +0000
307@@ -1012,21 +1012,51 @@
308 <value>"$1": picture string does not satisfy format-number() function rules</value>
309 </diagnostic>
310
311- <diagnostic code="XTDE1340">
312+ <diagnostic code="FOFD1340">
313 <comment>
314- It is a non-recoverable dynamic error if the syntax of the picture is
315- incorrect.
316+ It is a non-recoverable dynamic error if the syntax of the picture is
317+ incorrect.
318 </comment>
319- <value>"$1": invalid picture string for date/time</value>
320+ <value>"$1": invalid picture string for date/time${: 2}</value>
321+ <entry key="BadComponent_3">
322+ <value>'$3': invalid component specifier</value>
323+ </entry>
324+ <entry key="BadWidthModifier">
325+ <value>invalid width modifier</value>
326+ </entry>
327+ <entry key="DigitNotSameFamily_34">
328+ <value>"$3": digit not from same digit family as $4</value>
329+ </entry>
330+ <entry key="MultipleComponent_3">
331+ <value>'$3': multiple component specifiers between []</value>
332+ </entry>
333+ <entry key="MustBeOneMandatoryDigit">
334+ <value>there must be at least one mandatory-digit-sign</value>
335+ </entry>
336+ <entry key="NoComponent">
337+ <value>component specifier expected between []</value>
338+ </entry>
339+ <entry key="NoAdjacentGroupSep_3">
340+ <value>"$3": grouping separator must not be adjacent to others</value>
341+ </entry>
342+ <entry key="NoGroupSepAtStart_3">
343+ <value>"$3": grouping separator illegal at start of decimal-digit-pattern</value>
344+ </entry>
345+ <entry key="NoGroupSepAtEnd_3">
346+ <value>"$3": grouping separator illegal at end of decimal-digit-pattern</value>
347+ </entry>
348+ <entry key="NoOptDigitAfterMandatory">
349+ <value>"#": optional-digit-sign must precede all mandatory-digit-signs</value>
350+ </entry>
351 </diagnostic>
352
353- <diagnostic code="XTDE1350">
354+ <diagnostic code="FOFD1350">
355 <comment>
356- It is a non-recoverable dynamic error if a component specifier within the
357- picture refers to components that are not available in the given type of
358- \c $value.
359+ It is a non-recoverable dynamic error if a component specifier within
360+ the picture refers to components that are not available in the given
361+ type of $value.
362 </comment>
363- <value>component specifier not available</value>
364+ <value>"$1": component specifier not available</value>
365 </diagnostic>
366
367 <!--////////// XQuery Full-Text Errors /////////////////////////////////-->
368
369=== modified file 'src/diagnostics/pregenerated/diagnostic_list.cpp'
370--- src/diagnostics/pregenerated/diagnostic_list.cpp 2013-03-06 10:37:33 +0000
371+++ src/diagnostics/pregenerated/diagnostic_list.cpp 2013-03-21 16:00:34 +0000
372@@ -271,10 +271,10 @@
373 XQueryErrorCode XTDE1310( "XTDE1310" );
374
375
376-XQueryErrorCode XTDE1340( "XTDE1340" );
377-
378-
379-XQueryErrorCode XTDE1350( "XTDE1350" );
380+XQueryErrorCode FOFD1340( "FOFD1340" );
381+
382+
383+XQueryErrorCode FOFD1350( "FOFD1350" );
384
385
386 #if !defined(ZORBA_NO_FULL_TEXT)
387
388=== modified file 'src/diagnostics/pregenerated/dict_en.cpp'
389--- src/diagnostics/pregenerated/dict_en.cpp 2013-03-16 20:44:27 +0000
390+++ src/diagnostics/pregenerated/dict_en.cpp 2013-03-21 16:00:34 +0000
391@@ -53,6 +53,8 @@
392 { "FODT0002", "overflow/underflow in duration operation" },
393 { "FODT0003", "\"$1\": invalid timezone value (in seconds)" },
394 { "FOER0000", "unidentifier error" },
395+ { "FOFD1340", "\"$1\": invalid picture string for date/time${: 2}" },
396+ { "FOFD1350", "\"$1\": component specifier not available" },
397 { "FOFI0001", "\"$1\": not castable to xs:language" },
398 { "FOFI0002", "invalid argument in format-integer: $1" },
399 { "FONS0004", "\"$1\": no namespace found for prefix" },
400@@ -270,8 +272,6 @@
401 { "XSST0009", "\"break loop\" statement not inside while statement" },
402 { "XSST0010", "\"continue loop\" statement not inside while statement" },
403 { "XTDE1310", "\"$1\": picture string does not satisfy format-number() function rules" },
404- { "XTDE1340", "\"$1\": invalid picture string for date/time" },
405- { "XTDE1350", "component specifier not available" },
406 { "XUDY0009", "node has no parent in \"replace\" expression (without \"value of\")" },
407 { "XUDY0014", "\"modify\" can not modify node not created by \"copy\"" },
408 { "XUDY0015", "node is target of multiple \"rename\" expressions in same query" },
409@@ -613,6 +613,16 @@
410 { "~FOCA0002_BadLexicalQName_2", "\"$2\": value is not a valid lexical QName" },
411 { "~FOCA0002_NoCastTo_234", "\"$2\": value of type $3 is not castable to type $4" },
412 { "~FOCA0002_NoURIforPrefix_2", "no namespace URI provided for prefix in lexical QName \"$2\"" },
413+ { "~FOFD1340_BadComponent_3", "'$3': invalid component specifier" },
414+ { "~FOFD1340_BadWidthModifier", "invalid width modifier" },
415+ { "~FOFD1340_DigitNotSameFamily_34", "\"$3\": digit not from same digit family as $4" },
416+ { "~FOFD1340_MultipleComponent_3", "'$3': multiple component specifiers between []" },
417+ { "~FOFD1340_MustBeOneMandatoryDigit", "there must be at least one mandatory-digit-sign" },
418+ { "~FOFD1340_NoAdjacentGroupSep_3", "\"$3\": grouping separator must not be adjacent to others" },
419+ { "~FOFD1340_NoComponent", "component specifier expected between []" },
420+ { "~FOFD1340_NoGroupSepAtEnd_3", "\"$3\": grouping separator illegal at end of decimal-digit-pattern" },
421+ { "~FOFD1340_NoGroupSepAtStart_3", "\"$3\": grouping separator illegal at start of decimal-digit-pattern" },
422+ { "~FOFD1340_NoOptDigitAfterMandatory", "\"#\": optional-digit-sign must precede all mandatory-digit-signs" },
423 { "~FORG0001_BadHexDigit_2", "'$2': invalid hexedecimal digit" },
424 { "~FORG0001_Base64BadChar_2", "'$2': invalid Base64 character" },
425 { "~FORG0001_Base64Multiple4", "Base64 data must be a multiple of 4 bytes" },
426
427=== modified file 'src/diagnostics/pregenerated/dict_zed_keys.h'
428--- src/diagnostics/pregenerated/dict_zed_keys.h 2013-03-16 20:44:27 +0000
429+++ src/diagnostics/pregenerated/dict_zed_keys.h 2013-03-21 16:00:34 +0000
430@@ -63,6 +63,16 @@
431 #define ZED_XQDY0074_NotCastToQName "~XQDY0074_NotCastToQName"
432 #define ZED_XQDY0074_NoEmptyLocalname "~XQDY0074_NoEmptyLocalname"
433 #define ZED_XQDY0074_NameSapceConstructor "~XQDY0074_NameSapceConstructor"
434+#define ZED_FOFD1340_BadComponent_3 "~FOFD1340_BadComponent_3"
435+#define ZED_FOFD1340_BadWidthModifier "~FOFD1340_BadWidthModifier"
436+#define ZED_FOFD1340_DigitNotSameFamily_34 "~FOFD1340_DigitNotSameFamily_34"
437+#define ZED_FOFD1340_MultipleComponent_3 "~FOFD1340_MultipleComponent_3"
438+#define ZED_FOFD1340_MustBeOneMandatoryDigit "~FOFD1340_MustBeOneMandatoryDigit"
439+#define ZED_FOFD1340_NoComponent "~FOFD1340_NoComponent"
440+#define ZED_FOFD1340_NoAdjacentGroupSep_3 "~FOFD1340_NoAdjacentGroupSep_3"
441+#define ZED_FOFD1340_NoGroupSepAtStart_3 "~FOFD1340_NoGroupSepAtStart_3"
442+#define ZED_FOFD1340_NoGroupSepAtEnd_3 "~FOFD1340_NoGroupSepAtEnd_3"
443+#define ZED_FOFD1340_NoOptDigitAfterMandatory "~FOFD1340_NoOptDigitAfterMandatory"
444 #define ZED_FTST0009_BadStopWordsLang "~FTST0009_BadStopWordsLang"
445 #define ZED_FTST0009_BadStemmerLang "~FTST0009_BadStemmerLang"
446 #define ZED_FTST0009_BadThesaurusLang "~FTST0009_BadThesaurusLang"
447
448=== modified file 'src/functions/func_durations_dates_times_impl.cpp'
449--- src/functions/func_durations_dates_times_impl.cpp 2013-02-07 17:24:36 +0000
450+++ src/functions/func_durations_dates_times_impl.cpp 2013-03-21 16:00:34 +0000
451@@ -19,6 +19,7 @@
452 #include "functions/function_impl.h"
453
454 #include "runtime/durations_dates_times/DurationsDatesTimesImpl.h"
455+#include "runtime/durations_dates_times/format_dateTime.h"
456 #include "runtime/numerics/NumericsImpl.h"
457 #include "runtime/core/arithmetic_impl.h"
458 #include "zorbamisc/ns_consts.h"
459
460=== modified file 'src/runtime/CMakeLists.txt'
461--- src/runtime/CMakeLists.txt 2013-02-07 17:24:36 +0000
462+++ src/runtime/CMakeLists.txt 2013-03-21 16:00:34 +0000
463@@ -125,6 +125,7 @@
464 core/gflwor/outerfor_iterator.cpp
465 core/internal_operators.cpp
466 durations_dates_times/DurationsDatesTimesImpl.cpp
467+ durations_dates_times/format_dateTime.cpp
468 indexing/doc_indexer.cpp
469 indexing/index_ddl.cpp
470 json/common.cpp
471
472=== modified file 'src/runtime/durations_dates_times/DurationsDatesTimesImpl.cpp'
473--- src/runtime/durations_dates_times/DurationsDatesTimesImpl.cpp 2013-02-28 11:15:32 +0000
474+++ src/runtime/durations_dates_times/DurationsDatesTimesImpl.cpp 2013-03-21 16:00:34 +0000
475@@ -45,8 +45,6 @@
476 {
477 SERIALIZABLE_CLASS_VERSIONS(FnDateTimeConstructorIterator)
478
479-SERIALIZABLE_CLASS_VERSIONS(FnFormatDateTimeIterator)
480-
481 SERIALIZABLE_CLASS_VERSIONS(FnAdjustToTimeZoneIterator_1)
482
483 SERIALIZABLE_CLASS_VERSIONS(FnAdjustToTimeZoneIterator_2)
484@@ -54,19 +52,11 @@
485
486 BINARY_ACCEPT(FnDateTimeConstructorIterator);
487
488-NARY_ACCEPT(FnFormatDateTimeIterator);
489-
490 UNARY_ACCEPT(FnAdjustToTimeZoneIterator_1);
491
492 BINARY_ACCEPT(FnAdjustToTimeZoneIterator_2);
493
494
495-static void skip_whitespace(zstring& str, ascii::size_type& position, int delta = 0)
496-{
497- while (position+delta < str.size() && ascii::is_space(str[position+delta]))
498- position++;
499-}
500-
501 bool FnDateTimeConstructorIterator::nextImpl(store::Item_t& result, PlanState& planState) const
502 {
503 store::Item_t item0;
504@@ -199,555 +189,5 @@
505 STACK_END(state);
506 }
507
508-
509-/**
510- *______________________________________________________________________
511- *
512- * fn:format-dateTime()
513- *
514- *_______________________________________________________________________*/
515-
516-class Modifier
517-{
518-public:
519- zstring presentation_modifier;
520- zstring second_modifier;
521-
522- // for min_width and max_width
523- // -3 means an error in the picture
524- // -2 means width modifiers are not specified
525- // -1 means '*'
526- // >=0 means explicitly specified width
527- long min_width_modifier;
528- long max_width_modifier;
529-
530- Modifier()
531- :
532- presentation_modifier(""),
533- second_modifier(""),
534- min_width_modifier(-2),
535- max_width_modifier(-2)
536- {
537- };
538-};
539-
540-
541-static void format_number(zstring& str, long number, Modifier& modifier)
542-{
543- // Presentation modifier can be:
544- // 'Ww', "Nn', 'W', 'w', 'N', 'n'
545- // 'i', 'I', '1', '00...01'
546- // the modifier will not be checked if it is supported or not
547- zstring temp;
548-
549- if (modifier.presentation_modifier.size() > 0 && modifier.presentation_modifier[0] == '0')
550- {
551- ztd::to_string(number, &temp);
552- while (temp.size() < modifier.presentation_modifier.size())
553- temp = "0" + temp;
554- }
555- else // "1" or fallback
556- {
557- ztd::to_string(number, &temp);
558- }
559-
560- if (modifier.second_modifier == "o")
561- {
562- if ((number % 10) == 1 && (number % 100) != 11)
563- temp.append("st");
564- else if ((number % 10) == 2 && (number % 100) != 12)
565- temp.append("nd");
566- else if ((number % 10) == 3 && (number % 100) != 13)
567- temp.append("rd");
568- else
569- temp.append("th");
570- }
571-
572- if (modifier.min_width_modifier >= 0)
573- while (temp.size() < (unsigned int)modifier.min_width_modifier)
574- temp = "0" + temp;
575-
576- str.append(temp.c_str());
577-}
578-
579-
580-static void format_string_width(
581- zstring& destination,
582- zstring& source,
583- Modifier& modifier)
584-{
585- zstring temp = source;
586- while (modifier.max_width_modifier > 0 && temp.size() < (unsigned int)modifier.max_width_modifier)
587- temp.append(" ");
588- destination.append(temp.c_str());
589-}
590-
591-
592-static bool format_string(
593- zstring& destination,
594- zstring& source,
595- Modifier& modifier)
596-{
597- zstring temp;
598- if (modifier.presentation_modifier == "n")
599- {
600- zstring newcase = source;
601- ascii::to_lower(newcase);
602- temp.append(newcase);
603- }
604- else if (modifier.presentation_modifier == "N")
605- {
606- zstring newcase = source;
607- ascii::to_upper(newcase);
608- temp.append(newcase);
609- }
610- else if (modifier.presentation_modifier == "Nn")
611- {
612- zstring newcase;
613-
614- newcase = source.substr(0, 1);
615- ascii::to_upper(newcase);
616- temp.append(newcase);
617-
618- newcase = source.substr(1,source.size()-1);
619- ascii::to_lower(newcase);
620- temp.append(newcase);
621- }
622- else
623- return false;
624-
625- format_string_width(destination, temp, modifier);
626- return true;
627-}
628-
629-
630-static bool format_string(
631- zstring& destination,
632- const char* source,
633- Modifier& modifier)
634-{
635- zstring temp(source);
636- return format_string(destination, temp, modifier);
637-}
638-
639-
640-static void format_component(
641- zstring& destination,
642- long number,
643- zstring& source,
644- Modifier& modifier)
645-{
646- if (!format_string(destination, source, modifier))
647- format_number(destination, number, modifier);
648-}
649-
650-
651-static void output_year(
652- zstring& destination,
653- long number,
654- Modifier& modifier)
655-{
656- format_number(destination, number, modifier);
657-
658- if (modifier.max_width_modifier >= 0)
659- {
660- if ((unsigned int)modifier.max_width_modifier > destination.size())
661- modifier.max_width_modifier = destination.size();
662-
663- destination = destination.substr(destination.size() - modifier.max_width_modifier, modifier.max_width_modifier);
664- }
665-}
666-
667-
668-static void output_month(
669- zstring& destination,
670- long number,
671- Modifier& modifier)
672-{
673- static const char* month[12] = { "january", "february", "march", "april", "may", "june", "july", "august", "september", "october", "november", "december"};
674- zstring temp(month[number-1]);
675- if (modifier.max_width_modifier > 0 && (unsigned int)modifier.max_width_modifier < temp.size())
676- temp = temp.substr(0, modifier.max_width_modifier);
677-
678- format_component(destination, number, temp, modifier);
679-}
680-
681-
682-static void output_day_of_week(
683- zstring& destination,
684- long number,
685- Modifier& modifier)
686-{
687- static const char* day[7] = { "sunday", "monday", "tuesday", "wednesday", "thursday", "friday", "saturday"};
688- zstring temp(day[number]);
689- if (modifier.max_width_modifier > 0 && (unsigned int)modifier.max_width_modifier < temp.size())
690- temp = temp.substr(0, modifier.max_width_modifier);
691-
692- if (modifier.presentation_modifier.size() == 0)
693- modifier.presentation_modifier = "n"; // Default for day of week is "n"
694-
695- format_component(destination, number, temp, modifier);
696-}
697-
698-
699-static void parse_presentation_modifier(
700- zstring& str,
701- ascii::size_type& position,
702- zstring& result)
703-{
704- result = "";
705-
706- skip_whitespace(str, position, 1);
707-
708- if (position+1 >= str.size())
709- return;
710-
711- zstring modifier = "";
712-
713- if (str[position+1] == '1' || str[position+1] == 'i' || str[position+1] == 'I'
714- || str[position+1] == 'a' || str[position+1] == 'A'
715- || str[position+1] == 'w' || str[position+1] == 'W'
716- || str[position+1] == 'n' || str[position+1] == 'N' )
717- {
718- modifier.append(str, position+1, 1);
719- position++;
720-
721- skip_whitespace(str, position, 1);
722-
723- if (position+1 < str.size() &&
724- ((modifier[0] == 'W' && str[position+1] == 'w')
725- ||
726- (modifier[0] == 'N' && str[position+1] == 'n')))
727- {
728- modifier.append(str, position+1, 1);
729- position++;
730- }
731- }
732- else if (str[position+1] == '0')
733- {
734- ascii::size_type start = position;
735- while (position+1 < str.size() && (str[position+1] == '0' || ascii::is_space(str[position+1])))
736- {
737- if (str[position+1] == '0')
738- modifier.append(str, position+1, 1);
739- position++;
740- }
741-
742- if (position+1 >= str.size() || str[position+1] != '1')
743- {
744- position = start;
745- return;
746- }
747-
748- modifier.append(str, position+1, 1);
749- position++;
750- }
751-
752- result = modifier;
753-}
754-
755-
756-static void parse_second_modifier(
757- zstring& str,
758- ascii::size_type& position,
759- zstring& result)
760-{
761- result = "";
762-
763- skip_whitespace(str, position, 1);
764-
765- if (position+1 >= str.size())
766- return;
767-
768- position++;
769- if (str[position] == 't')
770- result = "t";
771- else if (str[position] == 'o')
772- result = "o";
773- else
774- position--;
775-}
776-
777-
778-// for min_width and max_width
779-// -3 means an error in the picture
780-// -2 means width modifiers are not specified
781-// -1 means '*'
782-// >=0 means explicitly specified width
783-static void parse_width_modifier(
784- zstring& str,
785- ascii::size_type& position,
786- long& min_width,
787- long& max_width)
788-{
789- min_width = -2;
790- max_width = -2;
791-
792- skip_whitespace(str, position, 1);
793-
794- if (position+1 >= str.size() || str[position+1] != ',')
795- return;
796-
797- position++;
798- skip_whitespace(str, position, 1);
799-
800- // The min_width must be present if there is a comma symbol
801- min_width = -3;
802- if (position+1 >= str.size())
803- return;
804-
805- if (str[position+1] == '*')
806- {
807- min_width = -1;
808- position++;
809- }
810- else
811- {
812- if (parse_long(str.data(), str.size(), position, min_width, -1, -1, 1))
813- min_width = -3;
814- }
815-
816- skip_whitespace(str, position, 1);
817-
818- if (position+1 >= str.size() || str[position+1] != '-')
819- return;
820-
821- position++;
822- skip_whitespace(str, position, 1);
823-
824- if (position+1 < str.size() && str[position+1] == '*')
825- {
826- max_width = -1;
827- position++;
828- }
829- else
830- {
831- if (parse_long(str.data(), str.size(), position, max_width, -1, -1, 1))
832- min_width = -3;
833- }
834-}
835-
836-
837-static int get_data_type(char component)
838-{
839- switch (component)
840- {
841- case 'Y':
842- return DateTime::YEAR_DATA;
843- case 'M':
844- return DateTime::MONTH_DATA;
845- case 'D':
846- return DateTime::DAY_DATA;
847- case 'd': // day in year
848- return DateTime::DAY_DATA;
849- case 'F': // day of week
850- return DateTime::DAY_DATA;
851- case 'W': // week in year
852- return DateTime::DAY_DATA;
853- case 'w': // week in month
854- return DateTime::DAY_DATA;
855- case 'H': // hour in day (24 hours)
856- return DateTime::HOUR_DATA;
857- case 'h': // hour in half-day (12 hours)
858- return DateTime::HOUR_DATA;
859- case 'P': // am/pm marker
860- return DateTime::HOUR_DATA;
861- case 'm':
862- return DateTime::MINUTE_DATA;
863- case 's':
864- return DateTime::SECONDS_DATA;
865- case 'f': // fractional seconds
866- return DateTime::FRACSECONDS_DATA;
867- 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)
868- return -1;
869- case 'z': // timezone as a time offset using GMT, for example GMT+1
870- return -1;
871- case 'C': // calendar: the name or abbreviation of a calendar name
872- return -1;
873- case 'E': // era: the name of a baseline for the numbering of years, for example the reign of a monarch
874- return -1;
875- default:
876- return -1;
877- }
878-}
879-
880-
881-bool FnFormatDateTimeIterator::nextImpl(
882- store::Item_t& result,
883- PlanState& planState) const
884-{
885- bool variable_marker;
886- zstring pictureString, resultString;
887- store::Item_t dateTimeItem, picture;
888- PlanIteratorState* state;
889- DEFAULT_STACK_INIT(PlanIteratorState, state, planState);
890-
891- if (!consumeNext(dateTimeItem, theChildren[0].getp(), planState))
892- {
893- // Got void -- returning void
894- STACK_PUSH(false, state);
895- }
896- else
897- {
898- consumeNext(picture, theChildren[1].getp(), planState);
899-
900- pictureString = picture->getStringValue().str();
901- resultString = "";
902- variable_marker = false;
903-
904- for (ascii::size_type i = 0; i < pictureString.size(); i++)
905- {
906- if (!variable_marker)
907- {
908- if (pictureString[i] == '[')
909- {
910- // check for quoted "[["
911- if (i<pictureString.size()-1 && pictureString[i+1] == '[')
912- i++;
913- else
914- {
915- variable_marker = true;
916- continue;
917- }
918- }
919- else if (pictureString[i] == ']')
920- {
921- // check for quoted "]]"
922- if (i<pictureString.size()-1 && pictureString[i+1] == ']')
923- i++;
924- }
925-
926- resultString.append(pictureString, i, 1);
927- }
928- else // variable_marker == true
929- {
930- char component = 0;
931- Modifier modifier;
932-
933- switch (pictureString[i])
934- {
935- case 'Y': case 'M': case 'D': case 'd': case 'F': case 'W': case 'w':
936- case 'H': case 'h': case 'P': case 'm': case 's': case 'f':
937- case 'Z': case 'z': case 'C': case 'E':
938- component = pictureString[i];
939- break;
940-
941- case ' ': case '\f': case '\n': case '\r': case '\t': case '\v':
942- continue; // ignore whitespace
943- break;
944-
945- case ']':
946- variable_marker = false;
947- break;
948-
949- default:
950- throw XQUERY_EXCEPTION(
951- err::XTDE1340, ERROR_PARAMS( pictureString ), ERROR_LOC( loc )
952- );
953- }
954-
955- if (variable_marker == false)
956- continue;
957-
958- parse_presentation_modifier(pictureString, i, modifier.presentation_modifier);
959-
960- parse_second_modifier(pictureString, i, modifier.second_modifier);
961-
962- parse_width_modifier(pictureString,
963- i,
964- modifier.min_width_modifier,
965- modifier.max_width_modifier);
966-
967- // min_width_modifier is -3, there was an error in the picture
968- if (modifier.min_width_modifier == -3)
969- throw XQUERY_EXCEPTION(
970- err::XTDE1340, ERROR_PARAMS( pictureString ), ERROR_LOC( loc )
971- );
972-
973- int data_type = get_data_type(component);
974- if (data_type != -1 && (!DateTime::FACET_MEMBERS[facet_type][data_type]))
975- throw XQUERY_EXCEPTION(err::XTDE1350, ERROR_LOC(loc));
976-
977- switch (component)
978- {
979- case 'Y':
980- output_year(resultString, std::abs(dateTimeItem->getDateTimeValue().getYear()), modifier);
981- break;
982- case 'M':
983- output_month(resultString, dateTimeItem->getDateTimeValue().getMonth(), modifier);
984- break;
985- case 'D':
986- format_number(resultString, dateTimeItem->getDateTimeValue().getDay(), modifier);
987- break;
988- case 'd': // day in year
989- format_number(resultString, dateTimeItem->getDateTimeValue().getDayOfYear(), modifier);
990- break;
991- case 'F': // day of week
992- output_day_of_week(resultString, dateTimeItem->getDateTimeValue().getDayOfWeek(), modifier);
993- break;
994- case 'W': // week in year
995- format_number(resultString, dateTimeItem->getDateTimeValue().getWeekInYear(), modifier);
996- break;
997- case 'w': // week in month
998- format_number(resultString, dateTimeItem->getDateTimeValue().getWeekInMonth(), modifier);
999- break;
1000- case 'H': // hour in day (24 hours)
1001- format_number(resultString, dateTimeItem->getDateTimeValue().getHours(), modifier);
1002- break;
1003- case 'h': // hour in half-day (12 hours)
1004- // Convert hour from: 0 1 ... 12 13 ... 23 0
1005- // to: 12 1 ... 12 1 ... 11 12
1006- format_number(resultString, 1 + (11 + dateTimeItem->getDateTimeValue().getHours()) % 12,
1007- modifier);
1008- break;
1009- case 'P': // am/pm marker
1010- if (modifier.presentation_modifier.empty())
1011- modifier.presentation_modifier = "n"; // Default for the AM/PM marker is "n"
1012- format_string(resultString, dateTimeItem->getDateTimeValue().getHours() >= 12 ? "pm" : "am", modifier);
1013- break;
1014- case 'm':
1015- if (modifier.presentation_modifier.empty())
1016- modifier.presentation_modifier.append("01");
1017- format_number(resultString, dateTimeItem->getDateTimeValue().getMinutes(), modifier);
1018- break;
1019- case 's':
1020- if (modifier.presentation_modifier.empty())
1021- modifier.presentation_modifier.append("01");
1022- format_number(resultString, dateTimeItem->getDateTimeValue().getIntSeconds(), modifier);
1023- break;
1024- case 'f': // fractional seconds
1025- format_number(resultString, (long)(dateTimeItem->getDateTimeValue().getFractionalSeconds()*1000.0/DateTime::FRAC_SECONDS_UPPER_LIMIT),
1026- modifier);
1027- break;
1028- 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)
1029- // deliberate fall-through
1030- case 'z': // timezone as a time offset using GMT, for example GMT+1
1031- {
1032- zstring temp = "gmt";
1033- temp += dateTimeItem->getDateTimeValue().getTimezone().toString();
1034- format_string(resultString, temp.c_str(), modifier);
1035- }
1036- break;
1037- case 'C': // calendar: the name or abbreviation of a calendar name
1038- if (modifier.presentation_modifier.empty())
1039- modifier.presentation_modifier.append("n");
1040- format_string(resultString, "gregorian", modifier);
1041- break;
1042- case 'E': // era: the name of a baseline for the numbering of years, for example the reign of a monarch
1043- if (modifier.presentation_modifier.empty())
1044- modifier.presentation_modifier.append("n");
1045- format_string(resultString, dateTimeItem->getDateTimeValue().getYear() < 0 ? "ad" : "bc", modifier);
1046- break;
1047- } // switch
1048- } // if (!variable_marker)
1049-
1050- } // for
1051-
1052- STACK_PUSH(GENV_ITEMFACTORY->createString(result, resultString), state);
1053- }
1054-
1055- STACK_END (state);
1056-}
1057-
1058 } // namespace zorba
1059 /* vim:set et sw=2 ts=2: */
1060
1061=== modified file 'src/runtime/durations_dates_times/DurationsDatesTimesImpl.h'
1062--- src/runtime/durations_dates_times/DurationsDatesTimesImpl.h 2013-02-07 17:24:36 +0000
1063+++ src/runtime/durations_dates_times/DurationsDatesTimesImpl.h 2013-03-21 16:00:34 +0000
1064@@ -24,53 +24,12 @@
1065 #include "runtime/base/unarybase.h"
1066 #include "runtime/base/narybase.h"
1067
1068+namespace zorba {
1069
1070-namespace zorba
1071-{
1072+///////////////////////////////////////////////////////////////////////////////
1073
1074 BINARY_ITER(FnDateTimeConstructorIterator);
1075
1076-
1077-// XQuery 3.0 DateTime formatting
1078-class FnFormatDateTimeIterator : public NaryBaseIterator<FnFormatDateTimeIterator,
1079- PlanIteratorState >
1080-{
1081-private:
1082- DateTime::FACET_TYPE facet_type;
1083-
1084-public:
1085- SERIALIZABLE_CLASS(FnFormatDateTimeIterator);
1086-
1087- SERIALIZABLE_CLASS_CONSTRUCTOR2T(
1088- FnFormatDateTimeIterator,
1089- NaryBaseIterator<FnFormatDateTimeIterator, PlanIteratorState >);
1090-
1091- void serialize(::zorba::serialization::Archiver &ar)
1092- {
1093- serialize_baseclass(ar,
1094- (NaryBaseIterator<FnFormatDateTimeIterator, PlanIteratorState >*)this);
1095-
1096- SERIALIZE_ENUM(DateTime::FACET_TYPE, facet_type);
1097- }
1098-
1099-public:
1100- FnFormatDateTimeIterator(
1101- static_context* sctx,
1102- const QueryLoc& loc,
1103- std::vector<PlanIter_t>& aChildren,
1104- DateTime::FACET_TYPE a_facet_type = DateTime::DATETIME_FACET)
1105- :
1106- NaryBaseIterator<FnFormatDateTimeIterator, PlanIteratorState>(sctx, loc, aChildren),
1107- facet_type(a_facet_type)
1108- {
1109- }
1110-
1111- void accept(PlanIterVisitor& v) const;
1112-
1113- bool nextImpl(store::Item_t& result, PlanState& aPlanState) const;
1114-};
1115-
1116-
1117 /*
1118 10.7 Timezone Adjustment Functions on Dates and Time Values
1119 */
1120@@ -88,14 +47,14 @@
1121 */
1122 BINARY_ITER(FnAdjustToTimeZoneIterator_2);
1123
1124+///////////////////////////////////////////////////////////////////////////////
1125+
1126 } // namespace zorba
1127
1128-#endif
1129-
1130+#endif /* ZORBA_RUNTIME_DURATIONSDATESTIMES */
1131 /*
1132 * Local variables:
1133 * mode: c++
1134 * End:
1135 */
1136-
1137 /* vim:set et sw=2 ts=2: */
1138
1139=== added file 'src/runtime/durations_dates_times/format_dateTime.cpp'
1140--- src/runtime/durations_dates_times/format_dateTime.cpp 1970-01-01 00:00:00 +0000
1141+++ src/runtime/durations_dates_times/format_dateTime.cpp 2013-03-21 16:00:34 +0000
1142@@ -0,0 +1,1377 @@
1143+/*
1144+ * Copyright 2006-2008 The FLWOR Foundation.
1145+ *
1146+ * Licensed under the Apache License, Version 2.0 (the "License");
1147+ * you may not use this file except in compliance with the License.
1148+ * You may obtain a copy of the License at
1149+ *
1150+ * http://www.apache.org/licenses/LICENSE-2.0
1151+ *
1152+ * Unless required by applicable law or agreed to in writing, software
1153+ * distributed under the License is distributed on an "AS IS" BASIS,
1154+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1155+ * See the License for the specific language governing permissions and
1156+ * limitations under the License.
1157+ */
1158+
1159+#include "stdafx.h"
1160+
1161+// standard
1162+#include <algorithm>
1163+#include <cctype>
1164+#include <cmath>
1165+#include <cstdlib>
1166+#include <functional>
1167+#include <iomanip>
1168+#include <iostream>
1169+#include <sstream>
1170+
1171+// Zorba
1172+#include "context/dynamic_context.h"
1173+#include "context/static_context.h"
1174+#include "runtime/core/arithmetic_impl.h"
1175+#include "runtime/visitors/planiter_visitor.h"
1176+#include "store/api/item.h"
1177+#include "store/api/item_factory.h"
1178+#include "store/api/store.h"
1179+#include "system/globalenv.h"
1180+#include "util/ascii_util.h"
1181+#include "util/stream_util.h"
1182+#include "util/string_util.h"
1183+#include "util/time_util.h"
1184+#include "util/utf8_util.h"
1185+#include "zorbatypes/datetime.h"
1186+#include "zorbatypes/datetime/parse.h"
1187+#include "zorbatypes/duration.h"
1188+#include "zorbatypes/zstring.h"
1189+#include "zorbautils/locale.h"
1190+
1191+// local
1192+#include "format_dateTime.h"
1193+
1194+using namespace std;
1195+using namespace zorba::locale;
1196+using namespace zorba::time;
1197+
1198+namespace zorba {
1199+
1200+SERIALIZABLE_CLASS_VERSIONS(FnFormatDateTimeIterator)
1201+NARY_ACCEPT(FnFormatDateTimeIterator);
1202+
1203+///////////////////////////////////////////////////////////////////////////////
1204+
1205+/**
1206+ * Holds presentation modifier data.
1207+ */
1208+struct modifier {
1209+ enum first_type {
1210+ arabic, // '1' : 0 1 2 ... 10 11 12 ...
1211+ alpha, // 'a' : a b c ... z aa ab ac ...
1212+ ALPHA, // 'A' : A B C ... Z AA AB AC ...
1213+ roman, // 'i' : i ii iii iv v vi vii viii ix x ...
1214+ ROMAN, // 'I' : I II III IV V VI VII VIII IX X ...
1215+ name, // 'n' : name
1216+ Name, // 'Nn': Name
1217+ NAME, // 'N' : NAME
1218+ words, // 'w' : one two three four ...
1219+ Words, // 'Ww': One Two Three Four ...
1220+ WORDS, // 'W' : ONE TWO THREE FOUR ...
1221+ military_tz // 'Z' : A B C ... J ... X Y Z
1222+ };
1223+
1224+ enum second_co_type {
1225+ no_second_co,
1226+ cardinal, // 'c': 7 or seven
1227+ ordinal // 'o': 7th or seventh
1228+ };
1229+
1230+ enum second_at_type {
1231+ no_second_at,
1232+ alphabetic, // 'a'
1233+ traditional // 't'
1234+ };
1235+
1236+ typedef unsigned width_type;
1237+
1238+ struct {
1239+ bool parsed;
1240+ first_type type;
1241+ zstring format;
1242+ bool has_grouping_separators;
1243+ unicode::code_point zero;
1244+ } first;
1245+
1246+ struct {
1247+ second_co_type co_type;
1248+ zstring co_string;
1249+ second_at_type at_type;
1250+ } second;
1251+
1252+ width_type min_width;
1253+ width_type max_width;
1254+
1255+ //
1256+ // This stuff isn't part of the "presentation modifier" as discussed in the
1257+ // XQuery3.0 F&O spec, but this is a convenient place to put it nonetheless.
1258+ //
1259+ iso639_1::type lang;
1260+ bool lang_is_fallback;
1261+ iso3166_1::type country;
1262+ calendar::type cal;
1263+ bool cal_is_fallback;
1264+
1265+ void append_if_fallback_lang( zstring *s ) const {
1266+ if ( lang_is_fallback ) {
1267+ //
1268+ // XQuery 3.0 F&O: 9.8.4.3: If the fallback representation uses a
1269+ // different language from that requested, the output string must
1270+ // identify the language actually used, for example by prefixing the
1271+ // string with [Language: Y] (where Y is the language actually used)
1272+ // localized in an implementation-dependent way.
1273+ //
1274+ ostringstream oss;
1275+ // TODO: localize "Language"
1276+ oss << "[Language: " << lang << ']';
1277+ *s += oss.str();
1278+ }
1279+ }
1280+
1281+ bool gt_max_width( width_type n ) const {
1282+ return max_width > 0 && n > max_width;
1283+ }
1284+
1285+ zstring const& left_pad_zero( zstring *s ) const {
1286+ if ( min_width )
1287+ utf8::left_pad( s, min_width, first.zero );
1288+ return *s;
1289+ }
1290+
1291+ zstring const& right_pad_space( zstring *s ) const {
1292+ if ( min_width )
1293+ utf8::right_pad( s, min_width, ' ' );
1294+ return *s;
1295+ }
1296+
1297+ void set_default_width( width_type width ) {
1298+ if ( !(first.parsed || min_width || max_width) )
1299+ min_width = max_width = width;
1300+ }
1301+
1302+ modifier() {
1303+ first.parsed = false;
1304+ first.type = arabic;
1305+ first.has_grouping_separators = false;
1306+ first.zero = '0';
1307+ second.co_type = cardinal;
1308+ second.at_type = no_second_at;
1309+ min_width = max_width = 0;
1310+ };
1311+};
1312+
1313+///////////////////////////////////////////////////////////////////////////////
1314+
1315+zstring alpha( unsigned n, bool capital ) {
1316+ zstring result;
1317+ if ( n ) {
1318+ char const c = capital ? 'A' : 'a';
1319+ while ( n ) {
1320+ unsigned const m = n - 1;
1321+ result.insert( (zstring::size_type)0, 1, c + m % 26 );
1322+ n = m / 26;
1323+ }
1324+ } else
1325+ result = "0";
1326+ return result;
1327+}
1328+
1329+///////////////////////////////////////////////////////////////////////////////
1330+
1331+namespace english_impl {
1332+
1333+// Based on code from:
1334+// http://www.cprogramming.com/challenges/integer-to-english-sol.html
1335+
1336+static string const ones[][2] = {
1337+ { "", "" },
1338+ { "one", "first" },
1339+ { "two", "second" },
1340+ { "three", "third" },
1341+ { "four", "fourth" },
1342+ { "five", "fifth" },
1343+ { "six", "sixth" },
1344+ { "seven", "seventh" },
1345+ { "eight", "eighth" },
1346+ { "nine", "ninth" },
1347+ { "ten", "tenth" },
1348+ { "eleven", "eleventh" },
1349+ { "twelve", "twelveth" },
1350+ { "thirteen", "thirteenth" },
1351+ { "fourteen", "fourteenth" },
1352+ { "fifteen", "fifteenth" },
1353+ { "sixteen", "sixteenth" },
1354+ { "seventeen", "seventeenth" },
1355+ { "eighteen", "eighteenth" },
1356+ { "nineteen", "nineteenth" }
1357+};
1358+
1359+static zstring const tens[][2] = {
1360+ { "", "" },
1361+ { "", "" },
1362+ { "twenty", "twentieth" },
1363+ { "thirty", "thirtieth" },
1364+ { "forty", "fortieth" },
1365+ { "fifty", "fiftieth" },
1366+ { "sixty", "sixtieth" },
1367+ { "seventy", "seventieth" },
1368+ { "eighty", "eighteenth" },
1369+ { "ninety", "ninetieth" }
1370+};
1371+
1372+// Enough entries to print English for 64-bit integers.
1373+static zstring const big[][2] = {
1374+ { "", "" },
1375+ { "thousand", "thousandth" },
1376+ { "million", "millionth" },
1377+ { "billion", "billionth" },
1378+ { "trillion", "trillionth" },
1379+ { "quadrillion", "quadrillionth" },
1380+ { "quintillion", "quintillionth" }
1381+};
1382+
1383+inline zstring if_space( zstring const &s ) {
1384+ return s.empty() ? "" : ' ' + s;
1385+}
1386+
1387+static zstring hundreds( int64_t n, bool ordinal ) {
1388+ if ( n < 20 )
1389+ return ones[ n ][ ordinal ];
1390+ zstring const tmp( if_space( ones[ n % 10 ][ ordinal ] ) );
1391+ return tens[ n / 10 ][ ordinal && tmp.empty() ] + tmp;
1392+}
1393+
1394+} // namespace english_impl
1395+
1396+/**
1397+ * Converts a signed integer to English, e.g, 42 becomes "forty two".
1398+ *
1399+ * @param n The integer to convert.
1400+ * @param ordinal If \c true, ordinal words ("forty second") are returned.
1401+ * @return Returns \a n in English.
1402+ */
1403+static zstring english( int64_t n, bool ordinal = false ) {
1404+ using namespace english_impl;
1405+
1406+ if ( !n )
1407+ return ordinal ? "zeroth" : "zero";
1408+
1409+ bool const negative = n < 0;
1410+ if ( negative )
1411+ n = -n;
1412+
1413+ int big_count = 0;
1414+ bool big_ordinal = ordinal;
1415+ zstring r;
1416+
1417+ while ( n ) {
1418+ if ( int64_t const m = n % 1000 ) {
1419+ zstring s;
1420+ if ( m < 100 )
1421+ s = hundreds( m, ordinal );
1422+ else {
1423+ zstring const tmp( if_space( hundreds( m % 100, ordinal ) ) );
1424+ s = ones[ m / 100 ][0] + ' '
1425+ + (ordinal && tmp.empty() ? "hundredth" : "hundred") + tmp;
1426+ }
1427+ zstring const tmp( if_space( r ) );
1428+ r = s + if_space( big[ big_count ][ big_ordinal && tmp.empty() ] + tmp );
1429+ big_ordinal = false;
1430+ }
1431+ n /= 1000;
1432+ ++big_count;
1433+ ordinal = false;
1434+ }
1435+
1436+ if ( negative )
1437+ r = "negative " + r;
1438+ return r;
1439+}
1440+
1441+///////////////////////////////////////////////////////////////////////////////
1442+
1443+static bool is_grouping_separator( unicode::code_point cp ) {
1444+ using namespace unicode;
1445+ //
1446+ // XQuery 3.0 F&O: 4.6.1: a grouping-separator-sign is a non-alphanumeric
1447+ // character, that is a character whose Unicode category is other than Nd,
1448+ // Nl, No, Lu, Ll, Lt, Lm or Lo.
1449+ //
1450+ return !( is_category( cp, Nd )
1451+ || is_category( cp, Nl )
1452+ || is_category( cp, No )
1453+ || is_category( cp, Lu )
1454+ || is_category( cp, Ll )
1455+ || is_category( cp, Lt )
1456+ || is_category( cp, Lm )
1457+ || is_category( cp, Lo )
1458+ );
1459+}
1460+
1461+///////////////////////////////////////////////////////////////////////////////
1462+
1463+/**
1464+ * Returns the English ordinal suffix for an integer, e.g., "st" for 1, "nd"
1465+ * for 2, etc.
1466+ *
1467+ * @param n The integer to return the ordinal suffix for.
1468+ * @return Returns said suffix.
1469+ */
1470+static char const* ordinal( int n ) {
1471+ n = std::abs( n );
1472+ switch ( n % 100 ) {
1473+ case 11:
1474+ case 12:
1475+ case 13:
1476+ break;
1477+ default:
1478+ switch ( n % 10 ) {
1479+ case 1: return "st";
1480+ case 2: return "nd";
1481+ case 3: return "rd";
1482+ }
1483+ }
1484+ return "th";
1485+}
1486+
1487+///////////////////////////////////////////////////////////////////////////////
1488+
1489+/**
1490+ * A unary_function to convert a (presumed) lower-case string to title-case
1491+ * "Like This."
1492+ */
1493+class to_title : public unary_function<char,char> {
1494+public:
1495+ to_title() : capitalize_( true ) { }
1496+
1497+ result_type operator()( argument_type c ) {
1498+ if ( ascii::is_alpha( c ) ) {
1499+ if ( capitalize_ ) {
1500+ c = ascii::to_upper( c );
1501+ capitalize_ = false;
1502+ }
1503+ } else if ( ascii::is_space( c ) )
1504+ capitalize_ = true;
1505+ return c;
1506+ };
1507+
1508+private:
1509+ bool capitalize_;
1510+};
1511+
1512+///////////////////////////////////////////////////////////////////////////////
1513+
1514+static void append_number( int n, modifier const &mod, zstring *dest ) {
1515+ switch ( mod.first.type ) {
1516+ case modifier::arabic: {
1517+ utf8::itou_buf_type buf;
1518+ zstring tmp( utf8::itou( n, buf, mod.first.zero ) );
1519+ if ( mod.second.co_type == modifier::ordinal )
1520+ tmp += ordinal( n );
1521+ *dest += mod.left_pad_zero( &tmp );
1522+ break;
1523+ }
1524+
1525+ case modifier::alpha:
1526+ case modifier::ALPHA: {
1527+ zstring tmp( alpha( n, mod.first.type == modifier::ALPHA ) );
1528+ *dest += mod.right_pad_space( &tmp );
1529+ break;
1530+ }
1531+
1532+ case modifier::roman:
1533+ case modifier::ROMAN: {
1534+ ostringstream oss;
1535+ if ( mod.first.type == modifier::ROMAN )
1536+ oss << uppercase;
1537+ oss << roman( n );
1538+ zstring tmp( oss.str() );
1539+ *dest += mod.right_pad_space( &tmp );
1540+ break;
1541+ }
1542+
1543+ case modifier::words: {
1544+ zstring tmp( english( n, mod.second.co_type == modifier::ordinal ) );
1545+ *dest += mod.right_pad_space( &tmp );
1546+ break;
1547+ }
1548+
1549+ case modifier::Words: {
1550+ zstring tmp( english( n, mod.second.co_type == modifier::ordinal ) );
1551+ std::transform( tmp.begin(), tmp.end(), tmp.begin(), to_title() );
1552+ *dest += mod.right_pad_space( &tmp );
1553+ break;
1554+ }
1555+
1556+ case modifier::WORDS: {
1557+ zstring tmp( english( n, mod.second.co_type == modifier::ordinal ) );
1558+ ascii::to_upper( tmp );
1559+ *dest += mod.right_pad_space( &tmp );
1560+ break;
1561+ }
1562+
1563+ default:
1564+ /* handled elsewhere */;
1565+ }
1566+}
1567+
1568+static void append_fractional_seconds( int n, modifier const &mod,
1569+ zstring *dest ) {
1570+ switch ( mod.first.type ) {
1571+ case modifier::arabic:
1572+ if ( mod.min_width || mod.max_width ) {
1573+ if ( mod.max_width ) {
1574+ double const f = (double)n / DateTime::FRAC_SECONDS_UPPER_LIMIT;
1575+ double const p = ::pow( 10, mod.max_width );
1576+ n = (int)( f * p + 0.5 );
1577+ } else
1578+ n = (int)( n * 1000.0 / DateTime::FRAC_SECONDS_UPPER_LIMIT );
1579+
1580+ ascii::itoa_buf_type buf;
1581+ zstring tmp( ascii::itoa( n, buf ) );
1582+
1583+ if ( tmp.size() < mod.min_width )
1584+ ascii::right_pad( &tmp, mod.min_width, '0' );
1585+ else if ( mod.min_width > 0 )
1586+ while ( tmp.size() > mod.min_width &&
1587+ tmp[ tmp.size() - 1 ] == '0' ) {
1588+ tmp = tmp.substr( 0, tmp.size() - 1 );
1589+ }
1590+ *dest += tmp;
1591+ break;
1592+ }
1593+ n = (int)( n * 1000.0 / DateTime::FRAC_SECONDS_UPPER_LIMIT );
1594+ // no break;
1595+ default:
1596+ append_number( n, mod, dest );
1597+ }
1598+}
1599+
1600+static void append_string( zstring const &s, modifier const &mod,
1601+ zstring *dest ) {
1602+ zstring tmp;
1603+ switch ( mod.first.type ) {
1604+ case modifier::name:
1605+ utf8::to_lower( s, &tmp );
1606+ break;
1607+ case modifier::Name: {
1608+ utf8::to_upper( s.substr( 0, 1 ), &tmp );
1609+ zstring tmp2;
1610+ utf8::to_lower( s.substr( 1 ), &tmp2 );
1611+ tmp += tmp2;
1612+ break;
1613+ }
1614+ case modifier::NAME:
1615+ utf8::to_upper( s, &tmp );
1616+ break;
1617+ default:
1618+ break;
1619+ }
1620+ *dest += mod.right_pad_space( &tmp );
1621+}
1622+
1623+static void append_month( unsigned mon, modifier const &mod, zstring *dest ) {
1624+ switch ( mod.first.type ) {
1625+ case modifier::name:
1626+ case modifier::Name:
1627+ case modifier::NAME: {
1628+ zstring name( locale::get_month_name( mon, mod.lang, mod.country ) );
1629+ utf8_string<zstring> u_name( name );
1630+ if ( mod.gt_max_width( u_name.size() ) ) {
1631+ //
1632+ // XQuery 3.0 F&O: 9.8.4.1: If the full representation of the value
1633+ // exceeds the specified maximum width, then the processor should
1634+ // attempt to use an alternative shorter representation that fits
1635+ // within the maximum width. Where the presentation modifier is N, n,
1636+ // or Nn, this is done by abbreviating the name, using either
1637+ // conventional abbreviations if available, or crude right-truncation
1638+ // if not.
1639+ //
1640+ name = locale::get_month_abbr( mon, mod.lang, mod.country );
1641+ if ( mod.gt_max_width( u_name.size() ) )
1642+ u_name = u_name.substr( 0, mod.max_width );
1643+ }
1644+ mod.append_if_fallback_lang( dest );
1645+ append_string( name, mod, dest );
1646+ break;
1647+ }
1648+ default:
1649+ append_number( mon + 1, mod, dest );
1650+ }
1651+}
1652+
1653+static void append_timezone( char component, TimeZone const &tz,
1654+ modifier const &mod, zstring *dest ) {
1655+ ascii::itoa_buf_type buf;
1656+ zstring format, tmp;
1657+ bool has_grouping_separators;
1658+
1659+ if ( mod.first.format.empty() ) {
1660+ format = "01:01";
1661+ has_grouping_separators = true;
1662+ } else {
1663+ format = mod.first.format;
1664+ has_grouping_separators = mod.first.has_grouping_separators;
1665+ }
1666+
1667+ int hour = tz.getHours();
1668+ int const min = std::abs( tz.getMinutes() );
1669+
1670+ switch ( mod.first.type ) {
1671+ case modifier::NAME:
1672+ //
1673+ // XQuery 3.0 F&O: 9.8.4.2: If the first presentation modifier is N, then
1674+ // the timezone is output (where possible) as a timezone name, for
1675+ // example EST or CET. The same timezone offset has different names in
1676+ // different places; it is therefore recommended that this option should
1677+ // be used only if a country code or Olson timezone name is supplied in
1678+ // the $place argument. In the absence of this information, the
1679+ // implementation may apply a default, for example by using the timezone
1680+ // names that are conventional in North America. If no timezone name can
1681+ // be identified, the timezone offset is output using the fallback format
1682+ // +01:01.
1683+ //
1684+ if ( !min )
1685+ switch ( hour ) {
1686+ case 0: tmp += "GMT"; goto append;
1687+ case -5: tmp += "EST"; goto append;
1688+ case -6: tmp += "CST"; goto append;
1689+ case -7: tmp += "MST"; goto append;
1690+ case -8: tmp += "PST"; goto append;
1691+ }
1692+ // TODO: use Olson timezone names
1693+ goto fallback;
1694+
1695+ case modifier::military_tz:
1696+ //
1697+ // Ibid: If the first presentation modifier is Z, then the timezone is
1698+ // formatted as a military timezone letter, using the convention Z =
1699+ // +00:00, A = +01:00, B = +02:00, ..., M = +12:00, N = -01:00, O =
1700+ // -02:00, ... Y = -12:00.
1701+ //
1702+ if ( tz.timeZoneNotSet() ) {
1703+ //
1704+ // Ibid: The letter J (meaning local time) is used in the case of a
1705+ // value that does not specify a timezone offset.
1706+ //
1707+ tmp += 'J';
1708+ break;
1709+ }
1710+ if ( hour >= -12 && hour <= 12 && !min ) {
1711+ tmp += time::get_military_tz( hour );
1712+ break;
1713+ }
1714+ //
1715+ // Ibid: Timezone offsets that have no representation in this system
1716+ // (for example Indian Standard Time, +05:30) are output as if the
1717+ // format 01:01 had been requested.
1718+ //
1719+ // no break;
1720+
1721+fallback:
1722+ format = "01:01";
1723+ // no break;
1724+
1725+ default:
1726+ if ( component == 'z' ) {
1727+ //
1728+ // Ibid: When the component specifier is z, the output is the same as
1729+ // for component specifier Z, except that it is prefixed by the
1730+ // characters GMT or some localized equivalent. The prefix is omitted,
1731+ // however, in cases where the timezone is identified by name rather
1732+ // than by a numeric offset from UTC.
1733+ //
1734+ tmp = "GMT";
1735+ }
1736+
1737+ if ( mod.second.at_type == modifier::traditional && !hour && !min ) {
1738+ //
1739+ // Ibid: If the first presentation modifier is numeric, in any of the
1740+ // above formats, and the second presentation modifier is t, then a
1741+ // zero timezone offset (that is, UTC) is output as Z instead of a
1742+ // signed numeric value.
1743+ //
1744+ tmp += 'Z';
1745+ break;
1746+ }
1747+
1748+ if ( tz.isNegative() )
1749+ tmp += '-', hour = std::abs( hour );
1750+ else
1751+ tmp += '+';
1752+
1753+ if ( has_grouping_separators ) {
1754+ //
1755+ // Ibid: If the first presentation modifier is numeric with a grouping-
1756+ // separator (for example 1:01 or 01.01), then the timezone offset is
1757+ // output in hours and minutes, separated by the grouping separator,
1758+ // even if the number of minutes is zero: for example +5:00 or +10.30.
1759+ //
1760+ int grouping_separators = 0;
1761+ bool got_digit = false;
1762+ int hm_width[] = { 0, 0 }; // hour/minute widths
1763+ utf8_string<zstring const> const u_format( format );
1764+ utf8_string<zstring> u_tmp( tmp );
1765+
1766+ FOR_EACH( utf8_string<zstring const>, i, u_format ) {
1767+ unicode::code_point const cp = *i;
1768+ if ( unicode::is_Nd( cp ) ) {
1769+ got_digit = true;
1770+ if ( grouping_separators < 2 )
1771+ ++hm_width[ grouping_separators ];
1772+ continue;
1773+ }
1774+ if ( got_digit && is_grouping_separator( cp ) ) {
1775+ if ( ++grouping_separators == 1 ) {
1776+ zstring tmp2( utf8::itou( hour, buf, mod.first.zero ) );
1777+ tmp += utf8::left_pad( &tmp2, hm_width[0], mod.first.zero );
1778+ }
1779+ } else if ( grouping_separators )
1780+ grouping_separators = 99;
1781+ u_tmp += cp;
1782+ }
1783+
1784+ if ( hm_width[1] ) {
1785+ zstring tmp2( utf8::itou( min, buf, mod.first.zero ) );
1786+ tmp += utf8::left_pad( &tmp2, hm_width[1], mod.first.zero );
1787+ }
1788+ } else {
1789+ utf8_string<zstring const> const u_format( format );
1790+ utf8_string<zstring const>::size_type const u_size( u_format.size() );
1791+
1792+ if ( u_size <= 2 ) {
1793+ //
1794+ // Ibid: If the first presentation modifier is numeric and comprises
1795+ // one or two digits with no grouping-separator (for example 1 or
1796+ // 01), then the timezone is formatted as a displacement from UTC in
1797+ // hours, preceded by a plus or minus sign: for example -5 or +03. If
1798+ // the actual timezone offset is not an integral number of hours,
1799+ // then the minutes part of the offset is appended, separated by a
1800+ // colon: for example +10:30 or -1:15.
1801+ //
1802+ zstring tmp2( utf8::itou( hour, buf, mod.first.zero ) );
1803+ tmp += utf8::left_pad( &tmp2, u_size, mod.first.zero );
1804+ if ( min ) {
1805+ tmp2 = utf8::itou( min, buf, mod.first.zero );
1806+ tmp += ':';
1807+ tmp += utf8::left_pad( &tmp2, 2, mod.first.zero );
1808+ }
1809+ break;
1810+ }
1811+ if ( u_size <= 4 ) {
1812+ //
1813+ // Ibid: If the first presentation modifier is numeric and comprises
1814+ // three or four digits with no grouping-separator, for example 001
1815+ // or 0001, then the timezone offset is shown in hours and minutes
1816+ // with no separator, for example -0500 or +1030.
1817+ //
1818+ int const hhmm = hour * 100 + min;
1819+ zstring tmp2( utf8::itou( hhmm, buf, mod.first.zero ) );
1820+ tmp += utf8::left_pad( &tmp2, u_size, mod.first.zero );
1821+ break;
1822+ }
1823+ } // else
1824+ } // switch
1825+
1826+append:
1827+ *dest += tmp;
1828+}
1829+
1830+static void append_weekday( unsigned mday, unsigned mon, unsigned year,
1831+ modifier const &mod, zstring *dest ) {
1832+ int wday = time::calc_wday( mday, mon, year );
1833+
1834+ modifier mod_copy( mod );
1835+ if ( !mod.first.parsed )
1836+ mod_copy.first.type = modifier::name;
1837+
1838+ switch ( mod_copy.first.type ) {
1839+ case modifier::name:
1840+ case modifier::Name:
1841+ case modifier::NAME: {
1842+ zstring name( locale::get_weekday_name( wday, mod.lang, mod.country ) );
1843+ utf8_string<zstring> u_name( name );
1844+ if ( mod.gt_max_width( u_name.size() ) ) {
1845+ //
1846+ // XQuery 3.0 F&O: 9.8.4.1: If the full representation of the value
1847+ // exceeds the specified maximum width, then the processor should
1848+ // attempt to use an alternative shorter representation that fits
1849+ // within the maximum width. Where the presentation modifier is N, n,
1850+ // or Nn, this is done by abbreviating the name, using either
1851+ // conventional abbreviations if available, or crude right-truncation
1852+ // if not.
1853+ //
1854+ name = locale::get_weekday_abbr( wday, mod.lang, mod.country );
1855+ if ( mod.gt_max_width( u_name.size() ) )
1856+ u_name = u_name.substr( 0, mod.max_width );
1857+ }
1858+ mod.append_if_fallback_lang( dest );
1859+ append_string( name, mod_copy, dest );
1860+ break;
1861+ }
1862+ default: {
1863+ int const new_wday = calendar::convert_wday_to( wday, mod.cal );
1864+ if ( mod.cal_is_fallback || new_wday == -1 ) {
1865+ //
1866+ // Ibid: If the fallback representation uses a different calendar from
1867+ // that requested, the output string must identify the calendar
1868+ // actually used, for example by prefixing the string with [Calendar:
1869+ // X] (where X is the calendar actually used), localized as appropriate
1870+ // to the requested language.
1871+ //
1872+ ostringstream oss;
1873+ // TODO: localize "Calendar"
1874+ oss << "[Calendar: "
1875+ << ( new_wday == -1 ? calendar::get_default() : mod.cal ) << ']';
1876+ *dest += oss.str();
1877+ } else
1878+ wday = new_wday;
1879+ append_number( wday, mod_copy, dest );
1880+ }
1881+ }
1882+}
1883+
1884+static void append_week_in_year( unsigned mday, unsigned mon, unsigned year,
1885+ modifier const &mod, zstring *dest ) {
1886+ int week = time::calendar::calc_week_in_year( mday, mon, year, mod.cal );
1887+ if ( week == -1 ) {
1888+ week = time::calendar::calc_week_in_year( mday, mon, year, calendar::ISO );
1889+ ostringstream oss;
1890+ // TODO: localize "Calendar"
1891+ oss << "[Calendar: " << calendar::string_of[ calendar::ISO ] << ']';
1892+ *dest += oss.str();
1893+ }
1894+ append_number( week, mod, dest );
1895+}
1896+
1897+static void append_year( int year, modifier const &mod, zstring *s ) {
1898+ zstring tmp;
1899+ append_number( year, mod, &tmp );
1900+
1901+ if ( mod.first.type == modifier::arabic ) {
1902+ utf8_string<zstring> u_tmp( tmp );
1903+ utf8_string<zstring>::size_type const u_size = u_tmp.size();
1904+ if ( mod.gt_max_width( u_size ) ) {
1905+ //
1906+ // XQuery 3.0 F&O: 9.8.4.1: If the full representation of the value
1907+ // exceeds the specified maximum width, then the processor should attempt
1908+ // to use an alternative shorter representation that fits within the
1909+ // maximum width. ... In the case of the year component, setting
1910+ // max-width requests omission of high-order digits from the year, for
1911+ // example, if max-width is set to 2 then the year 2003 will be output as
1912+ // 03.
1913+ //
1914+ u_tmp = u_tmp.substr( u_size - mod.max_width );
1915+ }
1916+ }
1917+ *s += tmp;
1918+}
1919+
1920+static void parse_first_modifier( zstring const &picture_str,
1921+ zstring::const_iterator *i,
1922+ modifier *mod, QueryLoc const &loc ) {
1923+ zstring::const_iterator &j = *i;
1924+ ascii::skip_whitespace( picture_str, &j );
1925+ if ( j == picture_str.end() || *j == ',' ) {
1926+ //
1927+ // Assume that the ',' is the start of the width modifier (hence there is
1928+ // neither a first nor second modifier).
1929+ //
1930+ return;
1931+ }
1932+
1933+ utf8_string<zstring const> const u_picture_str( picture_str );
1934+ utf8_string<zstring const>::const_iterator u( u_picture_str.current( j ) );
1935+ utf8_string<zstring> u_mod_format( mod->first.format );
1936+ unicode::code_point cp = *u;
1937+
1938+ if ( cp != '#' && is_grouping_separator( cp ) ) {
1939+ //
1940+ // XQuery 3.0 F&O: 4.6.1: A grouping-separator-sign must not appear
1941+ // at the start ... of the decimal-digit-pattern ....
1942+ //
1943+ throw XQUERY_EXCEPTION(
1944+ err::FOFD1340,
1945+ ERROR_PARAMS(
1946+ picture_str,
1947+ ZED( FOFD1340_NoGroupSepAtStart_3 ),
1948+ unicode::printable_cp( cp )
1949+ ),
1950+ ERROR_LOC( loc )
1951+ );
1952+ }
1953+
1954+ //
1955+ // Because of:
1956+ //
1957+ // Ibid: if a variable marker contains one or more commas, then the last
1958+ // comma is treated as introducing the width modifier, and all others are
1959+ // treated as grouping separators.
1960+ //
1961+ // we have to count the number of commas in order to know when we've reached
1962+ // the last one.
1963+ //
1964+ int commas = 0;
1965+ for ( zstring::const_iterator c( *i ); c != picture_str.end(); ++c )
1966+ if ( *c == ',' )
1967+ ++commas;
1968+
1969+ unicode::code_point zero[2];
1970+
1971+ if ( cp == '#' || unicode::is_Nd( cp, &zero[0] ) ) {
1972+ bool got_grouping_separator = false;
1973+ bool got_mandatory_digit = cp != '#';
1974+
1975+ u_mod_format = *u;
1976+ while ( ++u != u_picture_str.end() ) {
1977+ cp = *u;
1978+ if ( cp == '#' ) {
1979+ if ( got_mandatory_digit ) {
1980+ //
1981+ // Ibid: There may be zero or more optional-digit-signs, and (if
1982+ // present) these must precede all mandatory-digit-signs.
1983+ //
1984+ throw XQUERY_EXCEPTION(
1985+ err::FOFD1340,
1986+ ERROR_PARAMS(
1987+ picture_str,
1988+ ZED( FOFD1340_NoOptDigitAfterMandatory )
1989+ ),
1990+ ERROR_LOC( loc )
1991+ );
1992+ }
1993+ got_grouping_separator = false;
1994+ } else if ( unicode::is_Nd( cp, &zero[ got_mandatory_digit ] ) ) {
1995+ if ( got_mandatory_digit ) {
1996+ if ( zero[1] != zero[0] ) {
1997+ //
1998+ // Ibid: All mandatory-digit-signs within the format token must be
1999+ // from the same digit family, where a digit family is a sequence
2000+ // of ten consecutive characters in Unicode category Nd, having
2001+ // digit values 0 through 9.
2002+ //
2003+ throw XQUERY_EXCEPTION(
2004+ err::FOFD1340,
2005+ ERROR_PARAMS(
2006+ picture_str,
2007+ ZED( FOFD1340_DigitNotSameFamily_34 ),
2008+ unicode::printable_cp( cp ),
2009+ unicode::printable_cp( zero[1] )
2010+ ),
2011+ ERROR_LOC( loc )
2012+ );
2013+ }
2014+ //
2015+ // Ibid: A format token containing more than one digit, such as 001
2016+ // or 9999, sets the minimum and maximum width to the number of
2017+ // digits appearing in the format token.
2018+ //
2019+ if ( !mod->min_width )
2020+ mod->min_width = mod->max_width = 2;
2021+ else
2022+ mod->min_width = ++mod->max_width;
2023+ } else
2024+ got_mandatory_digit = true;
2025+ got_grouping_separator = false;
2026+ } else if ( cp == ';' || cp == ']' )
2027+ break;
2028+ else if ( unicode::is_space( cp ) )
2029+ continue;
2030+ else if ( is_grouping_separator( cp ) ) {
2031+ if ( cp == ',' && !--commas ) {
2032+ //
2033+ // Ibid: if a variable marker contains one or more commas, then the
2034+ // last comma is treated as introducing the width modifier, and all
2035+ // others are treated as grouping separators.
2036+ //
2037+ break;
2038+ }
2039+ if ( got_grouping_separator ) {
2040+ //
2041+ // Ibid: A grouping-separator-sign must not appear ... adjacent to
2042+ // another grouping-separator-sign.
2043+ //
2044+ throw XQUERY_EXCEPTION(
2045+ err::FOFD1340,
2046+ ERROR_PARAMS(
2047+ picture_str,
2048+ ZED( FOFD1340_NoAdjacentGroupSep_3 ),
2049+ unicode::printable_cp( cp )
2050+ ),
2051+ ERROR_LOC( loc )
2052+ );
2053+ }
2054+ got_grouping_separator = true;
2055+ mod->first.has_grouping_separators = true;
2056+ } else
2057+ break;
2058+
2059+ u_mod_format += cp;
2060+ } // while
2061+ if ( got_grouping_separator ) {
2062+ //
2063+ // Ibid: A grouping-separator-sign must not appear at the ... end of the
2064+ // decimal-digit-pattern ....
2065+ //
2066+ throw XQUERY_EXCEPTION(
2067+ err::FOFD1340,
2068+ ERROR_PARAMS(
2069+ picture_str,
2070+ ZED( FOFD1340_NoGroupSepAtEnd_3 ),
2071+ unicode::printable_cp( cp )
2072+ ),
2073+ ERROR_LOC( loc )
2074+ );
2075+ }
2076+ if ( !got_mandatory_digit ) {
2077+ //
2078+ // Ibid: There must be at least one mandatory-digit-sign.
2079+ //
2080+ throw XQUERY_EXCEPTION(
2081+ err::FOFD1340,
2082+ ERROR_PARAMS( picture_str, ZED( FOFD1340_MustBeOneMandatoryDigit ) ),
2083+ ERROR_LOC( loc )
2084+ );
2085+ }
2086+ mod->first.zero = zero[0];
2087+ j = u.base();
2088+ } else {
2089+ switch ( *j++ ) {
2090+ case 'A':
2091+ mod->first.type = modifier::ALPHA;
2092+ break;
2093+ case 'a':
2094+ mod->first.type = modifier::alpha;
2095+ break;
2096+ case 'I':
2097+ mod->first.type = modifier::ROMAN;
2098+ break;
2099+ case 'i':
2100+ mod->first.type = modifier::roman;
2101+ break;
2102+ case 'N':
2103+ if ( j != picture_str.end() && *j == 'n' )
2104+ mod->first.type = modifier::Name, ++j;
2105+ else
2106+ mod->first.type = modifier::NAME;
2107+ break;
2108+ case 'n':
2109+ mod->first.type = modifier::name;
2110+ break;
2111+ case 'W':
2112+ if ( j != picture_str.end() && *j == 'w' )
2113+ mod->first.type = modifier::Words, ++j;
2114+ else
2115+ mod->first.type = modifier::WORDS;
2116+ break;
2117+ case 'w':
2118+ mod->first.type = modifier::words;
2119+ break;
2120+ case 'Z':
2121+ mod->first.type = modifier::military_tz;
2122+ break;
2123+ default:
2124+ //
2125+ // Ibid: If an implementation does not support a numbering sequence
2126+ // represented by the given token, it must use a format token of 1.
2127+ //
2128+ mod->first.type = modifier::arabic;
2129+ } // switch
2130+ }
2131+ mod->first.parsed = true;
2132+}
2133+
2134+static void parse_second_modifier( zstring const &picture_str,
2135+ zstring::const_iterator *i, modifier *mod,
2136+ QueryLoc const &loc ) {
2137+ zstring::const_iterator &j = *i;
2138+ ascii::skip_whitespace( picture_str, &j );
2139+ if ( j == picture_str.end() )
2140+ return;
2141+ switch ( *j ) {
2142+ case 'c': mod->second.co_type = modifier::cardinal ; break;
2143+ case 'o': mod->second.co_type = modifier::ordinal ; break;
2144+ case 'a': mod->second.at_type = modifier::alphabetic ; ++j; return;
2145+ case 't': mod->second.at_type = modifier::traditional; ++j; return;
2146+ default : return;
2147+ }
2148+ if ( ++j == picture_str.end() )
2149+ return;
2150+ if ( *j == '(' ) {
2151+ while ( true ) {
2152+ if ( ++j == picture_str.end() )
2153+ throw XQUERY_EXCEPTION(
2154+ err::FOFD1340,
2155+ ERROR_PARAMS( picture_str, ZED( CharExpected_3 ), ')' ),
2156+ ERROR_LOC( loc )
2157+ );
2158+ if ( *j == ')' )
2159+ break;
2160+ mod->second.co_string += *j;
2161+ }
2162+ ++j;
2163+ }
2164+}
2165+
2166+static void parse_width_modifier( zstring const &picture_str,
2167+ zstring::const_iterator *i, modifier *mod,
2168+ QueryLoc const &loc ) {
2169+ zstring::const_iterator &j = *i;
2170+
2171+ ascii::skip_whitespace( picture_str, &j );
2172+ if ( j == picture_str.end() || (*j != ',' && *j != ';') )
2173+ return;
2174+ ascii::skip_whitespace( picture_str, &++j );
2175+ if ( j == picture_str.end() )
2176+ goto bad_width_modifier;
2177+ if ( *j == '*' ) {
2178+ mod->min_width = 0;
2179+ ++j;
2180+ } else {
2181+ try {
2182+ mod->min_width = static_cast<modifier::width_type>(
2183+ ztd::atoull( j, picture_str.end(), &j )
2184+ );
2185+ }
2186+ catch ( std::exception const& ) {
2187+ goto bad_width_modifier;
2188+ }
2189+ }
2190+
2191+ mod->max_width = 0;
2192+
2193+ ascii::skip_whitespace( picture_str, &j );
2194+ if ( j == picture_str.end() || *j != '-' )
2195+ return;
2196+ ascii::skip_whitespace( picture_str, &++j );
2197+ if ( j == picture_str.end() )
2198+ goto bad_width_modifier;
2199+ if ( *j == '*' )
2200+ ++j;
2201+ else {
2202+ try {
2203+ mod->max_width = static_cast<modifier::width_type>(
2204+ ztd::atoull( j, picture_str.end(), &j )
2205+ );
2206+ }
2207+ catch ( std::exception const& ) {
2208+ goto bad_width_modifier;
2209+ }
2210+ }
2211+
2212+ return;
2213+
2214+bad_width_modifier:
2215+ throw XQUERY_EXCEPTION(
2216+ err::FOFD1340,
2217+ ERROR_PARAMS( picture_str, ZED( FOFD1340_BadWidthModifier ) ),
2218+ ERROR_LOC( loc )
2219+ );
2220+}
2221+
2222+static int get_data_type( char component ) {
2223+ switch ( component ) {
2224+ case 'D': return DateTime::DAY_DATA;
2225+ case 'd': return DateTime::DAY_DATA;
2226+ case 'E': return DateTime::YEAR_DATA;
2227+ case 'F': return DateTime::DAY_DATA;
2228+ case 'f': return DateTime::FRACSECONDS_DATA;
2229+ case 'H': return DateTime::HOUR_DATA;
2230+ case 'h': return DateTime::HOUR_DATA;
2231+ case 'm': return DateTime::MINUTE_DATA;
2232+ case 'M': return DateTime::MONTH_DATA;
2233+ case 'P': return DateTime::HOUR_DATA;
2234+ case 's': return DateTime::SECONDS_DATA;
2235+ case 'W': return DateTime::DAY_DATA;
2236+ case 'w': return DateTime::DAY_DATA;
2237+ case 'Y': return DateTime::YEAR_DATA;
2238+ default : return -1;
2239+ }
2240+}
2241+
2242+bool FnFormatDateTimeIterator::nextImpl( store::Item_t& result,
2243+ PlanState &planState ) const {
2244+ zstring picture_str, result_str, item_str;
2245+ xs_dateTime dateTime;
2246+ calendar::type cal = calendar::unknown;
2247+ iso639_1::type lang = iso639_1::unknown;
2248+ iso3166_1::type country = iso3166_1::unknown;
2249+ bool cal_is_fallback = false, lang_is_fallback = false;
2250+ bool in_variable_marker;
2251+ store::Item_t item;
2252+ PlanIteratorState *state;
2253+
2254+ DEFAULT_STACK_INIT( PlanIteratorState, state, planState);
2255+
2256+ if ( !consumeNext( item, theChildren[0].getp(), planState ) ) {
2257+ // Got the empty sequence -- return same
2258+ STACK_PUSH( false, state );
2259+ } else {
2260+ dateTime = item->getDateTimeValue();
2261+ consumeNext( item, theChildren[1].getp(), planState );
2262+ item->getStringValue2( picture_str );
2263+
2264+ if ( theChildren.size() > 2 ) {
2265+ consumeNext( item, theChildren[2].getp(), planState );
2266+ if ( !locale::parse( item->getStringValue(), &lang, &country ) ||
2267+ !locale::is_supported( lang, country ) ) {
2268+ lang = iso639_1::unknown;
2269+ lang_is_fallback = true;
2270+ }
2271+
2272+ consumeNext( item, theChildren[3].getp(), planState );
2273+ item->getStringValue2( item_str );
2274+ // TODO: handle calendar being a QName.
2275+ cal = calendar::find( item_str );
2276+ if ( !cal )
2277+ cal_is_fallback = true;
2278+
2279+ consumeNext( item, theChildren[4].getp(), planState );
2280+ item->getStringValue2( item_str );
2281+ // TODO: do something with place
2282+ }
2283+
2284+ if ( !cal ) {
2285+ //
2286+ // XQuery 3.0 F&O: 9.8.4.3: If the $calendar argument is omitted or is
2287+ // set to an empty sequence then the default calendar defined in the
2288+ // dynamic context is used.
2289+ //
2290+ cal = planState.theLocalDynCtx->get_calendar();
2291+ }
2292+
2293+ if ( !lang ) {
2294+ //
2295+ // Ibid: If the $language argument is omitted or is set to an empty
2296+ // sequence, or if it is set to an invalid value or a value that the
2297+ // implementation does not recognize, then the processor uses the default
2298+ // language defined in the dynamic context.
2299+ //
2300+ planState.theLocalDynCtx->get_locale( &lang, &country );
2301+ }
2302+
2303+ char component;
2304+ in_variable_marker = false;
2305+
2306+ FOR_EACH( zstring, i, picture_str ) {
2307+ if ( !in_variable_marker ) {
2308+ switch ( *i ) {
2309+ case '[':
2310+ if ( ztd::peek( picture_str, i ) == '[' )
2311+ ++i;
2312+ else {
2313+ component = 0;
2314+ in_variable_marker = true;
2315+ continue;
2316+ }
2317+ break;
2318+ case ']':
2319+ if ( ztd::peek( picture_str, i ) == ']' )
2320+ ++i;
2321+ break;
2322+ }
2323+ result_str += *i;
2324+ continue;
2325+ }
2326+
2327+ if ( ascii::is_space( *i ) )
2328+ continue; // ignore all whitespace
2329+
2330+ switch ( *i ) {
2331+ case ']':
2332+ if ( !component )
2333+ throw XQUERY_EXCEPTION(
2334+ err::FOFD1340,
2335+ ERROR_PARAMS( picture_str, ZED( FOFD1340_NoComponent ) ),
2336+ ERROR_LOC( loc )
2337+ );
2338+ component = 0;
2339+ in_variable_marker = false;
2340+ continue;
2341+ case 'C':
2342+ case 'D':
2343+ case 'd':
2344+ case 'E':
2345+ case 'F':
2346+ case 'f':
2347+ case 'H':
2348+ case 'h':
2349+ case 'M':
2350+ case 'm':
2351+ case 'P':
2352+ case 's':
2353+ case 'W':
2354+ case 'w':
2355+ case 'Y':
2356+ case 'Z':
2357+ case 'z':
2358+#if 0
2359+ if ( component )
2360+ throw XQUERY_EXCEPTION(
2361+ err::FOFD1340,
2362+ ERROR_PARAMS(
2363+ picture_str, ZED( FOFD1340_MultipleComponent_3 ), *i
2364+ ),
2365+ ERROR_LOC( loc )
2366+ );
2367+#endif
2368+ component = *i;
2369+ break;
2370+ default:
2371+ throw XQUERY_EXCEPTION(
2372+ err::FOFD1340,
2373+ ERROR_PARAMS( picture_str, ZED( FOFD1340_BadComponent_3 ), *i ),
2374+ ERROR_LOC( loc )
2375+ );
2376+ } // switch
2377+ if ( ++i == picture_str.end() )
2378+ goto eos;
2379+
2380+ modifier mod;
2381+ mod.lang = lang;
2382+ mod.lang_is_fallback = lang_is_fallback;
2383+ mod.country = country;
2384+ mod.cal = cal;
2385+ mod.cal_is_fallback = cal_is_fallback;
2386+
2387+ if ( *i != ']' ) {
2388+ parse_first_modifier( picture_str, &i, &mod, loc );
2389+ if ( i == picture_str.end() )
2390+ goto eos;
2391+ if ( *i != ']' ) {
2392+ parse_second_modifier( picture_str, &i, &mod, loc );
2393+ if ( i == picture_str.end() )
2394+ goto eos;
2395+ parse_width_modifier( picture_str, &i, &mod, loc );
2396+ if ( i == picture_str.end() )
2397+ goto eos;
2398+ }
2399+ }
2400+ if ( *i == ']' )
2401+ --i;
2402+
2403+ int const data_type = get_data_type( component );
2404+ if ( data_type != -1 && !DateTime::FACET_MEMBERS[facet_type][data_type] )
2405+ throw XQUERY_EXCEPTION(
2406+ err::FOFD1350, ERROR_PARAMS( component ), ERROR_LOC( loc )
2407+ );
2408+
2409+ switch ( component ) {
2410+ case 'C': { // calendar
2411+ modifier mod_copy( mod );
2412+ if ( !mod.first.parsed )
2413+ mod_copy.first.type = modifier::name;
2414+ append_string( "gregorian", mod_copy, &result_str );
2415+ break;
2416+ }
2417+ case 'D':
2418+ append_number( dateTime.getDay(), mod, &result_str );
2419+ break;
2420+ case 'd':
2421+ append_number( dateTime.getDayOfYear(), mod, &result_str );
2422+ break;
2423+ case 'E': { // era
2424+ modifier mod_copy( mod );
2425+ if ( !mod.first.parsed )
2426+ mod_copy.first.type = modifier::name;
2427+ int const year = dateTime.getYear();
2428+ zstring const era( year > 0 ? "ad" : year < 0 ? "bc" : "" );
2429+ append_string( era, mod_copy, &result_str );
2430+ break;
2431+ }
2432+ case 'F': {
2433+ modifier mod_copy( mod );
2434+ if ( !mod.first.parsed )
2435+ mod_copy.first.type = modifier::name;
2436+ append_weekday(
2437+ dateTime.getDay(), dateTime.getMonth() - 1, dateTime.getYear(),
2438+ mod_copy, &result_str
2439+ );
2440+ break;
2441+ }
2442+ case 'f':
2443+ append_fractional_seconds(
2444+ dateTime.getFractionalSeconds(), mod, &result_str
2445+ );
2446+ break;
2447+ case 'H': // hour (24 hours)
2448+ append_number( dateTime.getHours(), mod, &result_str );
2449+ break;
2450+ case 'h': // hour (12 hours)
2451+ // Convert hour from: 0 1 ... 12 13 ... 23
2452+ // to: 12 1 ... 12 1 ... 11
2453+ append_number(
2454+ 1 + (11 + dateTime.getHours()) % 12, mod, &result_str
2455+ );
2456+ break;
2457+ case 'M':
2458+ append_month( dateTime.getMonth() - 1, mod, &result_str );
2459+ break;
2460+ case 'm': {
2461+ modifier mod_copy( mod );
2462+ mod_copy.set_default_width( 2 );
2463+ append_number( dateTime.getMinutes(), mod_copy, &result_str );
2464+ break;
2465+ }
2466+ case 'P': {
2467+ modifier mod_copy( mod );
2468+ if ( !mod.first.parsed )
2469+ mod_copy.first.type = modifier::name;
2470+ append_string(
2471+ locale::get_time_ampm( dateTime.getHours() >= 12, lang, country ),
2472+ mod_copy, &result_str
2473+ );
2474+ break;
2475+ }
2476+ case 's': {
2477+ modifier mod_copy( mod );
2478+ mod_copy.set_default_width( 2 );
2479+ append_number( dateTime.getIntSeconds(), mod_copy, &result_str );
2480+ break;
2481+ }
2482+ case 'W':
2483+ append_week_in_year(
2484+ dateTime.getDay(), dateTime.getMonth() - 1, dateTime.getYear(),
2485+ mod, &result_str
2486+ );
2487+ break;
2488+ case 'w':
2489+ append_number( dateTime.getWeekInMonth(), mod, &result_str );
2490+ break;
2491+ case 'Y':
2492+ append_year( std::abs( dateTime.getYear() ), mod, &result_str );
2493+ break;
2494+ case 'Z':
2495+ case 'z':
2496+ append_timezone(
2497+ component, dateTime.getTimezone(), mod, &result_str
2498+ );
2499+ break;
2500+ } // switch
2501+ } // for
2502+
2503+ if ( in_variable_marker )
2504+eos: throw XQUERY_EXCEPTION(
2505+ err::FOFD1340,
2506+ ERROR_PARAMS( picture_str, ZED( CharExpected_3 ), ']' ),
2507+ ERROR_LOC( loc )
2508+ );
2509+
2510+ STACK_PUSH( GENV_ITEMFACTORY->createString( result, result_str ), state );
2511+ }
2512+
2513+ STACK_END( state );
2514+}
2515+
2516+///////////////////////////////////////////////////////////////////////////////
2517+
2518+} // namespace zorba
2519+/* vim:set et sw=2 ts=2: */
2520
2521=== added file 'src/runtime/durations_dates_times/format_dateTime.h'
2522--- src/runtime/durations_dates_times/format_dateTime.h 1970-01-01 00:00:00 +0000
2523+++ src/runtime/durations_dates_times/format_dateTime.h 2013-03-21 16:00:34 +0000
2524@@ -0,0 +1,81 @@
2525+/*
2526+ * Copyright 2006-2008 The FLWOR Foundation.
2527+ *
2528+ * Licensed under the Apache License, Version 2.0 (the "License");
2529+ * you may not use this file except in compliance with the License.
2530+ * You may obtain a copy of the License at
2531+ *
2532+ * http://www.apache.org/licenses/LICENSE-2.0
2533+ *
2534+ * Unless required by applicable law or agreed to in writing, software
2535+ * distributed under the License is distributed on an "AS IS" BASIS,
2536+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
2537+ * See the License for the specific language governing permissions and
2538+ * limitations under the License.
2539+ */
2540+
2541+#ifndef ZORBA_RUNTIME_FORMAT_DATETIME_H
2542+#define ZORBA_RUNTIME_FORMAT_DATETIME_H
2543+
2544+#include "common/shared_types.h"
2545+#include "zorbatypes/datetime.h"
2546+
2547+#include "runtime/base/binarybase.h"
2548+#include "runtime/base/unarybase.h"
2549+#include "runtime/base/narybase.h"
2550+
2551+namespace zorba {
2552+
2553+///////////////////////////////////////////////////////////////////////////////
2554+
2555+// XQuery 3.0 DateTime formatting
2556+class FnFormatDateTimeIterator :
2557+ public NaryBaseIterator<FnFormatDateTimeIterator,PlanIteratorState>
2558+{
2559+
2560+public:
2561+ SERIALIZABLE_CLASS(FnFormatDateTimeIterator);
2562+
2563+ SERIALIZABLE_CLASS_CONSTRUCTOR2T(
2564+ FnFormatDateTimeIterator,
2565+ NaryBaseIterator<FnFormatDateTimeIterator, PlanIteratorState >);
2566+
2567+ void serialize( ::zorba::serialization::Archiver &ar )
2568+ {
2569+ serialize_baseclass(ar,
2570+ (NaryBaseIterator<FnFormatDateTimeIterator, PlanIteratorState >*)this);
2571+
2572+ SERIALIZE_ENUM(DateTime::FACET_TYPE, facet_type);
2573+ }
2574+
2575+public:
2576+ FnFormatDateTimeIterator(
2577+ static_context *sctx,
2578+ QueryLoc const &loc,
2579+ std::vector<PlanIter_t> &aChildren,
2580+ DateTime::FACET_TYPE a_facet_type = DateTime::DATETIME_FACET)
2581+ :
2582+ NaryBaseIterator<FnFormatDateTimeIterator, PlanIteratorState>(sctx, loc, aChildren),
2583+ facet_type(a_facet_type)
2584+ {
2585+ }
2586+
2587+ void accept( PlanIterVisitor& ) const;
2588+
2589+ bool nextImpl( store::Item_t&, PlanState& ) const;
2590+
2591+private:
2592+ DateTime::FACET_TYPE facet_type;
2593+};
2594+
2595+///////////////////////////////////////////////////////////////////////////////
2596+
2597+} // namespace zorba
2598+
2599+#endif /* ZORBA_RUNTIME_FORMAT_DATETIME_H */
2600+/*
2601+ * Local variables:
2602+ * mode: c++
2603+ * End:
2604+ */
2605+/* vim:set et sw=2 ts=2: */
2606
2607=== modified file 'src/runtime/visitors/printer_visitor_impl.cpp'
2608--- src/runtime/visitors/printer_visitor_impl.cpp 2013-03-05 12:34:19 +0000
2609+++ src/runtime/visitors/printer_visitor_impl.cpp 2013-03-21 16:00:34 +0000
2610@@ -46,6 +46,7 @@
2611 #include "runtime/core/arithmetic_impl.h"
2612 #include "runtime/sequences/SequencesImpl.h"
2613 #include "runtime/durations_dates_times/DurationsDatesTimesImpl.h"
2614+#include "runtime/durations_dates_times/format_dateTime.h"
2615 #ifdef ZORBA_WITH_DEBUGGER
2616 #include "runtime/debug/debug_iterator.h"
2617 #endif
2618
2619=== modified file 'src/unit_tests/CMakeLists.txt'
2620--- src/unit_tests/CMakeLists.txt 2013-03-17 04:47:01 +0000
2621+++ src/unit_tests/CMakeLists.txt 2013-03-21 16:00:34 +0000
2622@@ -22,6 +22,7 @@
2623 test_mem_sizeof.cpp
2624 test_parameters.cpp
2625 test_string.cpp
2626+ test_time.cpp
2627 test_time_parse.cpp
2628 test_uri.cpp
2629 test_uuid.cpp
2630
2631=== added file 'src/unit_tests/test_time.cpp'
2632--- src/unit_tests/test_time.cpp 1970-01-01 00:00:00 +0000
2633+++ src/unit_tests/test_time.cpp 2013-03-21 16:00:34 +0000
2634@@ -0,0 +1,118 @@
2635+/*
2636+ * Copyright 2006-2008 The FLWOR Foundation.
2637+ *
2638+ * Licensed under the Apache License, Version 2.0 (the "License");
2639+ * you may not use this file except in compliance with the License.
2640+ * You may obtain a copy of the License at
2641+ *
2642+ * http://www.apache.org/licenses/LICENSE-2.0
2643+ *
2644+ * Unless required by applicable law or agreed to in writing, software
2645+ * distributed under the License is distributed on an "AS IS" BASIS,
2646+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
2647+ * See the License for the specific language governing permissions and
2648+ * limitations under the License.
2649+ */
2650+
2651+#include "stdafx.h"
2652+
2653+#include <cstring>
2654+#include <functional>
2655+#include <iostream>
2656+#include <stdexcept>
2657+#include <string>
2658+
2659+#include "util/ascii_util.h"
2660+#include "util/stl_util.h"
2661+#include "util/time_util.h"
2662+#include "zorbatypes/zstring.h"
2663+
2664+using namespace std;
2665+using namespace zorba;
2666+using namespace zorba::time;
2667+
2668+///////////////////////////////////////////////////////////////////////////////
2669+
2670+static int failures;
2671+static int test_no;
2672+
2673+static bool assert_true( int no, char const *expr, int line, bool result ) {
2674+ if ( !result ) {
2675+ cout << '#' << no << " FAILED, line " << line << ": " << expr << endl;
2676+ ++failures;
2677+ }
2678+ return result;
2679+}
2680+
2681+#define ASSERT_TRUE( NO, EXPR ) assert_true( NO, #EXPR, __LINE__, !!(EXPR) )
2682+
2683+///////////////////////////////////////////////////////////////////////////////
2684+
2685+static void test_calc_week_in_year() {
2686+ struct test_type {
2687+ unsigned mday, mon, year;
2688+ time::calendar::type cal;
2689+ int expected;
2690+ };
2691+ static test_type const test[] = {
2692+ /* 1 */ { 1, time::jan, 2013, calendar::AD, 1 },
2693+ /* 2 */ { 2, time::jan, 2013, calendar::AD, 1 },
2694+ /* 3 */ { 3, time::jan, 2013, calendar::AD, 1 },
2695+ /* 4 */ { 4, time::jan, 2013, calendar::AD, 1 },
2696+ /* 5 */ { 5, time::jan, 2013, calendar::AD, 1 },
2697+ /* 6 */ { 6, time::jan, 2013, calendar::AD, 2 },
2698+ /* 7 */ { 28, time::dec, 2013, calendar::AD, 52 },
2699+ /* 8 */ { 31, time::dec, 2013, calendar::AD, 53 },
2700+
2701+ /* 9 */ { 1, time::jan, 2013, calendar::ISO, 1 },
2702+ /* 10 */ { 2, time::jan, 2013, calendar::ISO, 1 },
2703+ /* 11 */ { 3, time::jan, 2013, calendar::ISO, 1 },
2704+ /* 12 */ { 4, time::jan, 2013, calendar::ISO, 1 },
2705+ /* 13 */ { 5, time::jan, 2013, calendar::ISO, 1 },
2706+ /* 14 */ { 6, time::jan, 2013, calendar::ISO, 1 },
2707+ /* 15 */ { 7, time::jan, 2013, calendar::ISO, 2 },
2708+
2709+ // Test cases taken from http://en.wikipedia.org/wiki/ISO_week_date
2710+ /* 16 */ { 1, time::jan, 2005, calendar::ISO, 53 },
2711+ /* 17 */ { 2, time::jan, 2005, calendar::ISO, 53 },
2712+ /* 18 */ { 31, time::dec, 2005, calendar::ISO, 52 },
2713+ /* 19 */ { 1, time::jan, 2007, calendar::ISO, 1 },
2714+ /* 20 */ { 30, time::dec, 2007, calendar::ISO, 52 },
2715+ /* 21 */ { 31, time::dec, 2007, calendar::ISO, 1 },
2716+ /* 22 */ { 1, time::jan, 2008, calendar::ISO, 1 },
2717+ /* 23 */ { 28, time::dec, 2008, calendar::ISO, 52 },
2718+ /* 24 */ { 29, time::dec, 2008, calendar::ISO, 1 },
2719+ /* 25 */ { 30, time::dec, 2008, calendar::ISO, 1 },
2720+ /* 26 */ { 31, time::dec, 2008, calendar::ISO, 1 },
2721+ /* 27 */ { 31, time::dec, 2009, calendar::ISO, 53 },
2722+ /* 28 */ { 1, time::jan, 2010, calendar::ISO, 53 },
2723+ /* 29 */ { 2, time::jan, 2010, calendar::ISO, 53 },
2724+ /* 30 */ { 3, time::jan, 2010, calendar::ISO, 53 },
2725+ /* 31 */ { 4, time::jan, 2010, calendar::ISO, 1 },
2726+
2727+ { 0 },
2728+ };
2729+
2730+ for ( test_type const *t = test; t->mday; ++t ) {
2731+ int w = calendar::calc_week_in_year( t->mday, t->mon, t->year, t->cal );
2732+ ++test_no;
2733+ ASSERT_TRUE( test_no, w == t->expected );
2734+ }
2735+}
2736+
2737+///////////////////////////////////////////////////////////////////////////////
2738+
2739+namespace zorba {
2740+namespace UnitTests {
2741+
2742+int test_time( int, char*[] ) {
2743+
2744+ test_calc_week_in_year();
2745+
2746+ cout << failures << " test(s) failed\n";
2747+ return failures ? 1 : 0;
2748+}
2749+
2750+} // namespace UnitTests
2751+} // namespace zorba
2752+/* vim:set et sw=2 ts=2: */
2753
2754=== modified file 'src/unit_tests/unit_test_list.h'
2755--- src/unit_tests/unit_test_list.h 2013-03-17 04:47:01 +0000
2756+++ src/unit_tests/unit_test_list.h 2013-03-21 16:00:34 +0000
2757@@ -41,6 +41,7 @@
2758 int test_mem_sizeof( int, char*[] );
2759 int test_parameters( int, char*[] );
2760 int test_string( int, char*[] );
2761+ int test_time( int, char*[] );
2762 int test_time_parse( int, char*[] );
2763
2764 #ifdef ZORBA_WITH_FILE_ACCESS
2765
2766=== modified file 'src/unit_tests/unit_tests.cpp'
2767--- src/unit_tests/unit_tests.cpp 2013-03-17 04:47:01 +0000
2768+++ src/unit_tests/unit_tests.cpp 2013-03-21 16:00:34 +0000
2769@@ -56,6 +56,7 @@
2770 libunittests["json_parser"] = test_json_parser;
2771 libunittests["parameters"] = test_parameters;
2772 libunittests["string"] = test_string;
2773+ libunittests["time"] = test_time;
2774 libunittests["time_parse"] = test_time_parse;
2775
2776 #ifndef ZORBA_NO_FULL_TEXT
2777
2778=== modified file 'src/util/ascii_util.h'
2779--- src/util/ascii_util.h 2013-03-19 04:22:49 +0000
2780+++ src/util/ascii_util.h 2013-03-21 16:00:34 +0000
2781@@ -22,6 +22,7 @@
2782 #include <cctype>
2783 #include <cstddef>
2784 #include <cstring>
2785+#include <iterator>
2786
2787 // local
2788 #include "omanip.h"
2789@@ -1147,9 +1148,62 @@
2790 *pos = trim_start_whitespace( s + *pos, s_len - *pos ) - s;
2791 }
2792
2793+/**
2794+ * Skips any consecutive whitespace chars that are found at a given starting
2795+ * position within a given string.
2796+ *
2797+ * @tparam StringType The string type.
2798+ * @param s The string.
2799+ * @param i A pointer to the iterator to advance past the whitespace.
2800+ * On return, \a *i is updated with the position of the 1st non-whitespace
2801+ * char.
2802+ */
2803+template<class StringType> inline
2804+void skip_whitespace( StringType const &s,
2805+ typename StringType::const_iterator *i ) {
2806+ typename StringType::difference_type const d = *i - s.begin();
2807+ char const *const sd = s.data() + d;
2808+ std::advance( *i, trim_start_whitespace( sd, s.size() - d ) - sd );
2809+}
2810+
2811 ////////// Miscellaneous //////////////////////////////////////////////////////
2812
2813 /**
2814+ * Pads a string to the left with a given character until the string is the
2815+ * given width.
2816+ *
2817+ * @param s The string to pad.
2818+ * @param width The width to pad to.
2819+ * @param c The character to pad with.
2820+ * @return Returns \c *s.
2821+ */
2822+template<class StringType> inline
2823+StringType& left_pad( StringType *s, typename StringType::size_type width,
2824+ char c ) {
2825+ typedef typename StringType::size_type size_type;
2826+ if ( s->size() < width )
2827+ s->insert( static_cast<size_type>( 0 ), width - s->size(), c );
2828+ return *s;
2829+}
2830+
2831+/**
2832+ * Pads a string to the right with a given character until the string is the
2833+ * given width.
2834+ *
2835+ * @param s The string to pad.
2836+ * @param width The width to pad to.
2837+ * @param c The character to pad with.
2838+ * @return Returns \c *s.
2839+ */
2840+template<class StringType> inline
2841+StringType& right_pad( StringType *s, typename StringType::size_type width,
2842+ char c ) {
2843+ if ( s->size() < width )
2844+ s->append( width - s->size(), c );
2845+ return *s;
2846+}
2847+
2848+/**
2849 * Prints the given character in a printable way: if \c is_print(c) is \c true,
2850 * prints \a c as-is; otherwise prints \c #x followed by the hexadecimal value
2851 * of the character.
2852
2853=== modified file 'src/util/stream_util.cpp'
2854--- src/util/stream_util.cpp 2013-03-16 20:44:27 +0000
2855+++ src/util/stream_util.cpp 2013-03-21 16:00:34 +0000
2856@@ -70,6 +70,37 @@
2857 return buf - buf_orig;
2858 }
2859
2860+ostream& roman( ostream &o, unsigned n ) {
2861+ //
2862+ // Based on http://rosettacode.org/wiki/Roman_numerals/Encode#C.2B.2B
2863+ //
2864+ struct roman_data {
2865+ unsigned value;
2866+ char const *numeral[2];
2867+ };
2868+ static roman_data const data[] = {
2869+ 1000, { "m", "M" },
2870+ 900, { "cm", "CM" },
2871+ 500, { "d", "D" },
2872+ 400, { "cd", "CD" },
2873+ 100, { "c", "C" },
2874+ 90, { "xc", "XC" },
2875+ 50, { "l", "L" },
2876+ 40, { "xl", "XL" },
2877+ 10, { "x", "X" },
2878+ 9, { "ix", "IX" },
2879+ 5, { "v", "V" },
2880+ 4, { "iv", "IV" },
2881+ 1, { "i", "I" },
2882+ 0, { 0, 0 }
2883+ };
2884+ bool const uc = !!(o.flags() & ios::uppercase);
2885+ for ( roman_data const *r = data; r->value > 0; ++r )
2886+ for ( ; n >= r->value; n -= r->value )
2887+ o << r->numeral[ uc ];
2888+ return o;
2889+}
2890+
2891 ///////////////////////////////////////////////////////////////////////////////
2892
2893 } // namespace zorba
2894
2895=== modified file 'src/util/stream_util.h'
2896--- src/util/stream_util.h 2013-03-16 20:44:27 +0000
2897+++ src/util/stream_util.h 2013-03-21 16:00:34 +0000
2898@@ -20,6 +20,7 @@
2899
2900 #include <iostream>
2901
2902+#include "omanip.h"
2903 #include "string_util.h"
2904
2905 namespace zorba {
2906@@ -73,6 +74,19 @@
2907 std::streamsize read_without_whitespace( std::istream &is, char *buf,
2908 std::streamsize n );
2909
2910+/**
2911+ * Emits an integer as Roman numerals to the given ostream. By default,
2912+ * numerals are emitted in lower-case. To emit in upper-case, set the
2913+ * \c uppercase format flag on the stream.
2914+ *
2915+ * @param o The ostream to emit to.
2916+ * @param n The integer to emit.
2917+ * @return Returns \a o.
2918+ */
2919+std::ostream& roman( std::ostream &o, unsigned n );
2920+
2921+DEF_OMANIP1( roman, unsigned )
2922+
2923 ///////////////////////////////////////////////////////////////////////////////
2924
2925 } // namespace zorba
2926
2927=== modified file 'src/util/time_util.cpp'
2928--- src/util/time_util.cpp 2013-02-13 01:57:47 +0000
2929+++ src/util/time_util.cpp 2013-03-21 16:00:34 +0000
2930@@ -16,7 +16,9 @@
2931
2932 #include "stdafx.h"
2933
2934+#include <algorithm>
2935 #include <cassert>
2936+#include <cstring>
2937 #ifdef WIN32
2938 # include <windows.h>
2939 # include <time.h> /* for gmtime_s() */
2940@@ -31,13 +33,138 @@
2941 #endif /* WIN32 */
2942
2943 // local
2944+#include "less.h"
2945 #include "time_util.h"
2946
2947+#define DEF_END(CHAR_ARRAY) \
2948+ static char const *const *const end = \
2949+ CHAR_ARRAY + sizeof( CHAR_ARRAY ) / sizeof( char* )
2950+
2951+#define FIND(WHAT) \
2952+ static_cast<type>( find_index( string_of, end, WHAT ) )
2953+
2954+using namespace std;
2955+
2956+/**
2957+ * A less-verbose way to use std::lower_bound.
2958+ */
2959+inline int find_index( char const *const *begin, char const *const *end,
2960+ char const *s ) {
2961+ char const *const *const entry =
2962+ ::lower_bound( begin, end, s, less<char const*>() );
2963+ return entry != end && ::strcmp( s, *entry ) == 0 ? entry - begin : 0;
2964+}
2965+
2966 namespace zorba {
2967 namespace time {
2968
2969 ///////////////////////////////////////////////////////////////////////////////
2970
2971+namespace iso8601 {
2972+ /**
2973+ * Weekday values as used by the ISO 8601 specification.
2974+ */
2975+ enum weekday {
2976+ mon = 1,
2977+ tue = 2,
2978+ wed = 3,
2979+ thu = 4,
2980+ fri = 5,
2981+ sat = 6,
2982+ sun = 7
2983+ };
2984+}
2985+
2986+namespace calendar {
2987+
2988+char const *const string_of[] = {
2989+ "#UNKNOWN",
2990+ "AD", // Anno Domini (Christian Era)
2991+ "AH", // Anno Hegirae (Muhammedan Era)
2992+ "AM", // Anno Mundi (Jewish)
2993+ "AME", // Mauludi Era (solar years since Mohammed's birth)
2994+ "AP", // Anno Persici
2995+ "AS", // Aji Saka Era (Java)
2996+ "BE", // Buddhist Era
2997+ "CB", // Cooch Behar Era
2998+ "CE", // Common Era
2999+ "CL", // Chinese Lunar Era
3000+ "CS", // Chula Sakarat Era
3001+ "EE", // Ethiopian Era
3002+ "FE", // Fasli Era
3003+ "ISO", // ISO 8601 calendar
3004+ "JE", // Japanese
3005+ "KE", // Khalsa Era (Sikh calendar)
3006+ "KY", // Kali Yuga
3007+ "ME", // Malabar Era
3008+ "MS", // Monarchic Solar Era
3009+ "OS", // Old Style (Julian)
3010+ "RS", // Rattanakosin (Bangkok) Era
3011+ "SE", // Saka Era
3012+ "SH", // Mohammedan Solar Era (Iran)
3013+ "SS", // Saka Samvat
3014+ "TE", // Tripurabda Era
3015+ "VE", // Vikrama Era
3016+ "VS" // Vikrama Samvat Era
3017+};
3018+
3019+int calc_week_in_year( unsigned mday, unsigned mon, unsigned year, type cal ) {
3020+ int yday = time::calc_yday( mday, mon, year );
3021+ int jan1_wday = time::calc_wday( 1, time::jan, year );
3022+
3023+ switch ( cal ) {
3024+ case AD:
3025+ return (jan1_wday + yday) / 7 + 1;
3026+ case ISO: {
3027+ // Based on http://www.personal.ecu.edu/mccartyr/ISOwdALG.txt
3028+ ++yday; // code assumes [1-366]
3029+ jan1_wday = convert_wday_to( jan1_wday, cal );
3030+
3031+ if ( jan1_wday > iso8601::thu && jan1_wday + yday <= 8 ) {
3032+ // date falls in week 52 or 53 of the previous year
3033+ return 52
3034+ + (jan1_wday == iso8601::fri ||
3035+ (jan1_wday == iso8601::sat && time::is_leap_year( year - 1 )));
3036+ }
3037+ int const wday =
3038+ convert_wday_to( time::calc_wday( mday, mon, year ), cal );
3039+ if ( time::days_in_year( year ) - yday < 4 - wday ) {
3040+ // date falls in week 1 of the next year
3041+ return 1;
3042+ }
3043+ return (yday + (7 - wday) + (jan1_wday - 1)) / 7
3044+ - (jan1_wday > iso8601::thu);
3045+ }
3046+ default:
3047+ return -1;
3048+ }
3049+}
3050+
3051+int convert_wday_from( unsigned wday, type from ) {
3052+ switch ( from ) {
3053+ case AD : return static_cast<int>( wday );
3054+ case ISO: return wday == iso8601::sun ? time::sun : wday;
3055+ default : return -1;
3056+ }
3057+}
3058+
3059+int convert_wday_to( unsigned wday, type to ) {
3060+ switch ( to ) {
3061+ case AD : return static_cast<int>( wday );
3062+ case ISO: return wday == time::sun ? iso8601::sun : wday;
3063+ default : return -1;
3064+ }
3065+}
3066+
3067+type find( char const *calendar ) {
3068+ DEF_END( string_of );
3069+ return FIND( calendar );
3070+}
3071+
3072+} // namespace calendar
3073+
3074+///////////////////////////////////////////////////////////////////////////////
3075+
3076 static unsigned const yday_mon[][13] = {
3077 // 0 1 2 3 4 5 6 7 8 9 10 11 12
3078 { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 }, // non-leap
3079@@ -48,7 +175,7 @@
3080
3081 bool calc_mday_mon( unsigned yday, unsigned *mday, unsigned *mon,
3082 unsigned year ) {
3083- assert( yday < 365 + is_leap_year( year ) );
3084+ assert( yday < days_in_year( year ) );
3085
3086 unsigned const *const ym = yday_mon[ is_leap_year( year ) ];
3087 for ( unsigned m = 1; m <= 12; ++m )
3088@@ -102,31 +229,31 @@
3089 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
3090 * USE OR OTHER DEALINGS IN THE SOFTWARE.
3091 *
3092- * @param mday Month day: 1-31.
3093- * @param mon Month: 0-11.
3094- * @param year Year.
3095- * @return Returns the weekday where 0 = Sunday.
3096+ * @param mday The month day [1-31].
3097+ * @param mon The month [0-11].
3098+ * @param year The year.
3099+ * @return Returns the weekday [0-6] where 0 = Sunday.
3100 */
3101-unsigned calc_wday( unsigned mday, unsigned mon, unsigned year ) {
3102+int calc_wday( unsigned mday, unsigned mon, unsigned year ) {
3103 assert( mday >= 1 );
3104 assert( mday <= days_in_month( mon, year ) );
3105 assert( mon < 12 );
3106
3107 ++mon; // Tondering's algorithm assumes month value in range 1-12.
3108- unsigned const a = (14 - mon) / 12;
3109- unsigned const y = year - a;
3110- unsigned const m = mon + 12 * a - 2;
3111+ int const a = (14 - mon) / 12;
3112+ int const y = year - a;
3113+ int const m = mon + 12 * a - 2;
3114 return (mday + y + y/4 - y/100 + y/400 + (31 * m) / 12) % 7;
3115 }
3116
3117-unsigned calc_yday( unsigned mday, unsigned mon, unsigned year ) {
3118+int calc_yday( unsigned mday, unsigned mon, unsigned year ) {
3119 assert( mday >= 1 );
3120 assert( mday <= days_in_month( mon, year ) );
3121- return yday_mon[ is_leap_year( year ) ][ mon ] + mday - 1;
3122+ return (int)yday_mon[ is_leap_year( year ) ][ mon ] + mday - 1;
3123 }
3124
3125-unsigned days_in_month( unsigned mon, unsigned year ) {
3126- static unsigned const days[] = {
3127+int days_in_month( unsigned mon, unsigned year ) {
3128+ static int const days[] = {
3129 31, // 0: Jan
3130 28, // 1: Feb
3131 31, // 2: Mar
3132@@ -141,7 +268,7 @@
3133 31 // 11: Dec
3134 };
3135 assert( mon < 12 );
3136- return days[ mon ] + (mon == 1 /* Feb */ && is_leap_year( year ));
3137+ return days[ mon ] + (mon == feb && is_leap_year( year ));
3138 }
3139
3140 void get_epoch( sec_type *sec, usec_type *usec ) {
3141@@ -202,6 +329,17 @@
3142 #endif /* WIN32 */
3143 }
3144
3145+char get_military_tz( int hour ) {
3146+ hour %= 24;
3147+ if ( hour > 12 )
3148+ hour -= 24;
3149+ else if ( hour < -12 )
3150+ hour += 24;
3151+ if ( hour >= 0 && hour <= 12 )
3152+ return "ZABCDEFGHIKLM" [ hour ]; // no 'J' here (it means "no timezone")
3153+ return " NOPQRSTUVWXY" [ -hour ];
3154+}
3155+
3156 ///////////////////////////////////////////////////////////////////////////////
3157
3158 } // namespace time
3159
3160=== modified file 'src/util/time_util.h'
3161--- src/util/time_util.h 2013-02-13 01:57:47 +0000
3162+++ src/util/time_util.h 2013-03-21 16:00:34 +0000
3163@@ -25,7 +25,9 @@
3164
3165 // Zorba
3166 #include <zorba/config.h>
3167+#include <zorba/time.h>
3168 #include "cxx_util.h"
3169+#include "string_util.h"
3170
3171 #ifndef TM_YEAR_BASE
3172 # define TM_YEAR_BASE 1900
3173@@ -36,14 +38,22 @@
3174
3175 ///////////////////////////////////////////////////////////////////////////////
3176
3177+/**
3178+ * A type to hold a number of seconds (at least since epoch).
3179+ */
3180 typedef time_t sec_type;
3181
3182+/**
3183+ * A type to hold a number of microseconds.
3184+ */
3185 #ifdef WIN32
3186 typedef unsigned long usec_type;
3187 #else
3188 typedef suseconds_t usec_type;
3189 #endif /* WIN32 */
3190
3191+///////////////////////////////////////////////////////////////////////////////
3192+
3193 //
3194 // If the OS's tm struct has a GMT-timezone offset field, simply typedef tm as
3195 // ztm; otherwise declare ztm as a struct derived from tm that adds a
3196@@ -71,12 +81,129 @@
3197 ///////////////////////////////////////////////////////////////////////////////
3198
3199 /**
3200+ * XQuery 3.0 F&O: 9.8.4.3: The calendars listed below were known to be in use
3201+ * during the last hundred years.
3202+ */
3203+namespace calendar {
3204+ extern char const* const string_of[];
3205+
3206+ /**
3207+ * Emits a calendar::type to an ostream.
3208+ *
3209+ * @param o The ostream to emit to.
3210+ * @param t The type to emit.
3211+ * @return Returns \a o.
3212+ */
3213+ inline std::ostream& operator<<( std::ostream &o, type t ) {
3214+ return o << string_of[ t ];
3215+ }
3216+
3217+ /**
3218+ * Calculates the week number for the given date and calendar.
3219+ *
3220+ * @param mday The month day [1-31].
3221+ * @param mon The month [0-11].
3222+ * @param year The year.
3223+ * @param cal The calendar.
3224+ * @return Returns the week [1-53] or -1 if it is unknown how to perform the
3225+ * calculation for \a cal.
3226+ */
3227+ int calc_week_in_year( unsigned mday, unsigned mon, unsigned year, type cal );
3228+
3229+ /**
3230+ * Converts a weekday number from a given calendar to the Unix interpretation
3231+ * [0-6] where 0 = Sunday.
3232+ *
3233+ * @param wday The weekday to convert where the meaning of the value is
3234+ * determined by \a from.
3235+ * @param from The calendar designator to convert \a wday from.
3236+ * @return Returns \a wday converted to \a to or -1 if it is unknown how to
3237+ * perform the conversion.
3238+ */
3239+ int convert_wday_from( unsigned wday, type from );
3240+
3241+ /**
3242+ * Converts a Unix weekday number to a specific calendar.
3243+ *
3244+ * @param wday The weekday to convert: [0-6] where 0 = Sunday.
3245+ * @param to The calendar designator to convert \a wday to.
3246+ * @return Returns \a wday converted to \a to or -1 if it is unknown how to
3247+ * perform the conversion.
3248+ */
3249+ int convert_wday_to( unsigned wday, type to );
3250+
3251+ /**
3252+ * Finds a calendar designator from the given string.
3253+ *
3254+ * @param calendar The calendar designator to find. It is presumed to be in
3255+ * upper-case.
3256+ * @return Returns said enumeration or \c unknown.
3257+ */
3258+ type find( char const *calendar );
3259+
3260+ //
3261+ // Template version of find().
3262+ //
3263+ template<class StringType> inline
3264+ typename std::enable_if<
3265+ ztd::has_c_str<StringType,char const* (StringType::*)() const>::value,
3266+ type
3267+ >::type
3268+ find( StringType const &calendar ) {
3269+ return find( calendar.c_str() );
3270+ }
3271+
3272+ /**
3273+ * Gets the default calendar to use.
3274+ *
3275+ * @return Returns said calendar.
3276+ */
3277+ inline type get_default() {
3278+ return AD; // i.e., the Gregorian calendar
3279+ }
3280+
3281+} // namespace calendar
3282+
3283+///////////////////////////////////////////////////////////////////////////////
3284+
3285+/**
3286+ * Month (<code>mod</code>) values as used by the \c tm structure.
3287+ */
3288+enum month {
3289+ jan = 0,
3290+ feb = 1,
3291+ mar = 2,
3292+ apr = 3,
3293+ may = 4,
3294+ jun = 5,
3295+ jul = 6,
3296+ aug = 7,
3297+ sep = 8,
3298+ oct = 9,
3299+ nov = 10,
3300+ dec = 11
3301+};
3302+
3303+/**
3304+ * Weekday (<code>wday</code>) values as used by the \c tm structure.
3305+ */
3306+enum weekday {
3307+ sun = 0,
3308+ mon = 1,
3309+ tue = 2,
3310+ wed = 3,
3311+ thu = 4,
3312+ fri = 5,
3313+ sat = 6
3314+};
3315+
3316+/**
3317 * Calculates the day of the month and month from the given day of the year.
3318 *
3319- * @param yday The year day (0-365) where 0 = January 1.
3320- * @param mday A pointer to the result for the month day (1-31) or \c null if
3321+ * @param yday The year day [0-365] where 0 = January 1.
3322+ * @param mday A pointer to the result for the month day [1-31] or \c null if
3323 * this is not desired.
3324- * @param mon A pointer to the result for the month (0-11) or \c null if this
3325+ * @param mon A pointer to the result for the month [0-11] or \c null if this
3326 * is not desired.
3327 * @param year The year.
3328 * @return Returns \c true if \a yday and \a year are a valid combination and
3329@@ -88,31 +215,31 @@
3330 /**
3331 * Calculates the weekday for the given date.
3332 *
3333- * @param mday The month day (1-31).
3334- * @param mon The month (0-11).
3335+ * @param mday The month day [1-31].
3336+ * @param mon The month [0-11].
3337 * @param year The year.
3338- * @return Returns the weekday (0-6) where 0 = Sunday.
3339+ * @return Returns the weekday [0-6] where 0 = Sunday.
3340 */
3341-unsigned calc_wday( unsigned mday, unsigned mon, unsigned year );
3342+int calc_wday( unsigned mday, unsigned mon, unsigned year );
3343
3344 /**
3345 * Calculates the day of the year for the given date.
3346 *
3347- * @param mday The month day (1-31).
3348- * @param mon The month (0-11).
3349+ * @param mday The month day [1-31].
3350+ * @param mon The month [0-11].
3351 * @param year The year.
3352- * @return Returns the day of the year (0-365) where 0 = January 1.
3353+ * @return Returns the day of the year [0-365] where 0 = January 1.
3354 */
3355-unsigned calc_yday( unsigned mday, unsigned mon, unsigned year );
3356+int calc_yday( unsigned mday, unsigned mon, unsigned year );
3357
3358 /**
3359 * Gets the number of days in the given month.
3360 *
3361- * @param mon The month (0-11).
3362+ * @param mon The month [0-11].
3363 * @param year The year.
3364- * @return Returns said number of days (1-31).
3365+ * @return Returns said number of days, one of: 28, 29, 30, or 31.
3366 */
3367-unsigned days_in_month( unsigned mon, unsigned year );
3368+int days_in_month( unsigned mon, unsigned year );
3369
3370 /**
3371 * Gets the number of seconds and microseconds since epoch.
3372@@ -150,6 +277,14 @@
3373 void get_localtime( ztm *tm, sec_type when = 0 );
3374
3375 /**
3376+ * Gets the military timezone letter code for the given GMT hour offset.
3377+ *
3378+ * @param hour The number of hours offset from GMT.
3379+ * @return Returns one of ABCDEFGHIKLMNOPQRSTUVWXYZ (no J).
3380+ */
3381+char get_military_tz( int hour );
3382+
3383+/**
3384 * Checks whether the given year is a leap year.
3385 *
3386 * @param year The year to check.
3387@@ -160,43 +295,53 @@
3388 }
3389
3390 /**
3391+ * Gets the number of days in the given year.
3392+ *
3393+ * @param year The year.
3394+ * @return Returns said number of days, either: 365 or 366.
3395+ */
3396+inline int days_in_year( unsigned year ) {
3397+ return 365 + is_leap_year( year );
3398+}
3399+
3400+/**
3401 * Checks whether the given day of the month is valid.
3402 *
3403- * @param mday The month day (1-31).
3404- * @param mon The month (0-11).
3405+ * @param mday The month day [1-31].
3406+ * @param mon The month [0-11].
3407 * @param year The year.
3408 * @return Returns \a true only if the given day of the month is valid.
3409 */
3410 inline bool is_mday_valid( unsigned mday, unsigned mon, unsigned year ) {
3411- return mday >= 1 && mday <= days_in_month( mon, year );
3412+ return mday >= 1 && (int)mday <= days_in_month( mon, year );
3413 }
3414
3415 /**
3416 * Checks whether the given weekday is valid.
3417 *
3418- * @param wday The weekday (0-6) where 0 = Sunday.
3419- * @param mday The month day (1-31).
3420- * @param mon The month (0-11).
3421+ * @param wday The weekday [0-6] where 0 = Sunday.
3422+ * @param mday The month day [1-31].
3423+ * @param mon The month [0-11].
3424 * @param year The year.
3425 * @return Returns \a true only if the given weekday is valid.
3426 */
3427 inline bool is_wday_valid( unsigned wday, unsigned mday, unsigned mon,
3428 unsigned year ) {
3429- return wday == calc_wday( mday, mon, year );
3430+ return (int)wday == calc_wday( mday, mon, year );
3431 }
3432
3433 /**
3434 * Checks whether the given day of the year is valid.
3435 *
3436- * @param yday The day of the year (0-365).
3437- * @param mday The month day (1-31).
3438- * @param mon The month (0-11).
3439+ * @param yday The day of the year [0-365].
3440+ * @param mday The month day [1-31].
3441+ * @param mon The month [0-11].
3442 * @param year The year.
3443 * @return Returns \a true only if the given day of the year is valid.
3444 */
3445 inline bool is_yday_valid( unsigned yday, unsigned mday, unsigned mon,
3446 unsigned year ) {
3447- return yday == calc_yday( mday, mon, year );
3448+ return (int)yday == calc_yday( mday, mon, year );
3449 }
3450
3451 ///////////////////////////////////////////////////////////////////////////////
3452
3453=== modified file 'src/util/unicode_util.cpp'
3454--- src/util/unicode_util.cpp 2013-02-07 17:24:36 +0000
3455+++ src/util/unicode_util.cpp 2013-03-21 16:00:34 +0000
3456@@ -28,6 +28,7 @@
3457 # include <unicode/ustring.h>
3458 #endif /* ZORBA_NO_ICU */
3459
3460+#include "ascii_util.h"
3461 #include "cxx_util.h"
3462 #include "unicode_util.h"
3463 #include "utf8_util.h"
3464@@ -2205,6 +2206,23 @@
3465 return is_case<upper>( c );
3466 }
3467
3468+ostream& printable_cp( ostream &o, code_point cp ) {
3469+ if ( ascii::is_print( cp ) )
3470+ o << static_cast<char>( cp );
3471+ else
3472+ switch ( cp ) {
3473+ case '\n': o << "\\n"; break;
3474+ case '\r': o << "\\r"; break;
3475+ case '\t': o << "\\t"; break;
3476+ default: {
3477+ ios::fmtflags const old_flags = o.flags();
3478+ o << "#x" << uppercase << hex << static_cast<uint32_t>( cp );
3479+ o.flags( old_flags );
3480+ }
3481+ }
3482+ return o;
3483+}
3484+
3485 code_point to_lower( code_point c ) {
3486 return to_case<lower>( c );
3487 }
3488
3489=== modified file 'src/util/unicode_util.h'
3490--- src/util/unicode_util.h 2013-02-28 11:15:32 +0000
3491+++ src/util/unicode_util.h 2013-03-21 16:00:34 +0000
3492@@ -32,6 +32,7 @@
3493 # include <unicode/unistr.h>
3494 #endif /* ZORBA_NO_ICU */
3495
3496+#include "omanip.h"
3497 #include "stl_util.h"
3498
3499 namespace zorba {
3500@@ -426,6 +427,22 @@
3501 return c >= 0x10000 && c <= 0x10FFFF;
3502 }
3503
3504+////////// Miscellaneous //////////////////////////////////////////////////////
3505+
3506+/**
3507+ * Prints the given code-point in a printable way: if \c ascii::is_print(c) is
3508+ * \c true, prints \a c as-is; otherwise prints \c #x followed by the
3509+ * hexadecimal value of the character.
3510+ *
3511+ * @param o The ostream to print to.
3512+ * @param cp The \c code-point to print.
3513+ * @return Returns \a o.
3514+ */
3515+std::ostream& printable_cp( std::ostream &o, code_point cp );
3516+
3517+// An ostream manipulator version of the above.
3518+DEF_OMANIP1( printable_cp, code_point )
3519+
3520 ///////////////////////////////////////////////////////////////////////////////
3521
3522 } // namespace unicode
3523
3524=== modified file 'src/util/utf8_string.h'
3525--- src/util/utf8_string.h 2013-02-07 17:24:36 +0000
3526+++ src/util/utf8_string.h 2013-03-21 16:00:34 +0000
3527@@ -207,8 +207,12 @@
3528 typedef typename StringType::const_pointer const_storage_pointer;
3529 typedef typename StringType::reference storage_reference;
3530 typedef typename StringType::const_reference const_storage_reference;
3531+
3532 typedef typename StringType::iterator storage_iterator;
3533 typedef typename StringType::const_iterator const_storage_iterator;
3534+ typedef typename StringType::reverse_iterator storage_reverse_iterator;
3535+ typedef typename StringType::const_reverse_iterator
3536+ const_storage_reverse_iterator;
3537
3538 typedef typename utf8::iterator<storage_iterator> iterator;
3539 typedef typename utf8::iterator<const_storage_iterator> const_iterator;
3540@@ -1005,6 +1009,16 @@
3541 }
3542
3543 /**
3544+ * Returns a read-only iterator positioned at the same byte as the given
3545+ * iterator of the string.
3546+ *
3547+ * @return Returns said iterator.
3548+ */
3549+ const_iterator current( const_storage_iterator const &i ) const {
3550+ return const_iterator( i );
3551+ }
3552+
3553+ /**
3554 * Returns a read-only reverse iterator positioned at the first character
3555 * (not byte) of the string.
3556 *
3557@@ -1024,6 +1038,17 @@
3558 return const_reverse_iterator( begin() );
3559 }
3560
3561+ /**
3562+ * Returns a read-only reverse iterator positioned at the same byte as the
3563+ * given reverse iterator of the string.
3564+ *
3565+ * @return Returns said iterator.
3566+ */
3567+ const_reverse_iterator
3568+ current( const_storage_reverse_iterator const &i ) const {
3569+ return const_reverse_iterator( i );
3570+ }
3571+
3572 ////////// miscellaneous ////////////////////////////////////////////////////
3573
3574 /**
3575
3576=== modified file 'src/util/utf8_util.cpp'
3577--- src/util/utf8_util.cpp 2013-02-07 17:24:36 +0000
3578+++ src/util/utf8_util.cpp 2013-03-21 16:00:34 +0000
3579@@ -15,6 +15,9 @@
3580 */
3581 #include "stdafx.h"
3582
3583+#include <algorithm>
3584+#include <cstring>
3585+
3586 #ifndef ZORBA_NO_ICU
3587 #include <unicode/ustring.h>
3588 #endif /* ZORBA_NO_ICU */
3589@@ -144,6 +147,35 @@
3590 return len;
3591 }
3592
3593+storage_type* itou( unsigned long long n, storage_type *buf,
3594+ unicode::code_point zero ) {
3595+ storage_type *s = buf;
3596+ encoded_char_type utf8_digit[10]; // cache of UTF-8 bytes for each digit
3597+ size_type utf8_size[10]; // number of UTF-8 bytes for each digit
3598+
3599+ std::fill( utf8_size, utf8_size + 10, 0 );
3600+ do {
3601+ unsigned long long const n_prev = n;
3602+ n /= 10;
3603+ unsigned const digit = n_prev - n * 10;
3604+ if ( !utf8_size[ digit ] ) // didn't cache previously: cache now
3605+ utf8_size[ digit ] = encode( zero + digit, utf8_digit[ digit ] );
3606+ //
3607+ // Copy the UTF-8 bytes into buf backwards so when we reverse the entire
3608+ // buffer later (to reverse the digit order to put them the right way
3609+ // around), we can treat buf as a simple string and ignore multi-byte UTF-8
3610+ // character boundaries.
3611+ //
3612+ for ( size_type i = utf8_size[ digit ]; i; )
3613+ *s++ = utf8_digit[ digit ][ --i ];
3614+
3615+ } while ( n );
3616+
3617+ *s = '\0';
3618+ std::reverse( buf, s );
3619+ return buf;
3620+}
3621+
3622 size_type length( storage_type const *begin, storage_type const *end ) {
3623 size_type len = 0;
3624 while ( begin < end && *begin ) {
3625
3626=== modified file 'src/util/utf8_util.h'
3627--- src/util/utf8_util.h 2013-02-07 17:24:36 +0000
3628+++ src/util/utf8_util.h 2013-03-21 16:00:34 +0000
3629@@ -306,6 +306,31 @@
3630 std::copy( u.begin(), u.end(), std::back_inserter( *c ) );
3631 }
3632
3633+////////// Integer-to-string conversion ///////////////////////////////////////
3634+
3635+/**
3636+ * A type that can hold the largest possible C string equivalent of the largest
3637+ * possible integral value using any Unicode numeric range within the Nd
3638+ * ("Number, Decimal Digit") category.
3639+ */
3640+typedef storage_type itou_buf_type[
3641+ (sizeof( encoded_char_type ) - 1 /* subtract null */) * 20 + 1 /* add null */
3642+];
3643+
3644+/**
3645+ * Converts an <code>unsigned long long</code> to a UTF-8 encoded string.
3646+ *
3647+ * @param n The <code>unsigned long long</code> to convert.
3648+ * @param buf The buffer for the result. The caller must ensure it's of
3649+ * sufficient size.
3650+ * @param zero The Unicode code-point of the zero at the start of a 10
3651+ * code-point range [zero,zero+9] for the digits to use in the Nd ("Number,
3652+ * Decimal Digit") category.
3653+ * @return Returns \a buf for convenience.
3654+ */
3655+storage_type* itou( unsigned long long n, storage_type *buf,
3656+ unicode::code_point zero );
3657+
3658 ////////// Encoding conversion ////////////////////////////////////////////////
3659
3660 #ifndef ZORBA_NO_ICU
3661@@ -737,6 +762,48 @@
3662 ////////// Miscellaneous //////////////////////////////////////////////////////
3663
3664 /**
3665+ * Pads a string to the left with a given code-point until the string is the
3666+ * given width.
3667+ *
3668+ * @param s The string to pad.
3669+ * @param width The width to pad to.
3670+ * @param cp The code-point to pad with.
3671+ * @return Returns \c *s.
3672+ */
3673+template<class StringType> inline
3674+StringType& left_pad( StringType *s, typename StringType::size_type width,
3675+ unicode::code_point cp ) {
3676+ typedef typename utf8_stringify<StringType>::type u_type;
3677+ typedef typename u_type::size_type u_size_type;
3678+ u_type u( *s );
3679+ u_size_type const u_size( u.size() );
3680+ if ( u_size < width )
3681+ u.insert( static_cast<size_type>( 0 ), width - u_size, cp );
3682+ return *s;
3683+}
3684+
3685+/**
3686+ * Pads a string to the right with a given code-point until the string is the
3687+ * given width.
3688+ *
3689+ * @param s The string to pad.
3690+ * @param width The width to pad to.
3691+ * @param cp The code-point to pad with.
3692+ * @return Returns \c *s.
3693+ */
3694+template<class StringType> inline
3695+StringType& right_pad( StringType *s, typename StringType::size_type width,
3696+ unicode::code_point cp ) {
3697+ typedef typename utf8_stringify<StringType>::type u_type;
3698+ typedef typename u_type::size_type u_size_type;
3699+ u_type u( *s );
3700+ u_size_type const u_size( u.size() );
3701+ if ( u_size < width )
3702+ u.append( width - u_size, cp );
3703+ return *s;
3704+}
3705+
3706+/**
3707 * Reverses the characters in a string.
3708 *
3709 * @tparam InputStringType The input string type.
3710
3711=== modified file 'src/zorbatypes/datetime.h'
3712--- src/zorbatypes/datetime.h 2013-03-12 17:03:31 +0000
3713+++ src/zorbatypes/datetime.h 2013-03-21 16:00:34 +0000
3714@@ -250,16 +250,10 @@
3715 */
3716 static int parseGDay(const char* str, ascii::size_type strlen, DateTime& dt);
3717
3718- static int getDayOfWeek(int year, int month, int day);
3719-
3720 static int getDayOfYear(int year, int month, int day);
3721
3722- static int getWeekInYear(int year, int month, int day);
3723-
3724 static int getWeekInMonth(int year, int month, int day);
3725
3726- static bool isLeapYear(int year);
3727-
3728 protected:
3729 static int parse_date(
3730 const char* str,
3731@@ -361,11 +355,8 @@
3732 * with the index being 0 based, with 0 being Sunday, 1 Monday, etc. If the give
3733 * DateTime does not have a Date or DateTime facet, the function will return -1.
3734 */
3735- int getDayOfWeek() const;
3736 int getDayOfYear() const;
3737- int getWeekInYear() const;
3738 int getWeekInMonth() const;
3739- bool isLeapYear() const;
3740
3741 protected:
3742 Duration* toDayTimeDuration() const;
3743
3744=== modified file 'src/zorbatypes/datetime/datetimetype.cpp'
3745--- src/zorbatypes/datetime/datetimetype.cpp 2013-03-12 17:03:31 +0000
3746+++ src/zorbatypes/datetime/datetimetype.cpp 2013-03-21 16:00:34 +0000
3747@@ -39,6 +39,7 @@
3748 #include "zorbatypes/datetime/parse.h"
3749
3750 #include "util/ascii_util.h"
3751+#include "util/time_util.h"
3752
3753
3754 namespace zorba
3755@@ -47,7 +48,7 @@
3756 static const char separators[] = { '-', '-', 'T', ':', ':', '.'};
3757
3758 static const char min_length[] = { 4, 2, 2, 2, 2, 2, 0};
3759-
3760+
3761
3762 const int DateTime::FACET_MEMBERS[][8] =
3763 {
3764@@ -79,7 +80,7 @@
3765
3766 for (int i = YEAR_DATA; i <= DAY_DATA; i++)
3767 data[i] = 1;
3768-
3769+
3770 for (int i = HOUR_DATA; i <= FRACSECONDS_DATA; i++)
3771 data[i] = 0;
3772
3773@@ -158,10 +159,10 @@
3774 dt.data[MINUTE_DATA] = std::abs(minutes);
3775 dt.data[SECONDS_DATA] = std::floor(std::fabs(seconds));
3776 dt.data[FRACSECONDS_DATA] = round(frac(std::fabs(seconds)) * FRAC_SECONDS_UPPER_LIMIT);
3777-
3778+
3779 if (tz != NULL)
3780 dt.the_time_zone = *tz;
3781-
3782+
3783 return 0;
3784 }
3785
3786@@ -185,7 +186,7 @@
3787 dt.data[MINUTE_DATA] = std::abs(minutes);
3788 dt.data[SECONDS_DATA] = std::abs(seconds);
3789 dt.data[FRACSECONDS_DATA] = std::abs(fractional_seconds);
3790-
3791+
3792 if (tz != NULL)
3793 dt.the_time_zone = *tz;
3794
3795@@ -211,7 +212,7 @@
3796
3797 if (tz != NULL)
3798 dt.the_time_zone = *tz;
3799-
3800+
3801 return 0;
3802 }
3803
3804@@ -231,10 +232,10 @@
3805 dt.data[MINUTE_DATA] = std::abs(minutes);
3806 dt.data[SECONDS_DATA] = std::floor(std::fabs(seconds));
3807 dt.data[FRACSECONDS_DATA] = round(frac(std::fabs(seconds)) * FRAC_SECONDS_UPPER_LIMIT);
3808-
3809+
3810 if (tz != NULL)
3811 dt.the_time_zone = *tz;
3812-
3813+
3814 return 0;
3815 }
3816
3817@@ -352,7 +353,7 @@
3818 ascii::skip_whitespace(str, len, &pos);
3819
3820 dt.facet = DATETIME_FACET;
3821-
3822+
3823 if (parse_date(str,
3824 len,
3825 pos,
3826@@ -363,7 +364,7 @@
3827
3828 if (pos == len || str[pos++] != 'T')
3829 return 1;
3830-
3831+
3832 if (parse_time(str,
3833 len,
3834 pos,
3835@@ -372,7 +373,7 @@
3836 dt.data[SECONDS_DATA],
3837 dt.data[FRACSECONDS_DATA]))
3838 return 1;
3839-
3840+
3841 ascii::size_type savepos = pos;
3842
3843 ascii::skip_whitespace(str, len, &pos);
3844@@ -387,7 +388,7 @@
3845 dt.the_time_zone))
3846 return 1;
3847 }
3848-
3849+
3850 if (dt.data[HOUR_DATA] == 24)
3851 {
3852 dt.data[HOUR_DATA] = 0;
3853@@ -408,7 +409,7 @@
3854 ascii::skip_whitespace(str, len, &pos);
3855
3856 dt.facet = DATE_FACET;
3857-
3858+
3859 if (parse_date(str,
3860 len,
3861 pos,
3862@@ -429,7 +430,7 @@
3863 if (0 != TimeZone::parseTimeZone(str + pos, len - pos, dt.the_time_zone))
3864 return 1;
3865 }
3866-
3867+
3868 return 0;
3869 }
3870
3871@@ -441,14 +442,14 @@
3872 ascii::skip_whitespace(str, len, &pos);
3873
3874 dt.facet = TIME_FACET;
3875-
3876+
3877 if (parse_time(str, len, pos,
3878 dt.data[HOUR_DATA],
3879 dt.data[MINUTE_DATA],
3880 dt.data[SECONDS_DATA],
3881 dt.data[FRACSECONDS_DATA]))
3882 return 1;
3883-
3884+
3885 ascii::size_type savepos = pos;
3886
3887 ascii::skip_whitespace(str, len, &pos);
3888@@ -461,7 +462,7 @@
3889 if (0 != TimeZone::parseTimeZone(str + pos, len - pos, dt.the_time_zone))
3890 return 1;
3891 }
3892-
3893+
3894 if (dt.data[HOUR_DATA] == 24)
3895 dt.data[HOUR_DATA] = 0;
3896
3897@@ -476,11 +477,11 @@
3898 zstring temp;
3899
3900 // GYearMonth of form: '-'? yyyy '-' mm zzzzzz?
3901-
3902+
3903 ascii::skip_whitespace(str, len, &pos);
3904
3905 dt.facet = GYEARMONTH_FACET;
3906-
3907+
3908 if (str[pos] == '-')
3909 {
3910 temp.append(str + pos, (8 < len - pos ? 8 : len - pos));
3911@@ -500,7 +501,7 @@
3912 dt.data[MONTH_DATA],
3913 dt.data[DAY_DATA]))
3914 return 1;
3915-
3916+
3917 pos += 7;
3918
3919 ascii::size_type savepos = pos;
3920@@ -527,11 +528,11 @@
3921 zstring temp;
3922
3923 // GYear of form: '-'? yyyy zzzzzz?
3924-
3925+
3926 ascii::skip_whitespace(str, len, &pos);
3927
3928 dt.facet = GYEAR_FACET;
3929-
3930+
3931 temp.reserve(12);
3932
3933 if (str[pos] == '-')
3934@@ -553,7 +554,7 @@
3935 dt.data[MONTH_DATA],
3936 dt.data[DAY_DATA]))
3937 return 1;
3938-
3939+
3940 pos += 4;
3941
3942 ascii::size_type savepos = pos;
3943@@ -581,11 +582,11 @@
3944
3945 // GMonth of form: --MM zzzzzz?
3946 // preceding - is not allowed.
3947-
3948+
3949 ascii::skip_whitespace(str, len, &pos);
3950
3951 dt.facet = GMONTH_FACET;
3952-
3953+
3954 if (str[pos++] != '-')
3955 return 1;
3956
3957@@ -601,7 +602,7 @@
3958 dt.data[MONTH_DATA],
3959 dt.data[DAY_DATA]))
3960 return 1;
3961-
3962+
3963 pos += 3;
3964
3965 ascii::size_type savepos = pos;
3966@@ -633,10 +634,10 @@
3967 ascii::skip_whitespace(str, len, &pos);
3968
3969 dt.facet = GMONTHDAY_FACET;
3970-
3971+
3972 if (str[pos++] != '-')
3973 return 1;
3974-
3975+
3976 temp.reserve(12);
3977 temp = "0004";
3978 temp.append(str + pos, 6); // Year 4 to make it a leap year, to allow the MonthDay of 29 February
3979@@ -650,7 +651,7 @@
3980 return 1;
3981
3982 dt.data[YEAR_DATA] = 1;
3983-
3984+
3985 pos += 6;
3986
3987 ascii::size_type savepos = pos;
3988@@ -678,17 +679,17 @@
3989
3990 // GDay of form: ---DD zzzzzz?
3991 // preceding - is not allowed.
3992-
3993+
3994 ascii::skip_whitespace(str, len, &pos);
3995
3996 dt.facet = GDAY_FACET;
3997-
3998- if (str[pos++] != '-')
3999- return 1;
4000-
4001- if (str[pos++] != '-')
4002- return 1;
4003-
4004+
4005+ if (str[pos++] != '-')
4006+ return 1;
4007+
4008+ if (str[pos++] != '-')
4009+ return 1;
4010+
4011 temp = "0001-01";
4012 temp.append(str + pos, 3);
4013
4014@@ -699,7 +700,7 @@
4015 dt.data[MONTH_DATA],
4016 dt.data[DAY_DATA]))
4017 return 1;
4018-
4019+
4020 pos += 3;
4021
4022 ascii::size_type savepos = pos;
4023@@ -730,7 +731,7 @@
4024 {
4025 bool is_negative = false;
4026 ascii::size_type temp_pos;
4027-
4028+
4029 if (pos == len)
4030 return 1;
4031
4032@@ -765,18 +766,18 @@
4033 // Parse day
4034 if (pos == len || parse_long(str, len, pos, day, 2, 2))
4035 return 1;
4036-
4037+
4038 // Validate the date
4039 // year may not be 0
4040 if (year == 0)
4041 return 1;
4042-
4043+
4044 if (month < 1 || month > 12)
4045 return 1;
4046
4047 if (day < 1 || day > get_last_day(year, month))
4048 return 1;
4049-
4050+
4051 return 0;
4052 }
4053
4054@@ -793,7 +794,7 @@
4055 {
4056 if (position == len)
4057 return 1;
4058-
4059+
4060 // Parse hour
4061 if (position == len || parse_long(str, len, position, hour, 2, 2))
4062 return 1;
4063@@ -811,7 +812,7 @@
4064 // Parse seconds
4065 if (position == len || parse_long(str, len, position, seconds, 2, 2))
4066 return 1;
4067-
4068+
4069 if (position < len && str[position] == '.')
4070 {
4071 double temp_frac_seconds;
4072@@ -830,19 +831,19 @@
4073 // Validate the time
4074 if (hour > 24)
4075 return 1;
4076-
4077+
4078 if (minute > 59)
4079 return 1;
4080
4081 if (hour == 24 && minute != 0)
4082 return 1;
4083-
4084+
4085 if (seconds > 59)
4086 return 1;
4087
4088 if (hour == 24 && (seconds != 0 || frac_seconds != 0))
4089 return 1;
4090-
4091+
4092 return 0;
4093 }
4094
4095@@ -871,18 +872,18 @@
4096 zstring DateTime::toString() const
4097 {
4098 zstring result;
4099-
4100+
4101 // output sign
4102 if (FACET_MEMBERS[facet][0])
4103 if (data[YEAR_DATA] < 0)
4104 result.append("-", 1);
4105-
4106+
4107 // output preceding '-' for Gregorian dates, when needed
4108 if (facet == GMONTH_FACET || facet == GMONTHDAY_FACET)
4109 result.append("--", 2);
4110 if (facet == GDAY_FACET)
4111 result.append("---", 3);
4112-
4113+
4114 for (int i=0; i<=5; i++)
4115 {
4116 if (FACET_MEMBERS[facet][i])
4117@@ -892,12 +893,12 @@
4118 result.push_back(separators[i]);
4119 }
4120 }
4121-
4122+
4123 if (FACET_MEMBERS[facet][FRACSECONDS_DATA] && (data[FRACSECONDS_DATA] != 0))
4124 {
4125 int temp;
4126 result.append(".", 1);
4127-
4128+
4129 // print leading 0s, if any
4130 temp = FRAC_SECONDS_UPPER_LIMIT / 10;
4131 while (temp > data[FRACSECONDS_DATA] && temp > 0)
4132@@ -905,17 +906,17 @@
4133 result.append("0", 1);
4134 temp /= 10;
4135 }
4136-
4137+
4138 // strip trailing 0s, if any
4139 temp = data[FRACSECONDS_DATA];
4140 while (temp%10 == 0 && temp > 0)
4141 temp = temp / 10;
4142-
4143+
4144 result.append(ztd::to_string(temp));
4145 }
4146-
4147+
4148 result.append(the_time_zone.toString());
4149-
4150+
4151 return result;
4152 }
4153
4154@@ -984,7 +985,7 @@
4155 assert(data[SECONDS_DATA] >= 0);
4156 return data[SECONDS_DATA];
4157 }
4158-
4159+
4160
4161 int DateTime::getFractionalSeconds() const
4162 {
4163@@ -1003,21 +1004,21 @@
4164 {
4165 return !the_time_zone.timeZoneNotSet();
4166 }
4167-
4168-
4169+
4170+
4171 int DateTime::compare(const DateTime* dt, long timezone_seconds) const
4172 {
4173 std::auto_ptr<DateTime> d1_t;
4174 std::auto_ptr<DateTime> d2_t;
4175-
4176+
4177 d1_t.reset(normalizeTimeZone(timezone_seconds));
4178 d2_t.reset(dt->normalizeTimeZone(timezone_seconds));
4179-
4180+
4181 if (d1_t->data[YEAR_DATA] < d2_t->data[YEAR_DATA])
4182 return -1;
4183 else if (d1_t->data[YEAR_DATA] > d2_t->data[YEAR_DATA])
4184 return 1;
4185-
4186+
4187 // compare the rest of the data
4188 if (d1_t->data[YEAR_DATA] < 0 && d2_t->data[YEAR_DATA] < 0)
4189 {
4190@@ -1039,7 +1040,7 @@
4191 return 1;
4192 }
4193 }
4194-
4195+
4196 return 0;
4197 }
4198
4199@@ -1048,7 +1049,7 @@
4200 {
4201 uint32_t hval = 0;
4202 std::auto_ptr<DateTime> dt(normalizeTimeZone(implicit_timezone_seconds));
4203-
4204+
4205 hval = hashfun::h32<int>((int)dt->facet, hval);
4206 hval = hashfun::h32<int>(dt->data[YEAR_DATA], hval);
4207 hval = hashfun::h32<int>(dt->data[MONTH_DATA], hval);
4208@@ -1057,9 +1058,9 @@
4209 hval = hashfun::h32<int>(dt->data[MINUTE_DATA], hval);
4210 hval = hashfun::h32<int>(dt->data[SECONDS_DATA], hval);
4211 hval = hashfun::h32<int>(dt->data[FRACSECONDS_DATA], hval);
4212-
4213+
4214 hval = dt->the_time_zone.hash(hval);
4215-
4216+
4217 return hval;
4218 }
4219
4220@@ -1086,13 +1087,13 @@
4221 data[MONTH_DATA],
4222 data[DAY_DATA])-1,
4223 0, 0, 0, 0);
4224-
4225+
4226 Duration remainder(Duration::DAYTIMEDURATION_FACET, false, 0, 0, 0,
4227 data[HOUR_DATA],
4228 data[MINUTE_DATA],
4229 data[SECONDS_DATA],
4230 data[FRACSECONDS_DATA]);
4231-
4232+
4233 return days + remainder;
4234 }
4235 }
4236@@ -1106,7 +1107,7 @@
4237
4238 // For the algorithm, see XML Schema 2 spec, Appendix E
4239 // http://www.w3.org/TR/xmlschema-2/#adding-durations-to-dateTimes
4240-
4241+
4242 months = modulo<int>(data[MONTH_DATA] + d.getMonths() - 1, 12) + 1;
4243
4244 years = data[YEAR_DATA] + d.getYears() +
4245@@ -1118,7 +1119,7 @@
4246 int_seconds = modulo<int>(total_seconds, 60);
4247
4248 frac_seconds = modulo<int>(temp_frac_seconds, DateTime::FRAC_SECONDS_UPPER_LIMIT);
4249-
4250+
4251 minutes = data[MINUTE_DATA] + d.getMinutes() + quotient<int>(total_seconds, 60);
4252
4253 hours = data[HOUR_DATA] + d.getHours() + quotient<int>(minutes, 60);
4254@@ -1155,7 +1156,7 @@
4255 years += quotient<int>(months + carry-1, 12);
4256 months = modulo<int>(months + carry -1, 12) + 1;
4257 }
4258-
4259+
4260 if (data[YEAR_DATA] > 0 && d.isNegative() && years <= 0)
4261 years--;
4262 if (data[YEAR_DATA] < 0 && !d.isNegative() && years >= 0)
4263@@ -1167,7 +1168,7 @@
4264 int_seconds, frac_seconds, &the_time_zone,
4265 *new_dt))
4266 assert(0);
4267-
4268+
4269 new_dt->facet = facet;
4270 if (adjust_facet)
4271 new_dt->adjustToFacet();
4272@@ -1199,13 +1200,13 @@
4273 {
4274 DateTime* dt;
4275 Duration d;
4276-
4277+
4278 if( the_time_zone.timeZoneNotSet() )
4279 {
4280 // validate timezone value (-14 .. +14 H)
4281 if (tz_seconds > 14*3600 || tz_seconds < -14*3600)
4282 throw InvalidTimezoneException( tz_seconds );
4283-
4284+
4285 d = Duration(Duration::DAYTIMEDURATION_FACET,
4286 (tz_seconds < 0), 0, 0, 0, 0, 0, tz_seconds, 0);
4287 }
4288@@ -1214,10 +1215,10 @@
4289 if (0 != Duration::fromTimezone(the_time_zone, d))
4290 assert(0);
4291 }
4292-
4293+
4294 dt = subtractDuration(d, false); // do not adjust to facet
4295 dt->the_time_zone = TimeZone(0);
4296-
4297+
4298 return dt;
4299 }
4300
4301@@ -1227,7 +1228,7 @@
4302 std::auto_ptr<Duration> dtduration;
4303 std::auto_ptr<Duration> context_tz;
4304 std::auto_ptr<DateTime> dt;
4305-
4306+
4307 // validate timezone value (-14 .. +14 H)
4308 if (tz_seconds > 14*3600 || tz_seconds < -14*3600)
4309 throw InvalidTimezoneException( tz_seconds );
4310@@ -1236,7 +1237,7 @@
4311 context_tz = std::auto_ptr<Duration>(new Duration(Duration::DAYTIMEDURATION_FACET, (tz_seconds<0), 0, 0, 0, 0, 0, tz_seconds, 0));
4312
4313 dt = std::auto_ptr<DateTime>(new DateTime(*this));
4314-
4315+
4316 // If $arg does not have a timezone component and $timezone is not the empty sequence,
4317 // then the result is $arg with $timezone as the timezone component.
4318 if (the_time_zone.timeZoneNotSet())
4319@@ -1274,9 +1275,9 @@
4320
4321 // A dynamic error is raised [err:FODT0003] if $timezone is less than -PT14H
4322 // or greater than PT14H or if does not contain an integral number of minutes.
4323-
4324+
4325 dt = std::auto_ptr<DateTime>(new DateTime(*this));
4326-
4327+
4328 if (d == NULL)
4329 {
4330 if (!the_time_zone.timeZoneNotSet())
4331@@ -1291,7 +1292,7 @@
4332 d->getHours()*3600 + d->getMinutes()*60 > 14*3600 ||
4333 d->getHours()*3600 + d->getMinutes()*60 < -14*3600)
4334 throw InvalidTimezoneException( d->getHours()*3600 + d->getMinutes()*60 );
4335-
4336+
4337 // If $arg does not have a timezone component and $timezone is not the
4338 // empty sequence, then the result is $arg with $timezone as the timezone
4339 // component.
4340@@ -1385,79 +1386,18 @@
4341 }
4342
4343
4344-int DateTime::getDayOfWeek(int year, int month, int day)
4345-{
4346- if (month < 3)
4347- {
4348- month = month + 12;
4349- year = year - 1;
4350- }
4351-
4352- return (day
4353- + (2 * month)
4354- + int(6 * (month + 1) / 10)
4355- + year
4356- + int(year / 4)
4357- - int(year / 100)
4358- + int(year / 400)
4359- + 1 // CalendarSystem, 1 for Gregorian
4360- ) % 7;
4361-}
4362-
4363-
4364-int DateTime::getWeekInYear(int year, int month, int day)
4365-{
4366- int day_of_year = DateTime::getDayOfYear(year, month, day);
4367- int year_first_day_of_week = DateTime::getDayOfWeek(year, 1, 1);
4368-
4369- if (year_first_day_of_week > 4 && (year_first_day_of_week + day_of_year) <= 8)
4370- return getWeekInYear(year-1, 12, 31);
4371-
4372- return ((day_of_year + year_first_day_of_week - 2) / 7) + year_first_day_of_week < 5 ? 1 : 0;
4373-}
4374-
4375-
4376 int DateTime::getDayOfYear(int year, int month, int day)
4377 {
4378- static const int days[] = {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365};
4379-
4380 if (month > 12)
4381 return -1;
4382-
4383- if (isLeapYear(year) && month >= 3)
4384- day++;
4385-
4386- return days[month-1] + day;
4387-}
4388-
4389-
4390-bool DateTime::isLeapYear(int year)
4391-{
4392- if (((year%4 == 0) && (year%100 != 0))
4393- ||
4394- (year%400 == 0))
4395- return true;
4396- else
4397- return false;
4398+ return time::calc_yday( day, month - 1, year ) + 1;
4399 }
4400
4401
4402 int DateTime::getWeekInMonth(int year, int month, int day)
4403 {
4404- int first_day_of_week = DateTime::getDayOfWeek(year, month, 1);
4405- return ((day + first_day_of_week - 2) / 7) + (first_day_of_week < 5 ? 1 : 0);
4406-}
4407-
4408-
4409-bool DateTime::isLeapYear() const
4410-{
4411- return isLeapYear(data[YEAR_DATA]);
4412-}
4413-
4414-
4415-int DateTime::getDayOfWeek() const
4416-{
4417- return getDayOfWeek(data[YEAR_DATA], data[MONTH_DATA], data[DAY_DATA]);
4418+ int const wday = time::calc_wday( 1, month - 1, year );
4419+ return ((day + wday - 2) / 7) + (wday < 5 ? 1 : 0);
4420 }
4421
4422
4423@@ -1467,12 +1407,6 @@
4424 }
4425
4426
4427-int DateTime::getWeekInYear() const
4428-{
4429- return getWeekInYear(data[YEAR_DATA], data[MONTH_DATA], data[DAY_DATA]);
4430-}
4431-
4432-
4433 int DateTime::getWeekInMonth() const
4434 {
4435 return getWeekInMonth(data[YEAR_DATA], data[MONTH_DATA], data[DAY_DATA]);
4436
4437=== modified file 'src/zorbautils/locale.cpp'
4438--- src/zorbautils/locale.cpp 2013-03-18 05:13:50 +0000
4439+++ src/zorbautils/locale.cpp 2013-03-21 16:00:34 +0000
4440@@ -169,6 +169,8 @@
4441 LPCWSTR wlocale_name;
4442 unique_ptr<WCHAR[]> wlocale_name_ptr;
4443
4444+ if ( !country )
4445+ country = iso3166_1::get_default( lang );
4446 if ( lang && country ) {
4447 wlocale_name_ptr = get_wlocale_name( lang, country );
4448 wlocale_name = wlocale_name_ptr.get();
4449@@ -278,6 +280,8 @@
4450 static zstring get_locale_info( nl_item item, iso639_1::type lang,
4451 iso3166_1::type country ) {
4452 if ( lang ) {
4453+ if ( !country )
4454+ country = iso3166_1::get_default( lang );
4455 if ( locale_t const loc = get_unix_locale_t( lang, country ) ) {
4456 char const *const info = nl_langinfo_l( item, loc );
4457 ::freelocale( loc );
4458@@ -549,6 +553,205 @@
4459 return FIND( country );
4460 }
4461
4462+type get_default( iso639_1::type lang ) {
4463+ //
4464+ // In cases where a language maps to multiple countries, if the language is
4465+ // the official language of a single country, that country is the one the
4466+ // language is mapped to.
4467+ //
4468+ static type const lang_to_country[] = {
4469+ unknown,
4470+ DJ , // aa: Afar => Djibouti
4471+ GE , // ab: Abkhazian => Georgia
4472+ IR , // ae: Avestan => Iran
4473+ ZA , // af: Afrikaans => South Africa
4474+ GH , // ak: Akan => Ghana
4475+ ET , // am: Amharic => Ethiopia
4476+ ES , // an: Aragonese => Spain
4477+ unknown, // ar: Arabic => (maps to multiple countries)
4478+ IN_ , // as: Assamese => India
4479+ AZ , // av: Avaric => Azerbaijan
4480+ BO , // ay: Aymara => Bolivia
4481+ AZ , // az: Azerbaijani => Azerbaijan
4482+ RU , // ba: Bashkir => Russian Federation
4483+ RU , // be: Byelorussian => Russian Federation
4484+ BG , // bg: Bulgarian => Bulgaria
4485+ IN_ , // bh: Bihari => India
4486+ VU , // bi: Bislama => Vanuatu
4487+ ML , // bm: Bambara => Mali
4488+ BD , // bn: Bengali; Bangla => Bangladesh
4489+ CN , // bo: Tibetan => China
4490+ FR , // br: Breton => France
4491+ BA , // bs: Bosnian => Bosnia
4492+ AD , // ca: Catalan => Andorra
4493+ RU , // ce: Chechen => Russian Federation
4494+ MP , // ch: Chamorro => Northern Mariana Islands
4495+ FR , // co: Corsican => France
4496+ US , // cr: Cree => United States
4497+ CZ , // cs: Czech => Czech Republic
4498+ RU , // cu: Church Slavic; Church Slavonic => Russian Federation
4499+ RU , // cv: Chuvash => Russian Federation
4500+ GB , // cy: Welsh => United Kingdom
4501+ DK , // da: Danish => Denmark
4502+ DE , // de: German => Germany
4503+ MV , // dv: Divehi => Maldives
4504+ PK , // dz: Bhutani => Pakistan
4505+ unknown, // ee: Ewe => (maps to multiple countries)
4506+ GR , // el: Greek => Greece
4507+ GB , // en: English => United Kingdom
4508+ unknown, // eo: Esperanto => (constructed language)
4509+ ES , // es: Spanish => Spain
4510+ EE , // et: Estonian => Estonia
4511+ ES , // eu: Basque => Spain
4512+ IR , // fa: Persian => Iran
4513+ unknown, // ff: Fulah => (maps to multiple countries)
4514+ FI , // fi: Finnish => Finland
4515+ FJ , // fj: Fiji => Fiji
4516+ FO , // fo: Faroese => Faroe Islands
4517+ FR , // fr: French => France
4518+ NL , // fy: Frisian => Netherlands
4519+ IE , // ga: Irish => Ireland
4520+ GB , // gd: Scots Gaelic => United Kingdom
4521+ ES , // gl: Galician => Spain
4522+ PY , // gn: Guarani => Paraguay
4523+ IN_ , // gu: Gujarati => India
4524+ IM , // gv: Manx => Isle of Man
4525+ unknown, // ha: Hausa => (maps to multiple languages)
4526+ IL , // he: Hebrew => Israel
4527+ IN_ , // hi: Hindi => India
4528+ PG , // ho: Hiri Motu => Papua New Guinea
4529+ HR , // hr: Croatian => Croatia
4530+ HT , // ht: Haitian Creole => Haiti
4531+ HU , // hu: Hungarian => Hungary
4532+ AM , // hy: Armenian => Armenia
4533+ unknown, // hz: Herero => (maps to multiple countries)
4534+ unknown, // ia: Interlingua => (constructed language)
4535+ ID , // id: Indonesian => Indonesia
4536+ unknown, // ie: Interlingue => (constructed language)
4537+ NG , // ig: Igbo => Nigeria
4538+ CN , // ii: Nuosu => China
4539+ US , // ik: Inupiak => United States
4540+ unknown, // io: Ido => (constructed language)
4541+ IS , // is: Icelandic => Island
4542+ IT , // it: Italian => Italy
4543+ CA , // iu: Inuktitut => Canada
4544+ JP , // ja: Japanese => Japan
4545+ ID , // jv: Javanese => Indonesia
4546+ GE , // ka: Georgian => Georgia
4547+ unknown, // kg: Kongo => (maps to multiple countries)
4548+ KE , // ki: Gikuyu => Kenya
4549+ unknown, // kj: Kuanyama => (maps to multiple countries)
4550+ KZ , // kk: Kazakh => Kazakhstan
4551+ GL , // kl: Greenlandic => Greenland
4552+ KH , // km: Cambodian => Cambodia
4553+ IN_ , // kn: Kannada => India
4554+ KR , // ko: Korean => Korea
4555+ unknown, // kr: Kanuri => (maps to multiple countries)
4556+ IN_ , // ks: Kashmiri => India
4557+ IQ , // ku: Kurdish => Iraq
4558+ RU , // kv: Komi => Russian Federation
4559+ GB , // kw: Cornish => United Kingdom
4560+ KG , // ky: Kirghiz => Kyrgyzstan
4561+ unknown, // la: Latin => (maps to multiple countries)
4562+ LU , // lb: Letzeburgesch => Luxembourg
4563+ UG , // lg: Ganda => Uganda
4564+ NL , // li: Limburgan; Limburger; Limburgish => Netherands
4565+ unknown, // ln: Lingala => (maps to multiple countries)
4566+ LA , // lo: Laotian => Lao
4567+ LT , // lt: Lithuanian => Lithuania
4568+ CD , // lu: Luba-Katanga => Democratic Republic of the Congo
4569+ LV , // lv: Latvian => Latvia
4570+ MG , // mg: Malagasy => Madagascar
4571+ MH , // mh: Marshallese => Marshall Islands
4572+ NZ , // mi: Maori => New Zealand
4573+ MK , // mk: Macedonian => Macedonia
4574+ IN_ , // ml: Malayalam => India
4575+ MN , // mn: Mongolian => Mongolia
4576+ MD , // mo: Moldavian => Moldova
4577+ IN_ , // mr: Marathi => India
4578+ MY , // ms: Malay => Malaysia
4579+ MT , // mt: Maltese => Malta
4580+ MM , // my: Burmese => Myanmar (Burma)
4581+ NR , // na: Nauru => Nauru
4582+ NO , // nb: Norwegian Bokmal => Norway
4583+ ZW , // nd: Ndebele, North => Zimbabwe
4584+ NP , // ne: Nepali => Nepal
4585+ NA , // ng: Ndonga => Namibia
4586+ NL , // nl: Dutch => Netherlands
4587+ NO , // nn: Norwegian Nynorsk => Norway
4588+ NO , // no: Norwegian => Norway
4589+ ZA , // nr: Ndebele, South => South Africa
4590+ US , // nv: Navajo; Navaho => United States
4591+ MW , // ny: Chichewa; Chewa; Nyanja => Malawi
4592+ unknown, // oc: Occitan => (maps to multiple countries)
4593+ CA , // oj: Ojibwa => Canada
4594+ unknown, // om: Oromo => (maps to multiple countries)
4595+ IN_ , // or: Oriya => India
4596+ unknown, // os: Ossetian; Ossetic => (maps to multiple countries)
4597+ PK , // pa: Panjabi; Punjabi => Pakistan
4598+ unknown, // pi: Pali => (maps to multiple countries)
4599+ PL , // pl: Polish => Poland
4600+ AF , // ps: Pashto, Pushto => Afghanistan
4601+ PT , // pt: Portuguese => Portugal
4602+ unknown, // qu: Quechua => (maps to multiple countries)
4603+ CH , // rm: Romansh => Switzerland
4604+ BI , // rn: Kirundi => Burundi
4605+ RO , // ro: Romanian => Romania
4606+ RU , // ru: Russian => Russian Federation
4607+ RW , // rw: Kinyarwanda => Rwanda
4608+ IN_ , // sa: Sanskrit => India
4609+ IT , // sc: Sardinian => Italy
4610+ PK , // sd: Sindhi => Pakistan
4611+ NO , // se: Northern Sami => Norway
4612+ CF , // sg: Sangho => Central African Republic
4613+ RS , // sh: Serbo-Croatian => Serbia
4614+ LK , // si: Sinhalese => Sri Lanka
4615+ SK , // sk: Slovak => Slovakia
4616+ SI , // sl: Slovenian => Slovenia
4617+ AS , // sm: Samoan => American Samoa
4618+ ZW , // sn: Shona => Zimbabwe
4619+ SO , // so: Somali => Somalia
4620+ AL , // sq: Albanian => Albania
4621+ RS , // sr: Serbian => Serbia
4622+ SZ , // ss: Siswati => Swaziland
4623+ LS , // st: Sesotho => Lesotho
4624+ SD , // su: Sundanese => Sudan
4625+ SE , // sv: Swedish => Sweden
4626+ KE , // sw: Swahili => Kenya
4627+ IN_ , // ta: Tamil => India
4628+ IN_ , // te: Telugu => India
4629+ TJ , // tg: Tajik => Tajikistan
4630+ TH , // th: Thai => Thailand
4631+ ER , // ti: Tigrinya => Eritrea
4632+ TM , // tk: Turkmen => Turkmenistan
4633+ PH , // tl: Tagalog => Philippines
4634+ ZA , // tn: Setswana => South Africa
4635+ TO , // to: Tonga => Tonga
4636+ TR , // tr: Turkish => Turkey
4637+ ZA , // ts: Tsonga => South Africa
4638+ RU , // tt: Tatar => Russian Federation
4639+ GH , // tw: Twi => Ghana
4640+ PF , // ty: Tahitian => French Polynesia
4641+ CN , // ug: Uighur => China
4642+ UA , // uk: Ukrainian => Ukrain
4643+ PK , // ur: Urdu => Pakistan
4644+ UZ , // uz: Uzbek => Uzbekistan
4645+ ZA , // ve: Venda => South Africa
4646+ VN , // vi: Vietnamese => Viet Nam
4647+ DE , // vo: Volapuk => Germany
4648+ BE , // wa: Walloon => Belgium
4649+ SN , // wo: Wolof => Senegal
4650+ ZA , // xh: Xhosa => South Africa
4651+ IL , // yi: Yiddish => Israel
4652+ NG , // yo: Yoruba => Nigeria
4653+ CN , // za: Zhuang => China
4654+ CN , // zh: Chinese => China
4655+ ZA , // zu: Zulu => South Africa
4656+ };
4657+ assert( lang < iso639_1::NUM_ENTRIES );
4658+ return lang_to_country[ lang ];
4659+}
4660+
4661 } // namespace iso3166_1
4662
4663 ///////////////////////////////////////////////////////////////////////////////
4664@@ -1302,6 +1505,8 @@
4665 }
4666
4667 bool is_supported( iso639_1::type lang, iso3166_1::type country ) {
4668+ if ( !country )
4669+ country = iso3166_1::get_default( lang );
4670 #ifdef WIN32
4671 unique_ptr<WCHAR[]> const wlocale_name( get_wlocale_name( lang, country ) );
4672 return Zorba_IsValidLocaleName( wlocale_name.get() );
4673
4674=== modified file 'src/zorbautils/locale.h'
4675--- src/zorbautils/locale.h 2013-03-08 04:26:02 +0000
4676+++ src/zorbautils/locale.h 2013-03-21 16:00:34 +0000
4677@@ -62,6 +62,15 @@
4678 find( StringType const &country ) {
4679 return find( country.c_str() );
4680 }
4681+
4682+ /**
4683+ * Gets the "default" country that speaks the given language.
4684+ *
4685+ * @param lang The language to get the default country for.
4686+ * @return Returns said country or \c unknown.
4687+ */
4688+ type get_default( iso639_1::type lang );
4689+
4690 } // namespace iso3166_1
4691
4692 ///////////////////////////////////////////////////////////////////////////
4693
4694=== modified file 'test/fots/CMakeLists.txt'
4695--- test/fots/CMakeLists.txt 2013-03-20 22:49:58 +0000
4696+++ test/fots/CMakeLists.txt 2013-03-21 16:00:34 +0000
4697@@ -158,37 +158,8 @@
4698 EXPECTED_FOTS_FAILURE (fn-environment-variable environment-variable-005 0)
4699 EXPECTED_FOTS_FAILURE (fn-environment-variable environment-variable-006 0)
4700 EXPECTED_FOTS_FAILURE (fn-environment-variable environment-variable-007 0)
4701-EXPECTED_FOTS_FAILURE (fn-format-date format-date-001d 0)
4702-EXPECTED_FOTS_FAILURE (fn-format-date format-date-001g 0)
4703 EXPECTED_FOTS_FAILURE (fn-format-date format-date-005 0)
4704 EXPECTED_FOTS_FAILURE (fn-format-date format-date-006 0)
4705-EXPECTED_FOTS_FAILURE (fn-format-date format-date-007a 0)
4706-EXPECTED_FOTS_FAILURE (fn-format-date format-date-007b 0)
4707-EXPECTED_FOTS_FAILURE (fn-format-date format-date-007c 0)
4708-EXPECTED_FOTS_FAILURE (fn-format-date format-date-008a 0)
4709-EXPECTED_FOTS_FAILURE (fn-format-date format-date-008b 0)
4710-EXPECTED_FOTS_FAILURE (fn-format-date format-date-008c 0)
4711-EXPECTED_FOTS_FAILURE (fn-format-date format-date-009 0)
4712-EXPECTED_FOTS_FAILURE (fn-format-date format-date-010 0)
4713-EXPECTED_FOTS_FAILURE (fn-format-date format-date-014 0)
4714-EXPECTED_FOTS_FAILURE (fn-format-date format-date-015 0)
4715-EXPECTED_FOTS_FAILURE (fn-format-date format-date-016 0)
4716-EXPECTED_FOTS_FAILURE (fn-format-date format-date-017 0)
4717-EXPECTED_FOTS_FAILURE (fn-format-date format-date-018 0)
4718-EXPECTED_FOTS_FAILURE (fn-format-date format-date-019 0)
4719-EXPECTED_FOTS_FAILURE (fn-format-date format-date-020 0)
4720-EXPECTED_FOTS_FAILURE (fn-format-date format-date-021 0)
4721-EXPECTED_FOTS_FAILURE (fn-format-date format-date-022 0)
4722-EXPECTED_FOTS_FAILURE (fn-format-date format-date-023 0)
4723-EXPECTED_FOTS_FAILURE (fn-format-date format-date-024 0)
4724-EXPECTED_FOTS_FAILURE (fn-format-date format-date-025 0)
4725-EXPECTED_FOTS_FAILURE (fn-format-date format-date-026 0)
4726-EXPECTED_FOTS_FAILURE (fn-format-date format-date-027 0)
4727-EXPECTED_FOTS_FAILURE (fn-format-date format-date-en117 0)
4728-EXPECTED_FOTS_FAILURE (fn-format-date format-date-en118 0)
4729-EXPECTED_FOTS_FAILURE (fn-format-date format-date-en123 0)
4730-EXPECTED_FOTS_FAILURE (fn-format-date format-date-en124 0)
4731-EXPECTED_FOTS_FAILURE (fn-format-date format-date-en125 0)
4732 EXPECTED_FOTS_FAILURE (fn-format-date format-date-en126 0)
4733 EXPECTED_FOTS_FAILURE (fn-format-date format-date-en127 0)
4734 EXPECTED_FOTS_FAILURE (fn-format-date format-date-en128 0)
4735@@ -198,34 +169,9 @@
4736 EXPECTED_FOTS_FAILURE (fn-format-date format-date-en132 0)
4737 EXPECTED_FOTS_FAILURE (fn-format-date format-date-en133 0)
4738 EXPECTED_FOTS_FAILURE (fn-format-date format-date-en134 0)
4739-EXPECTED_FOTS_FAILURE (fn-format-date format-date-en141 0)
4740-EXPECTED_FOTS_FAILURE (fn-format-date format-date-en151 0)
4741-EXPECTED_FOTS_FAILURE (fn-format-dateTime format-dateTime-001d 0)
4742-EXPECTED_FOTS_FAILURE (fn-format-dateTime format-dateTime-001g 0)
4743-EXPECTED_FOTS_FAILURE (fn-format-dateTime format-dateTime-002g 0)
4744-EXPECTED_FOTS_FAILURE (fn-format-dateTime format-dateTime-002h 0)
4745-EXPECTED_FOTS_FAILURE (fn-format-dateTime format-dateTime-002i 0)
4746-EXPECTED_FOTS_FAILURE (fn-format-dateTime format-dateTime-003d 0)
4747-EXPECTED_FOTS_FAILURE (fn-format-dateTime format-dateTime-003g 0)
4748-EXPECTED_FOTS_FAILURE (fn-format-dateTime format-dateTime-003m 0)
4749-EXPECTED_FOTS_FAILURE (fn-format-dateTime format-dateTime-003n 0)
4750-EXPECTED_FOTS_FAILURE (fn-format-dateTime format-dateTime-003p 0)
4751 EXPECTED_FOTS_FAILURE (fn-format-dateTime format-dateTime-005 0)
4752 EXPECTED_FOTS_FAILURE (fn-format-dateTime format-dateTime-006 0)
4753-EXPECTED_FOTS_FAILURE (fn-format-dateTime format-dateTime-009 0)
4754-EXPECTED_FOTS_FAILURE (fn-format-dateTime format-dateTime-010 0)
4755 EXPECTED_FOTS_FAILURE (fn-format-dateTime format-dateTime-011 0)
4756-EXPECTED_FOTS_FAILURE (fn-format-dateTime format-dateTime-012 0)
4757-EXPECTED_FOTS_FAILURE (fn-format-dateTime format-dateTime-013p 0)
4758-EXPECTED_FOTS_FAILURE (fn-format-dateTime format-dateTime-013s 0)
4759-EXPECTED_FOTS_FAILURE (fn-format-dateTime format-dateTime-013u 0)
4760-EXPECTED_FOTS_FAILURE (fn-format-dateTime format-dateTime-014 0)
4761-EXPECTED_FOTS_FAILURE (fn-format-dateTime format-dateTime-015 0)
4762-EXPECTED_FOTS_FAILURE (fn-format-dateTime format-dateTime-016 0)
4763-EXPECTED_FOTS_FAILURE (fn-format-dateTime format-dateTime-017 0)
4764-EXPECTED_FOTS_FAILURE (fn-format-dateTime format-dateTime-018 0)
4765-EXPECTED_FOTS_FAILURE (fn-format-dateTime format-dateTime-en141 0)
4766-EXPECTED_FOTS_FAILURE (fn-format-dateTime format-dateTime-en151 0)
4767 EXPECTED_FOTS_FAILURE (fn-format-integer format-integer-030 0)
4768 EXPECTED_FOTS_FAILURE (fn-format-integer format-integer-031 0)
4769 EXPECTED_FOTS_FAILURE (fn-format-integer format-integer-033 0)
4770@@ -265,18 +211,6 @@
4771 EXPECTED_FOTS_FAILURE (fn-format-number numberformat86 0)
4772 EXPECTED_FOTS_FAILURE (fn-format-number numberformat87 0)
4773 EXPECTED_FOTS_FAILURE (fn-format-number numberformat88 0)
4774-EXPECTED_FOTS_FAILURE (fn-format-time format-time-002g 0)
4775-EXPECTED_FOTS_FAILURE (fn-format-time format-time-002h 0)
4776-EXPECTED_FOTS_FAILURE (fn-format-time format-time-002i 0)
4777-EXPECTED_FOTS_FAILURE (fn-format-time format-time-013p 0)
4778-EXPECTED_FOTS_FAILURE (fn-format-time format-time-013s 0)
4779-EXPECTED_FOTS_FAILURE (fn-format-time format-time-013u 0)
4780-EXPECTED_FOTS_FAILURE (fn-format-time format-time-014 0)
4781-EXPECTED_FOTS_FAILURE (fn-format-time format-time-015 0)
4782-EXPECTED_FOTS_FAILURE (fn-format-time format-time-016 0)
4783-EXPECTED_FOTS_FAILURE (fn-format-time format-time-017 0)
4784-EXPECTED_FOTS_FAILURE (fn-format-time format-time-018 0)
4785-EXPECTED_FOTS_FAILURE (fn-format-time format-time-816err 0)
4786 EXPECTED_FOTS_FAILURE (fn-generate-id generate-id-001 0)
4787 EXPECTED_FOTS_FAILURE (fn-generate-id generate-id-002 0)
4788 EXPECTED_FOTS_FAILURE (fn-generate-id generate-id-003 0)
4789
4790=== removed file 'test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/FormatDateFuncYearMonth1.xml.res'
4791--- test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/FormatDateFuncYearMonth1.xml.res 2013-02-07 17:24:36 +0000
4792+++ test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/FormatDateFuncYearMonth1.xml.res 1970-01-01 00:00:00 +0000
4793@@ -1,1 +0,0 @@
4794-true
4795\ No newline at end of file
4796
4797=== removed file 'test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/FormatDateFuncYearMonth2.xml.res'
4798--- test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/FormatDateFuncYearMonth2.xml.res 2013-02-07 17:24:36 +0000
4799+++ test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/FormatDateFuncYearMonth2.xml.res 1970-01-01 00:00:00 +0000
4800@@ -1,1 +0,0 @@
4801-true
4802\ No newline at end of file
4803
4804=== added file 'test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-D.xml.res'
4805--- test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-D.xml.res 1970-01-01 00:00:00 +0000
4806+++ test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-D.xml.res 2013-03-21 16:00:34 +0000
4807@@ -0,0 +1,1 @@
4808+true
4809
4810=== added file 'test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-D01.xml.res'
4811--- test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-D01.xml.res 1970-01-01 00:00:00 +0000
4812+++ test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-D01.xml.res 2013-03-21 16:00:34 +0000
4813@@ -0,0 +1,1 @@
4814+true
4815
4816=== added file 'test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-D1o.xml.res'
4817--- test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-D1o.xml.res 1970-01-01 00:00:00 +0000
4818+++ test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-D1o.xml.res 2013-03-21 16:00:34 +0000
4819@@ -0,0 +1,1 @@
4820+true
4821
4822=== added file 'test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-DW-1.xml.res'
4823--- test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-DW-1.xml.res 1970-01-01 00:00:00 +0000
4824+++ test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-DW-1.xml.res 2013-03-21 16:00:34 +0000
4825@@ -0,0 +1,1 @@
4826+true
4827
4828=== added file 'test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-DWo-1.xml.res'
4829--- test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-DWo-1.xml.res 1970-01-01 00:00:00 +0000
4830+++ test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-DWo-1.xml.res 2013-03-21 16:00:34 +0000
4831@@ -0,0 +1,1 @@
4832+true
4833
4834=== added file 'test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-DWw.xml.res'
4835--- test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-DWw.xml.res 1970-01-01 00:00:00 +0000
4836+++ test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-DWw.xml.res 2013-03-21 16:00:34 +0000
4837@@ -0,0 +1,1 @@
4838+true
4839
4840=== added file 'test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-DWwo.xml.res'
4841--- test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-DWwo.xml.res 1970-01-01 00:00:00 +0000
4842+++ test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-DWwo.xml.res 2013-03-21 16:00:34 +0000
4843@@ -0,0 +1,1 @@
4844+true
4845
4846=== added file 'test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-Dw-2.xml.res'
4847--- test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-Dw-2.xml.res 1970-01-01 00:00:00 +0000
4848+++ test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-Dw-2.xml.res 2013-03-21 16:00:34 +0000
4849@@ -0,0 +1,1 @@
4850+true
4851
4852=== added file 'test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-Dwo-2.xml.res'
4853--- test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-Dwo-2.xml.res 1970-01-01 00:00:00 +0000
4854+++ test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-Dwo-2.xml.res 2013-03-21 16:00:34 +0000
4855@@ -0,0 +1,1 @@
4856+true
4857
4858=== added file 'test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-FN-1.xml.res'
4859--- test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-FN-1.xml.res 1970-01-01 00:00:00 +0000
4860+++ test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-FN-1.xml.res 2013-03-21 16:00:34 +0000
4861@@ -0,0 +1,1 @@
4862+true
4863
4864=== added file 'test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-FN-3.xml.res'
4865--- test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-FN-3.xml.res 1970-01-01 00:00:00 +0000
4866+++ test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-FN-3.xml.res 2013-03-21 16:00:34 +0000
4867@@ -0,0 +1,1 @@
4868+true
4869
4870=== added file 'test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-FNn-1.xml.res'
4871--- test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-FNn-1.xml.res 1970-01-01 00:00:00 +0000
4872+++ test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-FNn-1.xml.res 2013-03-21 16:00:34 +0000
4873@@ -0,0 +1,1 @@
4874+true
4875
4876=== added file 'test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-FNn-2.xml.res'
4877--- test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-FNn-2.xml.res 1970-01-01 00:00:00 +0000
4878+++ test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-FNn-2.xml.res 2013-03-21 16:00:34 +0000
4879@@ -0,0 +1,1 @@
4880+true
4881
4882=== added file 'test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-Fn-2.xml.res'
4883--- test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-Fn-2.xml.res 1970-01-01 00:00:00 +0000
4884+++ test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-Fn-2.xml.res 2013-03-21 16:00:34 +0000
4885@@ -0,0 +1,1 @@
4886+true
4887
4888=== added file 'test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-Fn-4.xml.res'
4889--- test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-Fn-4.xml.res 1970-01-01 00:00:00 +0000
4890+++ test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-Fn-4.xml.res 2013-03-21 16:00:34 +0000
4891@@ -0,0 +1,1 @@
4892+true
4893
4894=== renamed file 'test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/FormatDateFuncMonthDefault.xml.res' => 'test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-M.xml.res'
4895--- test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/FormatDateFuncMonthDefault.xml.res 2013-02-07 17:24:36 +0000
4896+++ test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-M.xml.res 2013-03-21 16:00:34 +0000
4897@@ -1,1 +1,1 @@
4898-true
4899\ No newline at end of file
4900+true
4901
4902=== renamed file 'test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/FormatDateFuncMonthNumber.xml.res' => 'test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-M01.xml.res'
4903--- test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/FormatDateFuncMonthNumber.xml.res 2013-02-07 17:24:36 +0000
4904+++ test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-M01.xml.res 2013-03-21 16:00:34 +0000
4905@@ -1,1 +1,1 @@
4906-true
4907\ No newline at end of file
4908+true
4909
4910=== renamed file 'test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/FormatDateFuncMonthUpperCase.xml.res' => 'test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-MN-1.xml.res'
4911--- test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/FormatDateFuncMonthUpperCase.xml.res 2013-02-07 17:24:36 +0000
4912+++ test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-MN-1.xml.res 2013-03-21 16:00:34 +0000
4913@@ -1,1 +1,1 @@
4914-true
4915\ No newline at end of file
4916+true
4917
4918=== renamed file 'test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/FormatDateFuncMonthTitleCase.xml.res' => 'test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-MNn.xml.res'
4919--- test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/FormatDateFuncMonthTitleCase.xml.res 2013-02-07 17:24:36 +0000
4920+++ test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-MNn.xml.res 2013-03-21 16:00:34 +0000
4921@@ -1,1 +1,1 @@
4922-true
4923\ No newline at end of file
4924+true
4925
4926=== renamed file 'test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/FormatDateFuncMonthLowerCase.xml.res' => 'test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-Mn-2.xml.res'
4927--- test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/FormatDateFuncMonthLowerCase.xml.res 2013-02-07 17:24:36 +0000
4928+++ test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-Mn-2.xml.res 2013-03-21 16:00:34 +0000
4929@@ -1,1 +1,1 @@
4930-true
4931\ No newline at end of file
4932+true
4933
4934=== renamed file 'test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/FormatDateFuncYearMaxWidth.xml.res' => 'test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-Y-2-2.xml.res'
4935--- test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/FormatDateFuncYearMaxWidth.xml.res 2013-02-07 17:24:36 +0000
4936+++ test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-Y-2-2.xml.res 2013-03-21 16:00:34 +0000
4937@@ -1,1 +1,1 @@
4938-true
4939\ No newline at end of file
4940+true
4941
4942=== renamed file 'test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/FormatDateFuncReflexivity.xml.res' => 'test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-Y-M01-D01.xml.res'
4943--- test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/FormatDateFuncReflexivity.xml.res 2013-02-07 17:24:36 +0000
4944+++ test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-Y-M01-D01.xml.res 2013-03-21 16:00:34 +0000
4945@@ -1,1 +1,1 @@
4946-true
4947\ No newline at end of file
4948+true
4949
4950=== added file 'test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-Y-Thai-1.xml.res'
4951--- test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-Y-Thai-1.xml.res 1970-01-01 00:00:00 +0000
4952+++ test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-Y-Thai-1.xml.res 2013-03-21 16:00:34 +0000
4953@@ -0,0 +1,1 @@
4954+true
4955
4956=== added file 'test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-Y-Thai-2.xml.res'
4957--- test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-Y-Thai-2.xml.res 1970-01-01 00:00:00 +0000
4958+++ test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-Y-Thai-2.xml.res 2013-03-21 16:00:34 +0000
4959@@ -0,0 +1,1 @@
4960+true
4961
4962=== renamed file 'test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/FormatDateFuncYearDefault.xml.res' => 'test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-Y.xml.res'
4963--- test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/FormatDateFuncYearDefault.xml.res 2013-02-07 17:24:36 +0000
4964+++ test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-Y.xml.res 2013-03-21 16:00:34 +0000
4965@@ -1,1 +1,1 @@
4966-true
4967\ No newline at end of file
4968+true
4969
4970=== added file 'test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-YI-1.xml.res'
4971--- test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-YI-1.xml.res 1970-01-01 00:00:00 +0000
4972+++ test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-YI-1.xml.res 2013-03-21 16:00:34 +0000
4973@@ -0,0 +1,1 @@
4974+true
4975
4976=== added file 'test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-Yi-2.xml.res'
4977--- test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-Yi-2.xml.res 1970-01-01 00:00:00 +0000
4978+++ test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-Yi-2.xml.res 2013-03-21 16:00:34 +0000
4979@@ -0,0 +1,1 @@
4980+true
4981
4982=== renamed file 'test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/FormatDateFuncYearDefaultExtraChars.xml.res' => 'test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-chars.xml.res'
4983--- test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/FormatDateFuncYearDefaultExtraChars.xml.res 2013-02-07 17:24:36 +0000
4984+++ test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-chars.xml.res 2013-03-21 16:00:34 +0000
4985@@ -1,1 +1,1 @@
4986-true
4987\ No newline at end of file
4988+true
4989
4990=== renamed file 'test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/FormatDateFuncMonthNumberSpaces.xml.res' => 'test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-whitespace.xml.res'
4991--- test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/FormatDateFuncMonthNumberSpaces.xml.res 2013-02-07 17:24:36 +0000
4992+++ test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-whitespace.xml.res 2013-03-21 16:00:34 +0000
4993@@ -1,1 +1,1 @@
4994-true
4995\ No newline at end of file
4996+true
4997
4998=== renamed file 'test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/FormatDateTimeFuncReflexivity.xml.res' => 'test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-dateTime-01.xml.res'
4999--- test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/FormatDateTimeFuncReflexivity.xml.res 2013-02-07 17:24:36 +0000
5000+++ test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-dateTime-01.xml.res 2013-03-21 16:00:34 +0000
The diff has been truncated for viewing.

Subscribers

People subscribed via source and target branches