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
=== modified file 'ChangeLog'
--- ChangeLog 2013-03-20 22:28:21 +0000
+++ ChangeLog 2013-03-21 16:00:34 +0000
@@ -14,6 +14,8 @@
14 * In store API, added ability to specify a stream's originating URI (file)14 * In store API, added ability to specify a stream's originating URI (file)
15 for streamable strings and base64Binary.15 for streamable strings and base64Binary.
16 * Added millis-to-dateTime() function in datetime module.16 * Added millis-to-dateTime() function in datetime module.
17 * Added setCalendar(), getCalendar(), setLocale(), and getLocale() to
18 DynamicContext class in C++ API.
17 * fn:trace outputs "empty-sequence()" if the input is the empty-sequence.19 * fn:trace outputs "empty-sequence()" if the input is the empty-sequence.
18 * Allow multiple default function namespaces.20 * Allow multiple default function namespaces.
19 * Added xqxq:variable-value function.21 * Added xqxq:variable-value function.
@@ -33,6 +35,7 @@
33 * Fixed bug #1095889 (Improve error message for xml-parsing error).35 * Fixed bug #1095889 (Improve error message for xml-parsing error).
34 * Fixed bug in index join rule (no index join if inner clause has positional var).36 * Fixed bug in index join rule (no index join if inner clause has positional var).
35 * Fixed bug in index join rule (copy var ids after cloning index domain expr).37 * Fixed bug in index join rule (copy var ids after cloning index domain expr).
38 * Fixed bug #1123162 (FOTS: formatting dates and times failures)
36 * Added missing wrapper expressions around some variable references.39 * Added missing wrapper expressions around some variable references.
37 * Fixed bug in the throwing of error XQTY0086 during node construction.40 * Fixed bug in the throwing of error XQTY0086 during node construction.
38 * Fixed bug #1148335 (where-clause expression was not always reset when it should be)41 * Fixed bug #1148335 (where-clause expression was not always reset when it should be)
3942
=== modified file 'include/zorba/dynamic_context.h'
--- include/zorba/dynamic_context.h 2013-03-08 04:26:02 +0000
+++ include/zorba/dynamic_context.h 2013-03-21 16:00:34 +0000
@@ -22,6 +22,7 @@
2222
23#include <zorba/config.h>23#include <zorba/config.h>
24#include <zorba/locale.h>24#include <zorba/locale.h>
25#include <zorba/time.h>
25#include <zorba/api_shared_types.h>26#include <zorba/api_shared_types.h>
26#include <zorba/static_context_consts.h>27#include <zorba/static_context_consts.h>
27#include <zorba/xmldatamanager.h>28#include <zorba/xmldatamanager.h>
@@ -268,6 +269,20 @@
268 getLocale( locale::iso639_1::type *aLang,269 getLocale( locale::iso639_1::type *aLang,
269 locale::iso3166_1::type *aCountry ) const = 0;270 locale::iso3166_1::type *aCountry ) const = 0;
270271
272 /** \brief Sets the calendar.
273 *
274 * @param aCalendar The calendar to use.
275 */
276 virtual void
277 setCalendar( time::calendar::type aCalendar ) = 0;
278
279 /** \brief Gets the current calendar.
280 *
281 * @return the current calendar.
282 */
283 virtual time::calendar::type
284 getCalendar() const = 0;
285
271 /** \brief Add a name-value pair to this context.286 /** \brief Add a name-value pair to this context.
272 * The value can be accessed in the evaluate method287 * The value can be accessed in the evaluate method
273 * of external functions (see ContextualExternalFunction).288 * of external functions (see ContextualExternalFunction).
274289
=== modified file 'include/zorba/locale.h'
--- include/zorba/locale.h 2013-03-08 04:26:02 +0000
+++ include/zorba/locale.h 2013-03-21 16:00:34 +0000
@@ -263,7 +263,7 @@
263 BZ, ///< Belize263 BZ, ///< Belize
264 CA, ///< Canada264 CA, ///< Canada
265 CC, ///< Cocos Islands265 CC, ///< Cocos Islands
266 CD, ///< Congo266 CD, ///< Congo, the Democratic Republic of the
267 CF, ///< Central African Republic267 CF, ///< Central African Republic
268 CG, ///< Congo268 CG, ///< Congo
269 CH, ///< Switzerland269 CH, ///< Switzerland
270270
=== modified file 'include/zorba/pregenerated/diagnostic_list.h'
--- include/zorba/pregenerated/diagnostic_list.h 2013-03-06 10:37:33 +0000
+++ include/zorba/pregenerated/diagnostic_list.h 2013-03-21 16:00:34 +0000
@@ -192,9 +192,9 @@
192192
193extern ZORBA_DLL_PUBLIC XQueryErrorCode XTDE1310;193extern ZORBA_DLL_PUBLIC XQueryErrorCode XTDE1310;
194194
195extern ZORBA_DLL_PUBLIC XQueryErrorCode XTDE1340;195extern ZORBA_DLL_PUBLIC XQueryErrorCode FOFD1340;
196196
197extern ZORBA_DLL_PUBLIC XQueryErrorCode XTDE1350;197extern ZORBA_DLL_PUBLIC XQueryErrorCode FOFD1350;
198198
199#if !defined(ZORBA_NO_FULL_TEXT)199#if !defined(ZORBA_NO_FULL_TEXT)
200extern ZORBA_DLL_PUBLIC XQueryErrorCode FTST0008;200extern ZORBA_DLL_PUBLIC XQueryErrorCode FTST0008;
201201
=== added file 'include/zorba/time.h'
--- include/zorba/time.h 1970-01-01 00:00:00 +0000
+++ include/zorba/time.h 2013-03-21 16:00:34 +0000
@@ -0,0 +1,68 @@
1/*
2 * Copyright 2006-2008 The FLWOR Foundation.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#ifndef ZORBA_TIME_API_H
18#define ZORBA_TIME_API_H
19
20namespace zorba {
21namespace time {
22
23///////////////////////////////////////////////////////////////////////////////
24
25/**
26 * XQuery 3.0 F&O: 9.8.4.3: The calendars listed below were known to be in use
27 * during the last hundred years.
28 */
29namespace calendar {
30 enum type {
31 unknown,
32 AD, ///< Anno Domini (Christian Era)
33 AH, ///< Anno Hegirae (Muhammedan Era)
34 AM, ///< Anno Mundi (Jewish Calendar)
35 AME, ///< Mauludi Era (solar years since Mohammed's birth)
36 AP, ///< Anno Persici
37 AS, ///< Aji Saka Era (Java)
38 BE, ///< Buddhist Era
39 CB, ///< Cooch Behar Era
40 CE, ///< Common Era
41 CL, ///< Chinese Lunar Era
42 CS, ///< Chula Sakarat Era
43 EE, ///< Ethiopian Era
44 FE, ///< Fasli Era
45 ISO, ///< ISO 8601 calendar
46 JE, ///< Japanese Calendar
47 KE, ///< Khalsa Era (Sikh calendar)
48 KY, ///< Kali Yuga
49 ME, ///< Malabar Era
50 MS, ///< Monarchic Solar Era
51 OS, ///< Old Style (Julian Calendar)
52 RS, ///< Rattanakosin (Bangkok) Era
53 SE, ///< Saka Era
54 SH, ///< Mohammedan Solar Era (Iran)
55 SS, ///< Saka Samvat
56 TE, ///< Tripurabda Era
57 VE, ///< Vikrama Era
58 VS ///< Vikrama Samvat Era
59 };
60
61} // namespace calendar
62
63///////////////////////////////////////////////////////////////////////////////
64
65} // namespace time
66} // namespace zorba
67#endif /* ZORBA_TIME_API_H */
68/* vim:set et sw=2 ts=2: */
069
=== modified file 'modules/org/expath/ns/file.xq.src/file.cpp'
--- modules/org/expath/ns/file.xq.src/file.cpp 2013-03-06 02:54:03 +0000
+++ modules/org/expath/ns/file.xq.src/file.cpp 2013-03-21 16:00:34 +0000
@@ -657,7 +657,7 @@
657int657int
658LastModifiedFunction::getGmtOffset()658LastModifiedFunction::getGmtOffset()
659{659{
660 time_t t = time(0);660 time_t t = ::time(0);
661 struct tm* data;661 struct tm* data;
662 data = localtime(&t);662 data = localtime(&t);
663 data->tm_isdst = 0;663 data->tm_isdst = 0;
664664
=== modified file 'modules/w3c/pregenerated/xqt-errors.xq'
--- modules/w3c/pregenerated/xqt-errors.xq 2013-03-06 10:37:33 +0000
+++ modules/w3c/pregenerated/xqt-errors.xq 2013-03-21 16:00:34 +0000
@@ -861,17 +861,17 @@
861 : 861 :
862 : @see http://www.w3.org/2005/xqt-errors862 : @see http://www.w3.org/2005/xqt-errors
863:)863:)
864declare variable $err:XTDE1340 as xs:QName := fn:QName($err:NS, "err:XTDE1340");864declare variable $err:FOFD1340 as xs:QName := fn:QName($err:NS, "err:FOFD1340");
865865
866(:~866(:~
867 :867 :
868 : It is a non-recoverable dynamic error if a component specifier within the868 : It is a non-recoverable dynamic error if a component specifier within
869 : picture refers to components that are not available in the given type of869 : the picture refers to components that are not available in the given
870 : \c $value.870 : type of $value.
871 : 871 :
872 : @see http://www.w3.org/2005/xqt-errors872 : @see http://www.w3.org/2005/xqt-errors
873:)873:)
874declare variable $err:XTDE1350 as xs:QName := fn:QName($err:NS, "err:XTDE1350");874declare variable $err:FOFD1350 as xs:QName := fn:QName($err:NS, "err:FOFD1350");
875875
876(:~876(:~
877 :877 :
878878
=== modified file 'modules/xqxq/xqxq.xq.src/xqxq.cpp'
--- modules/xqxq/xqxq.xq.src/xqxq.cpp 2013-02-22 17:09:54 +0000
+++ modules/xqxq/xqxq.xq.src/xqxq.cpp 2013-03-21 16:00:34 +0000
@@ -238,7 +238,7 @@
238 :238 :
239 theModule(aModule)239 theModule(aModule)
240{240{
241 srand(time(NULL));241 srand(::time(NULL));
242}242}
243 243
244244
245245
=== modified file 'src/api/dynamiccontextimpl.cpp'
--- src/api/dynamiccontextimpl.cpp 2013-03-08 04:26:02 +0000
+++ src/api/dynamiccontextimpl.cpp 2013-03-21 16:00:34 +0000
@@ -691,6 +691,17 @@
691/****************************************************************************//**691/****************************************************************************//**
692692
693********************************************************************************/693********************************************************************************/
694void DynamicContextImpl::setCalendar( time::calendar::type aCalendar ) {
695 theCtx->set_calendar( aCalendar );
696}
697
698time::calendar::type DynamicContextImpl::getCalendar() const {
699 return theCtx->get_calendar();
700}
701
702/****************************************************************************//**
703
704********************************************************************************/
694bool DynamicContextImpl::addExternalFunctionParam(705bool DynamicContextImpl::addExternalFunctionParam(
695 const String& aName,706 const String& aName,
696 void* aValue)707 void* aValue)
697708
=== modified file 'src/api/dynamiccontextimpl.h'
--- src/api/dynamiccontextimpl.h 2013-03-08 04:26:02 +0000
+++ src/api/dynamiccontextimpl.h 2013-03-21 16:00:34 +0000
@@ -151,6 +151,12 @@
151 getLocale( locale::iso639_1::type *aLang, 151 getLocale( locale::iso639_1::type *aLang,
152 locale::iso3166_1::type *aCountry ) const;152 locale::iso3166_1::type *aCountry ) const;
153153
154 virtual void
155 setCalendar( time::calendar::type aCalendar );
156
157 virtual time::calendar::type
158 getCalendar() const;
159
154 virtual bool160 virtual bool
155 addExternalFunctionParam(const String& aName, void* aValue);161 addExternalFunctionParam(const String& aName, void* aValue);
156162
157163
=== modified file 'src/context/dynamic_context.cpp'
--- src/context/dynamic_context.cpp 2013-03-12 17:03:31 +0000
+++ src/context/dynamic_context.cpp 2013-03-21 16:00:34 +0000
@@ -137,6 +137,7 @@
137 reset_current_date_time();137 reset_current_date_time();
138 theLang = locale::get_host_lang();138 theLang = locale::get_host_lang();
139 theCountry = locale::get_host_country();139 theCountry = locale::get_host_country();
140 theCalendar = time::calendar::get_default();
140 }141 }
141 else142 else
142 {143 {
@@ -145,6 +146,7 @@
145 theDefaultCollectionUri = parent->theDefaultCollectionUri;146 theDefaultCollectionUri = parent->theDefaultCollectionUri;
146 theLang = parent->theLang;147 theLang = parent->theLang;
147 theCountry = parent->theCountry;148 theCountry = parent->theCountry;
149 theCalendar = parent->theCalendar;
148 }150 }
149}151}
150152
151153
=== modified file 'src/context/dynamic_context.h'
--- src/context/dynamic_context.h 2013-03-12 17:03:31 +0000
+++ src/context/dynamic_context.h 2013-03-21 16:00:34 +0000
@@ -18,6 +18,7 @@
18#define ZORBA_DYNAMIC_CONTEXT_H18#define ZORBA_DYNAMIC_CONTEXT_H
1919
20#include <zorba/external_function_parameter.h>20#include <zorba/external_function_parameter.h>
21#include <zorba/time.h>
2122
22#include "zorbautils/hashmap_zstring.h"23#include "zorbautils/hashmap_zstring.h"
23#include "zorbautils/hashmap_itemp.h"24#include "zorbautils/hashmap_itemp.h"
@@ -141,6 +142,7 @@
141142
142 locale::iso639_1::type theLang;143 locale::iso639_1::type theLang;
143 locale::iso3166_1::type theCountry;144 locale::iso3166_1::type theCountry;
145 time::calendar::type theCalendar;
144146
145public:147public:
146 double theDocLoadingUserTime;148 double theDocLoadingUserTime;
@@ -189,6 +191,14 @@
189 *country = theCountry;191 *country = theCountry;
190 }192 }
191193
194 void set_calendar( time::calendar::type calendar ) {
195 theCalendar = calendar;
196 }
197
198 time::calendar::type get_calendar() const {
199 return theCalendar;
200 }
201
192 const std::vector<VarValue>& get_variables() const { return theVarValues; }202 const std::vector<VarValue>& get_variables() const { return theVarValues; }
193203
194 void add_variable(ulong varid, store::Item_t& value);204 void add_variable(ulong varid, store::Item_t& value);
195205
=== modified file 'src/diagnostics/diagnostic_en.xml'
--- src/diagnostics/diagnostic_en.xml 2013-03-16 20:44:27 +0000
+++ src/diagnostics/diagnostic_en.xml 2013-03-21 16:00:34 +0000
@@ -1012,21 +1012,51 @@
1012 <value>"$1": picture string does not satisfy format-number() function rules</value>1012 <value>"$1": picture string does not satisfy format-number() function rules</value>
1013 </diagnostic>1013 </diagnostic>
10141014
1015 <diagnostic code="XTDE1340">1015 <diagnostic code="FOFD1340">
1016 <comment>1016 <comment>
1017 It is a non-recoverable dynamic error if the syntax of the picture is1017 It is a non-recoverable dynamic error if the syntax of the picture is
1018 incorrect.1018 incorrect.
1019 </comment>1019 </comment>
1020 <value>"$1": invalid picture string for date/time</value>1020 <value>"$1": invalid picture string for date/time${: 2}</value>
1021 <entry key="BadComponent_3">
1022 <value>'$3': invalid component specifier</value>
1023 </entry>
1024 <entry key="BadWidthModifier">
1025 <value>invalid width modifier</value>
1026 </entry>
1027 <entry key="DigitNotSameFamily_34">
1028 <value>"$3": digit not from same digit family as $4</value>
1029 </entry>
1030 <entry key="MultipleComponent_3">
1031 <value>'$3': multiple component specifiers between []</value>
1032 </entry>
1033 <entry key="MustBeOneMandatoryDigit">
1034 <value>there must be at least one mandatory-digit-sign</value>
1035 </entry>
1036 <entry key="NoComponent">
1037 <value>component specifier expected between []</value>
1038 </entry>
1039 <entry key="NoAdjacentGroupSep_3">
1040 <value>"$3": grouping separator must not be adjacent to others</value>
1041 </entry>
1042 <entry key="NoGroupSepAtStart_3">
1043 <value>"$3": grouping separator illegal at start of decimal-digit-pattern</value>
1044 </entry>
1045 <entry key="NoGroupSepAtEnd_3">
1046 <value>"$3": grouping separator illegal at end of decimal-digit-pattern</value>
1047 </entry>
1048 <entry key="NoOptDigitAfterMandatory">
1049 <value>"#": optional-digit-sign must precede all mandatory-digit-signs</value>
1050 </entry>
1021 </diagnostic>1051 </diagnostic>
10221052
1023 <diagnostic code="XTDE1350">1053 <diagnostic code="FOFD1350">
1024 <comment>1054 <comment>
1025 It is a non-recoverable dynamic error if a component specifier within the1055 It is a non-recoverable dynamic error if a component specifier within
1026 picture refers to components that are not available in the given type of1056 the picture refers to components that are not available in the given
1027 \c $value.1057 type of $value.
1028 </comment>1058 </comment>
1029 <value>component specifier not available</value>1059 <value>"$1": component specifier not available</value>
1030 </diagnostic>1060 </diagnostic>
10311061
1032 <!--////////// XQuery Full-Text Errors /////////////////////////////////-->1062 <!--////////// XQuery Full-Text Errors /////////////////////////////////-->
10331063
=== modified file 'src/diagnostics/pregenerated/diagnostic_list.cpp'
--- src/diagnostics/pregenerated/diagnostic_list.cpp 2013-03-06 10:37:33 +0000
+++ src/diagnostics/pregenerated/diagnostic_list.cpp 2013-03-21 16:00:34 +0000
@@ -271,10 +271,10 @@
271XQueryErrorCode XTDE1310( "XTDE1310" );271XQueryErrorCode XTDE1310( "XTDE1310" );
272272
273273
274XQueryErrorCode XTDE1340( "XTDE1340" );274XQueryErrorCode FOFD1340( "FOFD1340" );
275275
276276
277XQueryErrorCode XTDE1350( "XTDE1350" );277XQueryErrorCode FOFD1350( "FOFD1350" );
278278
279279
280#if !defined(ZORBA_NO_FULL_TEXT)280#if !defined(ZORBA_NO_FULL_TEXT)
281281
=== modified file 'src/diagnostics/pregenerated/dict_en.cpp'
--- src/diagnostics/pregenerated/dict_en.cpp 2013-03-16 20:44:27 +0000
+++ src/diagnostics/pregenerated/dict_en.cpp 2013-03-21 16:00:34 +0000
@@ -53,6 +53,8 @@
53 { "FODT0002", "overflow/underflow in duration operation" },53 { "FODT0002", "overflow/underflow in duration operation" },
54 { "FODT0003", "\"$1\": invalid timezone value (in seconds)" },54 { "FODT0003", "\"$1\": invalid timezone value (in seconds)" },
55 { "FOER0000", "unidentifier error" },55 { "FOER0000", "unidentifier error" },
56 { "FOFD1340", "\"$1\": invalid picture string for date/time${: 2}" },
57 { "FOFD1350", "\"$1\": component specifier not available" },
56 { "FOFI0001", "\"$1\": not castable to xs:language" },58 { "FOFI0001", "\"$1\": not castable to xs:language" },
57 { "FOFI0002", "invalid argument in format-integer: $1" },59 { "FOFI0002", "invalid argument in format-integer: $1" },
58 { "FONS0004", "\"$1\": no namespace found for prefix" },60 { "FONS0004", "\"$1\": no namespace found for prefix" },
@@ -270,8 +272,6 @@
270 { "XSST0009", "\"break loop\" statement not inside while statement" },272 { "XSST0009", "\"break loop\" statement not inside while statement" },
271 { "XSST0010", "\"continue loop\" statement not inside while statement" },273 { "XSST0010", "\"continue loop\" statement not inside while statement" },
272 { "XTDE1310", "\"$1\": picture string does not satisfy format-number() function rules" },274 { "XTDE1310", "\"$1\": picture string does not satisfy format-number() function rules" },
273 { "XTDE1340", "\"$1\": invalid picture string for date/time" },
274 { "XTDE1350", "component specifier not available" },
275 { "XUDY0009", "node has no parent in \"replace\" expression (without \"value of\")" },275 { "XUDY0009", "node has no parent in \"replace\" expression (without \"value of\")" },
276 { "XUDY0014", "\"modify\" can not modify node not created by \"copy\"" },276 { "XUDY0014", "\"modify\" can not modify node not created by \"copy\"" },
277 { "XUDY0015", "node is target of multiple \"rename\" expressions in same query" },277 { "XUDY0015", "node is target of multiple \"rename\" expressions in same query" },
@@ -613,6 +613,16 @@
613 { "~FOCA0002_BadLexicalQName_2", "\"$2\": value is not a valid lexical QName" },613 { "~FOCA0002_BadLexicalQName_2", "\"$2\": value is not a valid lexical QName" },
614 { "~FOCA0002_NoCastTo_234", "\"$2\": value of type $3 is not castable to type $4" },614 { "~FOCA0002_NoCastTo_234", "\"$2\": value of type $3 is not castable to type $4" },
615 { "~FOCA0002_NoURIforPrefix_2", "no namespace URI provided for prefix in lexical QName \"$2\"" },615 { "~FOCA0002_NoURIforPrefix_2", "no namespace URI provided for prefix in lexical QName \"$2\"" },
616 { "~FOFD1340_BadComponent_3", "'$3': invalid component specifier" },
617 { "~FOFD1340_BadWidthModifier", "invalid width modifier" },
618 { "~FOFD1340_DigitNotSameFamily_34", "\"$3\": digit not from same digit family as $4" },
619 { "~FOFD1340_MultipleComponent_3", "'$3': multiple component specifiers between []" },
620 { "~FOFD1340_MustBeOneMandatoryDigit", "there must be at least one mandatory-digit-sign" },
621 { "~FOFD1340_NoAdjacentGroupSep_3", "\"$3\": grouping separator must not be adjacent to others" },
622 { "~FOFD1340_NoComponent", "component specifier expected between []" },
623 { "~FOFD1340_NoGroupSepAtEnd_3", "\"$3\": grouping separator illegal at end of decimal-digit-pattern" },
624 { "~FOFD1340_NoGroupSepAtStart_3", "\"$3\": grouping separator illegal at start of decimal-digit-pattern" },
625 { "~FOFD1340_NoOptDigitAfterMandatory", "\"#\": optional-digit-sign must precede all mandatory-digit-signs" },
616 { "~FORG0001_BadHexDigit_2", "'$2': invalid hexedecimal digit" },626 { "~FORG0001_BadHexDigit_2", "'$2': invalid hexedecimal digit" },
617 { "~FORG0001_Base64BadChar_2", "'$2': invalid Base64 character" },627 { "~FORG0001_Base64BadChar_2", "'$2': invalid Base64 character" },
618 { "~FORG0001_Base64Multiple4", "Base64 data must be a multiple of 4 bytes" },628 { "~FORG0001_Base64Multiple4", "Base64 data must be a multiple of 4 bytes" },
619629
=== modified file 'src/diagnostics/pregenerated/dict_zed_keys.h'
--- src/diagnostics/pregenerated/dict_zed_keys.h 2013-03-16 20:44:27 +0000
+++ src/diagnostics/pregenerated/dict_zed_keys.h 2013-03-21 16:00:34 +0000
@@ -63,6 +63,16 @@
63#define ZED_XQDY0074_NotCastToQName "~XQDY0074_NotCastToQName"63#define ZED_XQDY0074_NotCastToQName "~XQDY0074_NotCastToQName"
64#define ZED_XQDY0074_NoEmptyLocalname "~XQDY0074_NoEmptyLocalname"64#define ZED_XQDY0074_NoEmptyLocalname "~XQDY0074_NoEmptyLocalname"
65#define ZED_XQDY0074_NameSapceConstructor "~XQDY0074_NameSapceConstructor"65#define ZED_XQDY0074_NameSapceConstructor "~XQDY0074_NameSapceConstructor"
66#define ZED_FOFD1340_BadComponent_3 "~FOFD1340_BadComponent_3"
67#define ZED_FOFD1340_BadWidthModifier "~FOFD1340_BadWidthModifier"
68#define ZED_FOFD1340_DigitNotSameFamily_34 "~FOFD1340_DigitNotSameFamily_34"
69#define ZED_FOFD1340_MultipleComponent_3 "~FOFD1340_MultipleComponent_3"
70#define ZED_FOFD1340_MustBeOneMandatoryDigit "~FOFD1340_MustBeOneMandatoryDigit"
71#define ZED_FOFD1340_NoComponent "~FOFD1340_NoComponent"
72#define ZED_FOFD1340_NoAdjacentGroupSep_3 "~FOFD1340_NoAdjacentGroupSep_3"
73#define ZED_FOFD1340_NoGroupSepAtStart_3 "~FOFD1340_NoGroupSepAtStart_3"
74#define ZED_FOFD1340_NoGroupSepAtEnd_3 "~FOFD1340_NoGroupSepAtEnd_3"
75#define ZED_FOFD1340_NoOptDigitAfterMandatory "~FOFD1340_NoOptDigitAfterMandatory"
66#define ZED_FTST0009_BadStopWordsLang "~FTST0009_BadStopWordsLang"76#define ZED_FTST0009_BadStopWordsLang "~FTST0009_BadStopWordsLang"
67#define ZED_FTST0009_BadStemmerLang "~FTST0009_BadStemmerLang"77#define ZED_FTST0009_BadStemmerLang "~FTST0009_BadStemmerLang"
68#define ZED_FTST0009_BadThesaurusLang "~FTST0009_BadThesaurusLang"78#define ZED_FTST0009_BadThesaurusLang "~FTST0009_BadThesaurusLang"
6979
=== modified file 'src/functions/func_durations_dates_times_impl.cpp'
--- src/functions/func_durations_dates_times_impl.cpp 2013-02-07 17:24:36 +0000
+++ src/functions/func_durations_dates_times_impl.cpp 2013-03-21 16:00:34 +0000
@@ -19,6 +19,7 @@
19#include "functions/function_impl.h"19#include "functions/function_impl.h"
2020
21#include "runtime/durations_dates_times/DurationsDatesTimesImpl.h"21#include "runtime/durations_dates_times/DurationsDatesTimesImpl.h"
22#include "runtime/durations_dates_times/format_dateTime.h"
22#include "runtime/numerics/NumericsImpl.h"23#include "runtime/numerics/NumericsImpl.h"
23#include "runtime/core/arithmetic_impl.h"24#include "runtime/core/arithmetic_impl.h"
24#include "zorbamisc/ns_consts.h"25#include "zorbamisc/ns_consts.h"
2526
=== modified file 'src/runtime/CMakeLists.txt'
--- src/runtime/CMakeLists.txt 2013-02-07 17:24:36 +0000
+++ src/runtime/CMakeLists.txt 2013-03-21 16:00:34 +0000
@@ -125,6 +125,7 @@
125 core/gflwor/outerfor_iterator.cpp125 core/gflwor/outerfor_iterator.cpp
126 core/internal_operators.cpp126 core/internal_operators.cpp
127 durations_dates_times/DurationsDatesTimesImpl.cpp127 durations_dates_times/DurationsDatesTimesImpl.cpp
128 durations_dates_times/format_dateTime.cpp
128 indexing/doc_indexer.cpp129 indexing/doc_indexer.cpp
129 indexing/index_ddl.cpp130 indexing/index_ddl.cpp
130 json/common.cpp131 json/common.cpp
131132
=== modified file 'src/runtime/durations_dates_times/DurationsDatesTimesImpl.cpp'
--- src/runtime/durations_dates_times/DurationsDatesTimesImpl.cpp 2013-02-28 11:15:32 +0000
+++ src/runtime/durations_dates_times/DurationsDatesTimesImpl.cpp 2013-03-21 16:00:34 +0000
@@ -45,8 +45,6 @@
45{45{
46SERIALIZABLE_CLASS_VERSIONS(FnDateTimeConstructorIterator)46SERIALIZABLE_CLASS_VERSIONS(FnDateTimeConstructorIterator)
4747
48SERIALIZABLE_CLASS_VERSIONS(FnFormatDateTimeIterator)
49
50SERIALIZABLE_CLASS_VERSIONS(FnAdjustToTimeZoneIterator_1)48SERIALIZABLE_CLASS_VERSIONS(FnAdjustToTimeZoneIterator_1)
5149
52SERIALIZABLE_CLASS_VERSIONS(FnAdjustToTimeZoneIterator_2)50SERIALIZABLE_CLASS_VERSIONS(FnAdjustToTimeZoneIterator_2)
@@ -54,19 +52,11 @@
5452
55BINARY_ACCEPT(FnDateTimeConstructorIterator);53BINARY_ACCEPT(FnDateTimeConstructorIterator);
5654
57NARY_ACCEPT(FnFormatDateTimeIterator);
58
59UNARY_ACCEPT(FnAdjustToTimeZoneIterator_1);55UNARY_ACCEPT(FnAdjustToTimeZoneIterator_1);
6056
61BINARY_ACCEPT(FnAdjustToTimeZoneIterator_2);57BINARY_ACCEPT(FnAdjustToTimeZoneIterator_2);
6258
6359
64static void skip_whitespace(zstring& str, ascii::size_type& position, int delta = 0)
65{
66 while (position+delta < str.size() && ascii::is_space(str[position+delta]))
67 position++;
68}
69
70bool FnDateTimeConstructorIterator::nextImpl(store::Item_t& result, PlanState& planState) const60bool FnDateTimeConstructorIterator::nextImpl(store::Item_t& result, PlanState& planState) const
71{61{
72 store::Item_t item0;62 store::Item_t item0;
@@ -199,555 +189,5 @@
199 STACK_END(state);189 STACK_END(state);
200}190}
201191
202
203/**
204 *______________________________________________________________________
205 *
206 * fn:format-dateTime()
207 *
208 *_______________________________________________________________________*/
209
210class Modifier
211{
212public:
213 zstring presentation_modifier;
214 zstring second_modifier;
215
216 // for min_width and max_width
217 // -3 means an error in the picture
218 // -2 means width modifiers are not specified
219 // -1 means '*'
220 // >=0 means explicitly specified width
221 long min_width_modifier;
222 long max_width_modifier;
223
224 Modifier()
225 :
226 presentation_modifier(""),
227 second_modifier(""),
228 min_width_modifier(-2),
229 max_width_modifier(-2)
230 {
231 };
232};
233
234
235static void format_number(zstring& str, long number, Modifier& modifier)
236{
237 // Presentation modifier can be:
238 // 'Ww', "Nn', 'W', 'w', 'N', 'n'
239 // 'i', 'I', '1', '00...01'
240 // the modifier will not be checked if it is supported or not
241 zstring temp;
242
243 if (modifier.presentation_modifier.size() > 0 && modifier.presentation_modifier[0] == '0')
244 {
245 ztd::to_string(number, &temp);
246 while (temp.size() < modifier.presentation_modifier.size())
247 temp = "0" + temp;
248 }
249 else // "1" or fallback
250 {
251 ztd::to_string(number, &temp);
252 }
253
254 if (modifier.second_modifier == "o")
255 {
256 if ((number % 10) == 1 && (number % 100) != 11)
257 temp.append("st");
258 else if ((number % 10) == 2 && (number % 100) != 12)
259 temp.append("nd");
260 else if ((number % 10) == 3 && (number % 100) != 13)
261 temp.append("rd");
262 else
263 temp.append("th");
264 }
265
266 if (modifier.min_width_modifier >= 0)
267 while (temp.size() < (unsigned int)modifier.min_width_modifier)
268 temp = "0" + temp;
269
270 str.append(temp.c_str());
271}
272
273
274static void format_string_width(
275 zstring& destination,
276 zstring& source,
277 Modifier& modifier)
278{
279 zstring temp = source;
280 while (modifier.max_width_modifier > 0 && temp.size() < (unsigned int)modifier.max_width_modifier)
281 temp.append(" ");
282 destination.append(temp.c_str());
283}
284
285
286static bool format_string(
287 zstring& destination,
288 zstring& source,
289 Modifier& modifier)
290{
291 zstring temp;
292 if (modifier.presentation_modifier == "n")
293 {
294 zstring newcase = source;
295 ascii::to_lower(newcase);
296 temp.append(newcase);
297 }
298 else if (modifier.presentation_modifier == "N")
299 {
300 zstring newcase = source;
301 ascii::to_upper(newcase);
302 temp.append(newcase);
303 }
304 else if (modifier.presentation_modifier == "Nn")
305 {
306 zstring newcase;
307
308 newcase = source.substr(0, 1);
309 ascii::to_upper(newcase);
310 temp.append(newcase);
311
312 newcase = source.substr(1,source.size()-1);
313 ascii::to_lower(newcase);
314 temp.append(newcase);
315 }
316 else
317 return false;
318
319 format_string_width(destination, temp, modifier);
320 return true;
321}
322
323
324static bool format_string(
325 zstring& destination,
326 const char* source,
327 Modifier& modifier)
328{
329 zstring temp(source);
330 return format_string(destination, temp, modifier);
331}
332
333
334static void format_component(
335 zstring& destination,
336 long number,
337 zstring& source,
338 Modifier& modifier)
339{
340 if (!format_string(destination, source, modifier))
341 format_number(destination, number, modifier);
342}
343
344
345static void output_year(
346 zstring& destination,
347 long number,
348 Modifier& modifier)
349{
350 format_number(destination, number, modifier);
351
352 if (modifier.max_width_modifier >= 0)
353 {
354 if ((unsigned int)modifier.max_width_modifier > destination.size())
355 modifier.max_width_modifier = destination.size();
356
357 destination = destination.substr(destination.size() - modifier.max_width_modifier, modifier.max_width_modifier);
358 }
359}
360
361
362static void output_month(
363 zstring& destination,
364 long number,
365 Modifier& modifier)
366{
367 static const char* month[12] = { "january", "february", "march", "april", "may", "june", "july", "august", "september", "october", "november", "december"};
368 zstring temp(month[number-1]);
369 if (modifier.max_width_modifier > 0 && (unsigned int)modifier.max_width_modifier < temp.size())
370 temp = temp.substr(0, modifier.max_width_modifier);
371
372 format_component(destination, number, temp, modifier);
373}
374
375
376static void output_day_of_week(
377 zstring& destination,
378 long number,
379 Modifier& modifier)
380{
381 static const char* day[7] = { "sunday", "monday", "tuesday", "wednesday", "thursday", "friday", "saturday"};
382 zstring temp(day[number]);
383 if (modifier.max_width_modifier > 0 && (unsigned int)modifier.max_width_modifier < temp.size())
384 temp = temp.substr(0, modifier.max_width_modifier);
385
386 if (modifier.presentation_modifier.size() == 0)
387 modifier.presentation_modifier = "n"; // Default for day of week is "n"
388
389 format_component(destination, number, temp, modifier);
390}
391
392
393static void parse_presentation_modifier(
394 zstring& str,
395 ascii::size_type& position,
396 zstring& result)
397{
398 result = "";
399
400 skip_whitespace(str, position, 1);
401
402 if (position+1 >= str.size())
403 return;
404
405 zstring modifier = "";
406
407 if (str[position+1] == '1' || str[position+1] == 'i' || str[position+1] == 'I'
408 || str[position+1] == 'a' || str[position+1] == 'A'
409 || str[position+1] == 'w' || str[position+1] == 'W'
410 || str[position+1] == 'n' || str[position+1] == 'N' )
411 {
412 modifier.append(str, position+1, 1);
413 position++;
414
415 skip_whitespace(str, position, 1);
416
417 if (position+1 < str.size() &&
418 ((modifier[0] == 'W' && str[position+1] == 'w')
419 ||
420 (modifier[0] == 'N' && str[position+1] == 'n')))
421 {
422 modifier.append(str, position+1, 1);
423 position++;
424 }
425 }
426 else if (str[position+1] == '0')
427 {
428 ascii::size_type start = position;
429 while (position+1 < str.size() && (str[position+1] == '0' || ascii::is_space(str[position+1])))
430 {
431 if (str[position+1] == '0')
432 modifier.append(str, position+1, 1);
433 position++;
434 }
435
436 if (position+1 >= str.size() || str[position+1] != '1')
437 {
438 position = start;
439 return;
440 }
441
442 modifier.append(str, position+1, 1);
443 position++;
444 }
445
446 result = modifier;
447}
448
449
450static void parse_second_modifier(
451 zstring& str,
452 ascii::size_type& position,
453 zstring& result)
454{
455 result = "";
456
457 skip_whitespace(str, position, 1);
458
459 if (position+1 >= str.size())
460 return;
461
462 position++;
463 if (str[position] == 't')
464 result = "t";
465 else if (str[position] == 'o')
466 result = "o";
467 else
468 position--;
469}
470
471
472// for min_width and max_width
473// -3 means an error in the picture
474// -2 means width modifiers are not specified
475// -1 means '*'
476// >=0 means explicitly specified width
477static void parse_width_modifier(
478 zstring& str,
479 ascii::size_type& position,
480 long& min_width,
481 long& max_width)
482{
483 min_width = -2;
484 max_width = -2;
485
486 skip_whitespace(str, position, 1);
487
488 if (position+1 >= str.size() || str[position+1] != ',')
489 return;
490
491 position++;
492 skip_whitespace(str, position, 1);
493
494 // The min_width must be present if there is a comma symbol
495 min_width = -3;
496 if (position+1 >= str.size())
497 return;
498
499 if (str[position+1] == '*')
500 {
501 min_width = -1;
502 position++;
503 }
504 else
505 {
506 if (parse_long(str.data(), str.size(), position, min_width, -1, -1, 1))
507 min_width = -3;
508 }
509
510 skip_whitespace(str, position, 1);
511
512 if (position+1 >= str.size() || str[position+1] != '-')
513 return;
514
515 position++;
516 skip_whitespace(str, position, 1);
517
518 if (position+1 < str.size() && str[position+1] == '*')
519 {
520 max_width = -1;
521 position++;
522 }
523 else
524 {
525 if (parse_long(str.data(), str.size(), position, max_width, -1, -1, 1))
526 min_width = -3;
527 }
528}
529
530
531static int get_data_type(char component)
532{
533 switch (component)
534 {
535 case 'Y':
536 return DateTime::YEAR_DATA;
537 case 'M':
538 return DateTime::MONTH_DATA;
539 case 'D':
540 return DateTime::DAY_DATA;
541 case 'd': // day in year
542 return DateTime::DAY_DATA;
543 case 'F': // day of week
544 return DateTime::DAY_DATA;
545 case 'W': // week in year
546 return DateTime::DAY_DATA;
547 case 'w': // week in month
548 return DateTime::DAY_DATA;
549 case 'H': // hour in day (24 hours)
550 return DateTime::HOUR_DATA;
551 case 'h': // hour in half-day (12 hours)
552 return DateTime::HOUR_DATA;
553 case 'P': // am/pm marker
554 return DateTime::HOUR_DATA;
555 case 'm':
556 return DateTime::MINUTE_DATA;
557 case 's':
558 return DateTime::SECONDS_DATA;
559 case 'f': // fractional seconds
560 return DateTime::FRACSECONDS_DATA;
561 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)
562 return -1;
563 case 'z': // timezone as a time offset using GMT, for example GMT+1
564 return -1;
565 case 'C': // calendar: the name or abbreviation of a calendar name
566 return -1;
567 case 'E': // era: the name of a baseline for the numbering of years, for example the reign of a monarch
568 return -1;
569 default:
570 return -1;
571 }
572}
573
574
575bool FnFormatDateTimeIterator::nextImpl(
576 store::Item_t& result,
577 PlanState& planState) const
578{
579 bool variable_marker;
580 zstring pictureString, resultString;
581 store::Item_t dateTimeItem, picture;
582 PlanIteratorState* state;
583 DEFAULT_STACK_INIT(PlanIteratorState, state, planState);
584
585 if (!consumeNext(dateTimeItem, theChildren[0].getp(), planState))
586 {
587 // Got void -- returning void
588 STACK_PUSH(false, state);
589 }
590 else
591 {
592 consumeNext(picture, theChildren[1].getp(), planState);
593
594 pictureString = picture->getStringValue().str();
595 resultString = "";
596 variable_marker = false;
597
598 for (ascii::size_type i = 0; i < pictureString.size(); i++)
599 {
600 if (!variable_marker)
601 {
602 if (pictureString[i] == '[')
603 {
604 // check for quoted "[["
605 if (i<pictureString.size()-1 && pictureString[i+1] == '[')
606 i++;
607 else
608 {
609 variable_marker = true;
610 continue;
611 }
612 }
613 else if (pictureString[i] == ']')
614 {
615 // check for quoted "]]"
616 if (i<pictureString.size()-1 && pictureString[i+1] == ']')
617 i++;
618 }
619
620 resultString.append(pictureString, i, 1);
621 }
622 else // variable_marker == true
623 {
624 char component = 0;
625 Modifier modifier;
626
627 switch (pictureString[i])
628 {
629 case 'Y': case 'M': case 'D': case 'd': case 'F': case 'W': case 'w':
630 case 'H': case 'h': case 'P': case 'm': case 's': case 'f':
631 case 'Z': case 'z': case 'C': case 'E':
632 component = pictureString[i];
633 break;
634
635 case ' ': case '\f': case '\n': case '\r': case '\t': case '\v':
636 continue; // ignore whitespace
637 break;
638
639 case ']':
640 variable_marker = false;
641 break;
642
643 default:
644 throw XQUERY_EXCEPTION(
645 err::XTDE1340, ERROR_PARAMS( pictureString ), ERROR_LOC( loc )
646 );
647 }
648
649 if (variable_marker == false)
650 continue;
651
652 parse_presentation_modifier(pictureString, i, modifier.presentation_modifier);
653
654 parse_second_modifier(pictureString, i, modifier.second_modifier);
655
656 parse_width_modifier(pictureString,
657 i,
658 modifier.min_width_modifier,
659 modifier.max_width_modifier);
660
661 // min_width_modifier is -3, there was an error in the picture
662 if (modifier.min_width_modifier == -3)
663 throw XQUERY_EXCEPTION(
664 err::XTDE1340, ERROR_PARAMS( pictureString ), ERROR_LOC( loc )
665 );
666
667 int data_type = get_data_type(component);
668 if (data_type != -1 && (!DateTime::FACET_MEMBERS[facet_type][data_type]))
669 throw XQUERY_EXCEPTION(err::XTDE1350, ERROR_LOC(loc));
670
671 switch (component)
672 {
673 case 'Y':
674 output_year(resultString, std::abs(dateTimeItem->getDateTimeValue().getYear()), modifier);
675 break;
676 case 'M':
677 output_month(resultString, dateTimeItem->getDateTimeValue().getMonth(), modifier);
678 break;
679 case 'D':
680 format_number(resultString, dateTimeItem->getDateTimeValue().getDay(), modifier);
681 break;
682 case 'd': // day in year
683 format_number(resultString, dateTimeItem->getDateTimeValue().getDayOfYear(), modifier);
684 break;
685 case 'F': // day of week
686 output_day_of_week(resultString, dateTimeItem->getDateTimeValue().getDayOfWeek(), modifier);
687 break;
688 case 'W': // week in year
689 format_number(resultString, dateTimeItem->getDateTimeValue().getWeekInYear(), modifier);
690 break;
691 case 'w': // week in month
692 format_number(resultString, dateTimeItem->getDateTimeValue().getWeekInMonth(), modifier);
693 break;
694 case 'H': // hour in day (24 hours)
695 format_number(resultString, dateTimeItem->getDateTimeValue().getHours(), modifier);
696 break;
697 case 'h': // hour in half-day (12 hours)
698 // Convert hour from: 0 1 ... 12 13 ... 23 0
699 // to: 12 1 ... 12 1 ... 11 12
700 format_number(resultString, 1 + (11 + dateTimeItem->getDateTimeValue().getHours()) % 12,
701 modifier);
702 break;
703 case 'P': // am/pm marker
704 if (modifier.presentation_modifier.empty())
705 modifier.presentation_modifier = "n"; // Default for the AM/PM marker is "n"
706 format_string(resultString, dateTimeItem->getDateTimeValue().getHours() >= 12 ? "pm" : "am", modifier);
707 break;
708 case 'm':
709 if (modifier.presentation_modifier.empty())
710 modifier.presentation_modifier.append("01");
711 format_number(resultString, dateTimeItem->getDateTimeValue().getMinutes(), modifier);
712 break;
713 case 's':
714 if (modifier.presentation_modifier.empty())
715 modifier.presentation_modifier.append("01");
716 format_number(resultString, dateTimeItem->getDateTimeValue().getIntSeconds(), modifier);
717 break;
718 case 'f': // fractional seconds
719 format_number(resultString, (long)(dateTimeItem->getDateTimeValue().getFractionalSeconds()*1000.0/DateTime::FRAC_SECONDS_UPPER_LIMIT),
720 modifier);
721 break;
722 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)
723 // deliberate fall-through
724 case 'z': // timezone as a time offset using GMT, for example GMT+1
725 {
726 zstring temp = "gmt";
727 temp += dateTimeItem->getDateTimeValue().getTimezone().toString();
728 format_string(resultString, temp.c_str(), modifier);
729 }
730 break;
731 case 'C': // calendar: the name or abbreviation of a calendar name
732 if (modifier.presentation_modifier.empty())
733 modifier.presentation_modifier.append("n");
734 format_string(resultString, "gregorian", modifier);
735 break;
736 case 'E': // era: the name of a baseline for the numbering of years, for example the reign of a monarch
737 if (modifier.presentation_modifier.empty())
738 modifier.presentation_modifier.append("n");
739 format_string(resultString, dateTimeItem->getDateTimeValue().getYear() < 0 ? "ad" : "bc", modifier);
740 break;
741 } // switch
742 } // if (!variable_marker)
743
744 } // for
745
746 STACK_PUSH(GENV_ITEMFACTORY->createString(result, resultString), state);
747 }
748
749 STACK_END (state);
750}
751
752} // namespace zorba192} // namespace zorba
753/* vim:set et sw=2 ts=2: */193/* vim:set et sw=2 ts=2: */
754194
=== modified file 'src/runtime/durations_dates_times/DurationsDatesTimesImpl.h'
--- src/runtime/durations_dates_times/DurationsDatesTimesImpl.h 2013-02-07 17:24:36 +0000
+++ src/runtime/durations_dates_times/DurationsDatesTimesImpl.h 2013-03-21 16:00:34 +0000
@@ -24,53 +24,12 @@
24#include "runtime/base/unarybase.h"24#include "runtime/base/unarybase.h"
25#include "runtime/base/narybase.h"25#include "runtime/base/narybase.h"
2626
27namespace zorba {
2728
28namespace zorba29///////////////////////////////////////////////////////////////////////////////
29{
3030
31BINARY_ITER(FnDateTimeConstructorIterator);31BINARY_ITER(FnDateTimeConstructorIterator);
3232
33
34// XQuery 3.0 DateTime formatting
35class FnFormatDateTimeIterator : public NaryBaseIterator<FnFormatDateTimeIterator,
36 PlanIteratorState >
37{
38private:
39 DateTime::FACET_TYPE facet_type;
40
41public:
42 SERIALIZABLE_CLASS(FnFormatDateTimeIterator);
43
44 SERIALIZABLE_CLASS_CONSTRUCTOR2T(
45 FnFormatDateTimeIterator,
46 NaryBaseIterator<FnFormatDateTimeIterator, PlanIteratorState >);
47
48 void serialize(::zorba::serialization::Archiver &ar)
49 {
50 serialize_baseclass(ar,
51 (NaryBaseIterator<FnFormatDateTimeIterator, PlanIteratorState >*)this);
52
53 SERIALIZE_ENUM(DateTime::FACET_TYPE, facet_type);
54 }
55
56public:
57 FnFormatDateTimeIterator(
58 static_context* sctx,
59 const QueryLoc& loc,
60 std::vector<PlanIter_t>& aChildren,
61 DateTime::FACET_TYPE a_facet_type = DateTime::DATETIME_FACET)
62 :
63 NaryBaseIterator<FnFormatDateTimeIterator, PlanIteratorState>(sctx, loc, aChildren),
64 facet_type(a_facet_type)
65 {
66 }
67
68 void accept(PlanIterVisitor& v) const;
69
70 bool nextImpl(store::Item_t& result, PlanState& aPlanState) const;
71};
72
73
74/*33/*
7510.7 Timezone Adjustment Functions on Dates and Time Values3410.7 Timezone Adjustment Functions on Dates and Time Values
76*/35*/
@@ -88,14 +47,14 @@
88*/47*/
89BINARY_ITER(FnAdjustToTimeZoneIterator_2);48BINARY_ITER(FnAdjustToTimeZoneIterator_2);
9049
50///////////////////////////////////////////////////////////////////////////////
51
91} // namespace zorba52} // namespace zorba
9253
93#endif54#endif /* ZORBA_RUNTIME_DURATIONSDATESTIMES */
94
95/*55/*
96 * Local variables:56 * Local variables:
97 * mode: c++57 * mode: c++
98 * End:58 * End:
99 */59 */
100
101/* vim:set et sw=2 ts=2: */60/* vim:set et sw=2 ts=2: */
10261
=== added file 'src/runtime/durations_dates_times/format_dateTime.cpp'
--- src/runtime/durations_dates_times/format_dateTime.cpp 1970-01-01 00:00:00 +0000
+++ src/runtime/durations_dates_times/format_dateTime.cpp 2013-03-21 16:00:34 +0000
@@ -0,0 +1,1377 @@
1/*
2 * Copyright 2006-2008 The FLWOR Foundation.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "stdafx.h"
18
19// standard
20#include <algorithm>
21#include <cctype>
22#include <cmath>
23#include <cstdlib>
24#include <functional>
25#include <iomanip>
26#include <iostream>
27#include <sstream>
28
29// Zorba
30#include "context/dynamic_context.h"
31#include "context/static_context.h"
32#include "runtime/core/arithmetic_impl.h"
33#include "runtime/visitors/planiter_visitor.h"
34#include "store/api/item.h"
35#include "store/api/item_factory.h"
36#include "store/api/store.h"
37#include "system/globalenv.h"
38#include "util/ascii_util.h"
39#include "util/stream_util.h"
40#include "util/string_util.h"
41#include "util/time_util.h"
42#include "util/utf8_util.h"
43#include "zorbatypes/datetime.h"
44#include "zorbatypes/datetime/parse.h"
45#include "zorbatypes/duration.h"
46#include "zorbatypes/zstring.h"
47#include "zorbautils/locale.h"
48
49// local
50#include "format_dateTime.h"
51
52using namespace std;
53using namespace zorba::locale;
54using namespace zorba::time;
55
56namespace zorba {
57
58SERIALIZABLE_CLASS_VERSIONS(FnFormatDateTimeIterator)
59NARY_ACCEPT(FnFormatDateTimeIterator);
60
61///////////////////////////////////////////////////////////////////////////////
62
63/**
64 * Holds presentation modifier data.
65 */
66struct modifier {
67 enum first_type {
68 arabic, // '1' : 0 1 2 ... 10 11 12 ...
69 alpha, // 'a' : a b c ... z aa ab ac ...
70 ALPHA, // 'A' : A B C ... Z AA AB AC ...
71 roman, // 'i' : i ii iii iv v vi vii viii ix x ...
72 ROMAN, // 'I' : I II III IV V VI VII VIII IX X ...
73 name, // 'n' : name
74 Name, // 'Nn': Name
75 NAME, // 'N' : NAME
76 words, // 'w' : one two three four ...
77 Words, // 'Ww': One Two Three Four ...
78 WORDS, // 'W' : ONE TWO THREE FOUR ...
79 military_tz // 'Z' : A B C ... J ... X Y Z
80 };
81
82 enum second_co_type {
83 no_second_co,
84 cardinal, // 'c': 7 or seven
85 ordinal // 'o': 7th or seventh
86 };
87
88 enum second_at_type {
89 no_second_at,
90 alphabetic, // 'a'
91 traditional // 't'
92 };
93
94 typedef unsigned width_type;
95
96 struct {
97 bool parsed;
98 first_type type;
99 zstring format;
100 bool has_grouping_separators;
101 unicode::code_point zero;
102 } first;
103
104 struct {
105 second_co_type co_type;
106 zstring co_string;
107 second_at_type at_type;
108 } second;
109
110 width_type min_width;
111 width_type max_width;
112
113 //
114 // This stuff isn't part of the "presentation modifier" as discussed in the
115 // XQuery3.0 F&O spec, but this is a convenient place to put it nonetheless.
116 //
117 iso639_1::type lang;
118 bool lang_is_fallback;
119 iso3166_1::type country;
120 calendar::type cal;
121 bool cal_is_fallback;
122
123 void append_if_fallback_lang( zstring *s ) const {
124 if ( lang_is_fallback ) {
125 //
126 // XQuery 3.0 F&O: 9.8.4.3: If the fallback representation uses a
127 // different language from that requested, the output string must
128 // identify the language actually used, for example by prefixing the
129 // string with [Language: Y] (where Y is the language actually used)
130 // localized in an implementation-dependent way.
131 //
132 ostringstream oss;
133 // TODO: localize "Language"
134 oss << "[Language: " << lang << ']';
135 *s += oss.str();
136 }
137 }
138
139 bool gt_max_width( width_type n ) const {
140 return max_width > 0 && n > max_width;
141 }
142
143 zstring const& left_pad_zero( zstring *s ) const {
144 if ( min_width )
145 utf8::left_pad( s, min_width, first.zero );
146 return *s;
147 }
148
149 zstring const& right_pad_space( zstring *s ) const {
150 if ( min_width )
151 utf8::right_pad( s, min_width, ' ' );
152 return *s;
153 }
154
155 void set_default_width( width_type width ) {
156 if ( !(first.parsed || min_width || max_width) )
157 min_width = max_width = width;
158 }
159
160 modifier() {
161 first.parsed = false;
162 first.type = arabic;
163 first.has_grouping_separators = false;
164 first.zero = '0';
165 second.co_type = cardinal;
166 second.at_type = no_second_at;
167 min_width = max_width = 0;
168 };
169};
170
171///////////////////////////////////////////////////////////////////////////////
172
173zstring alpha( unsigned n, bool capital ) {
174 zstring result;
175 if ( n ) {
176 char const c = capital ? 'A' : 'a';
177 while ( n ) {
178 unsigned const m = n - 1;
179 result.insert( (zstring::size_type)0, 1, c + m % 26 );
180 n = m / 26;
181 }
182 } else
183 result = "0";
184 return result;
185}
186
187///////////////////////////////////////////////////////////////////////////////
188
189namespace english_impl {
190
191// Based on code from:
192// http://www.cprogramming.com/challenges/integer-to-english-sol.html
193
194static string const ones[][2] = {
195 { "", "" },
196 { "one", "first" },
197 { "two", "second" },
198 { "three", "third" },
199 { "four", "fourth" },
200 { "five", "fifth" },
201 { "six", "sixth" },
202 { "seven", "seventh" },
203 { "eight", "eighth" },
204 { "nine", "ninth" },
205 { "ten", "tenth" },
206 { "eleven", "eleventh" },
207 { "twelve", "twelveth" },
208 { "thirteen", "thirteenth" },
209 { "fourteen", "fourteenth" },
210 { "fifteen", "fifteenth" },
211 { "sixteen", "sixteenth" },
212 { "seventeen", "seventeenth" },
213 { "eighteen", "eighteenth" },
214 { "nineteen", "nineteenth" }
215};
216
217static zstring const tens[][2] = {
218 { "", "" },
219 { "", "" },
220 { "twenty", "twentieth" },
221 { "thirty", "thirtieth" },
222 { "forty", "fortieth" },
223 { "fifty", "fiftieth" },
224 { "sixty", "sixtieth" },
225 { "seventy", "seventieth" },
226 { "eighty", "eighteenth" },
227 { "ninety", "ninetieth" }
228};
229
230// Enough entries to print English for 64-bit integers.
231static zstring const big[][2] = {
232 { "", "" },
233 { "thousand", "thousandth" },
234 { "million", "millionth" },
235 { "billion", "billionth" },
236 { "trillion", "trillionth" },
237 { "quadrillion", "quadrillionth" },
238 { "quintillion", "quintillionth" }
239};
240
241inline zstring if_space( zstring const &s ) {
242 return s.empty() ? "" : ' ' + s;
243}
244
245static zstring hundreds( int64_t n, bool ordinal ) {
246 if ( n < 20 )
247 return ones[ n ][ ordinal ];
248 zstring const tmp( if_space( ones[ n % 10 ][ ordinal ] ) );
249 return tens[ n / 10 ][ ordinal && tmp.empty() ] + tmp;
250}
251
252} // namespace english_impl
253
254/**
255 * Converts a signed integer to English, e.g, 42 becomes "forty two".
256 *
257 * @param n The integer to convert.
258 * @param ordinal If \c true, ordinal words ("forty second") are returned.
259 * @return Returns \a n in English.
260 */
261static zstring english( int64_t n, bool ordinal = false ) {
262 using namespace english_impl;
263
264 if ( !n )
265 return ordinal ? "zeroth" : "zero";
266
267 bool const negative = n < 0;
268 if ( negative )
269 n = -n;
270
271 int big_count = 0;
272 bool big_ordinal = ordinal;
273 zstring r;
274
275 while ( n ) {
276 if ( int64_t const m = n % 1000 ) {
277 zstring s;
278 if ( m < 100 )
279 s = hundreds( m, ordinal );
280 else {
281 zstring const tmp( if_space( hundreds( m % 100, ordinal ) ) );
282 s = ones[ m / 100 ][0] + ' '
283 + (ordinal && tmp.empty() ? "hundredth" : "hundred") + tmp;
284 }
285 zstring const tmp( if_space( r ) );
286 r = s + if_space( big[ big_count ][ big_ordinal && tmp.empty() ] + tmp );
287 big_ordinal = false;
288 }
289 n /= 1000;
290 ++big_count;
291 ordinal = false;
292 }
293
294 if ( negative )
295 r = "negative " + r;
296 return r;
297}
298
299///////////////////////////////////////////////////////////////////////////////
300
301static bool is_grouping_separator( unicode::code_point cp ) {
302 using namespace unicode;
303 //
304 // XQuery 3.0 F&O: 4.6.1: a grouping-separator-sign is a non-alphanumeric
305 // character, that is a character whose Unicode category is other than Nd,
306 // Nl, No, Lu, Ll, Lt, Lm or Lo.
307 //
308 return !( is_category( cp, Nd )
309 || is_category( cp, Nl )
310 || is_category( cp, No )
311 || is_category( cp, Lu )
312 || is_category( cp, Ll )
313 || is_category( cp, Lt )
314 || is_category( cp, Lm )
315 || is_category( cp, Lo )
316 );
317}
318
319///////////////////////////////////////////////////////////////////////////////
320
321/**
322 * Returns the English ordinal suffix for an integer, e.g., "st" for 1, "nd"
323 * for 2, etc.
324 *
325 * @param n The integer to return the ordinal suffix for.
326 * @return Returns said suffix.
327 */
328static char const* ordinal( int n ) {
329 n = std::abs( n );
330 switch ( n % 100 ) {
331 case 11:
332 case 12:
333 case 13:
334 break;
335 default:
336 switch ( n % 10 ) {
337 case 1: return "st";
338 case 2: return "nd";
339 case 3: return "rd";
340 }
341 }
342 return "th";
343}
344
345///////////////////////////////////////////////////////////////////////////////
346
347/**
348 * A unary_function to convert a (presumed) lower-case string to title-case
349 * "Like This."
350 */
351class to_title : public unary_function<char,char> {
352public:
353 to_title() : capitalize_( true ) { }
354
355 result_type operator()( argument_type c ) {
356 if ( ascii::is_alpha( c ) ) {
357 if ( capitalize_ ) {
358 c = ascii::to_upper( c );
359 capitalize_ = false;
360 }
361 } else if ( ascii::is_space( c ) )
362 capitalize_ = true;
363 return c;
364 };
365
366private:
367 bool capitalize_;
368};
369
370///////////////////////////////////////////////////////////////////////////////
371
372static void append_number( int n, modifier const &mod, zstring *dest ) {
373 switch ( mod.first.type ) {
374 case modifier::arabic: {
375 utf8::itou_buf_type buf;
376 zstring tmp( utf8::itou( n, buf, mod.first.zero ) );
377 if ( mod.second.co_type == modifier::ordinal )
378 tmp += ordinal( n );
379 *dest += mod.left_pad_zero( &tmp );
380 break;
381 }
382
383 case modifier::alpha:
384 case modifier::ALPHA: {
385 zstring tmp( alpha( n, mod.first.type == modifier::ALPHA ) );
386 *dest += mod.right_pad_space( &tmp );
387 break;
388 }
389
390 case modifier::roman:
391 case modifier::ROMAN: {
392 ostringstream oss;
393 if ( mod.first.type == modifier::ROMAN )
394 oss << uppercase;
395 oss << roman( n );
396 zstring tmp( oss.str() );
397 *dest += mod.right_pad_space( &tmp );
398 break;
399 }
400
401 case modifier::words: {
402 zstring tmp( english( n, mod.second.co_type == modifier::ordinal ) );
403 *dest += mod.right_pad_space( &tmp );
404 break;
405 }
406
407 case modifier::Words: {
408 zstring tmp( english( n, mod.second.co_type == modifier::ordinal ) );
409 std::transform( tmp.begin(), tmp.end(), tmp.begin(), to_title() );
410 *dest += mod.right_pad_space( &tmp );
411 break;
412 }
413
414 case modifier::WORDS: {
415 zstring tmp( english( n, mod.second.co_type == modifier::ordinal ) );
416 ascii::to_upper( tmp );
417 *dest += mod.right_pad_space( &tmp );
418 break;
419 }
420
421 default:
422 /* handled elsewhere */;
423 }
424}
425
426static void append_fractional_seconds( int n, modifier const &mod,
427 zstring *dest ) {
428 switch ( mod.first.type ) {
429 case modifier::arabic:
430 if ( mod.min_width || mod.max_width ) {
431 if ( mod.max_width ) {
432 double const f = (double)n / DateTime::FRAC_SECONDS_UPPER_LIMIT;
433 double const p = ::pow( 10, mod.max_width );
434 n = (int)( f * p + 0.5 );
435 } else
436 n = (int)( n * 1000.0 / DateTime::FRAC_SECONDS_UPPER_LIMIT );
437
438 ascii::itoa_buf_type buf;
439 zstring tmp( ascii::itoa( n, buf ) );
440
441 if ( tmp.size() < mod.min_width )
442 ascii::right_pad( &tmp, mod.min_width, '0' );
443 else if ( mod.min_width > 0 )
444 while ( tmp.size() > mod.min_width &&
445 tmp[ tmp.size() - 1 ] == '0' ) {
446 tmp = tmp.substr( 0, tmp.size() - 1 );
447 }
448 *dest += tmp;
449 break;
450 }
451 n = (int)( n * 1000.0 / DateTime::FRAC_SECONDS_UPPER_LIMIT );
452 // no break;
453 default:
454 append_number( n, mod, dest );
455 }
456}
457
458static void append_string( zstring const &s, modifier const &mod,
459 zstring *dest ) {
460 zstring tmp;
461 switch ( mod.first.type ) {
462 case modifier::name:
463 utf8::to_lower( s, &tmp );
464 break;
465 case modifier::Name: {
466 utf8::to_upper( s.substr( 0, 1 ), &tmp );
467 zstring tmp2;
468 utf8::to_lower( s.substr( 1 ), &tmp2 );
469 tmp += tmp2;
470 break;
471 }
472 case modifier::NAME:
473 utf8::to_upper( s, &tmp );
474 break;
475 default:
476 break;
477 }
478 *dest += mod.right_pad_space( &tmp );
479}
480
481static void append_month( unsigned mon, modifier const &mod, zstring *dest ) {
482 switch ( mod.first.type ) {
483 case modifier::name:
484 case modifier::Name:
485 case modifier::NAME: {
486 zstring name( locale::get_month_name( mon, mod.lang, mod.country ) );
487 utf8_string<zstring> u_name( name );
488 if ( mod.gt_max_width( u_name.size() ) ) {
489 //
490 // XQuery 3.0 F&O: 9.8.4.1: If the full representation of the value
491 // exceeds the specified maximum width, then the processor should
492 // attempt to use an alternative shorter representation that fits
493 // within the maximum width. Where the presentation modifier is N, n,
494 // or Nn, this is done by abbreviating the name, using either
495 // conventional abbreviations if available, or crude right-truncation
496 // if not.
497 //
498 name = locale::get_month_abbr( mon, mod.lang, mod.country );
499 if ( mod.gt_max_width( u_name.size() ) )
500 u_name = u_name.substr( 0, mod.max_width );
501 }
502 mod.append_if_fallback_lang( dest );
503 append_string( name, mod, dest );
504 break;
505 }
506 default:
507 append_number( mon + 1, mod, dest );
508 }
509}
510
511static void append_timezone( char component, TimeZone const &tz,
512 modifier const &mod, zstring *dest ) {
513 ascii::itoa_buf_type buf;
514 zstring format, tmp;
515 bool has_grouping_separators;
516
517 if ( mod.first.format.empty() ) {
518 format = "01:01";
519 has_grouping_separators = true;
520 } else {
521 format = mod.first.format;
522 has_grouping_separators = mod.first.has_grouping_separators;
523 }
524
525 int hour = tz.getHours();
526 int const min = std::abs( tz.getMinutes() );
527
528 switch ( mod.first.type ) {
529 case modifier::NAME:
530 //
531 // XQuery 3.0 F&O: 9.8.4.2: If the first presentation modifier is N, then
532 // the timezone is output (where possible) as a timezone name, for
533 // example EST or CET. The same timezone offset has different names in
534 // different places; it is therefore recommended that this option should
535 // be used only if a country code or Olson timezone name is supplied in
536 // the $place argument. In the absence of this information, the
537 // implementation may apply a default, for example by using the timezone
538 // names that are conventional in North America. If no timezone name can
539 // be identified, the timezone offset is output using the fallback format
540 // +01:01.
541 //
542 if ( !min )
543 switch ( hour ) {
544 case 0: tmp += "GMT"; goto append;
545 case -5: tmp += "EST"; goto append;
546 case -6: tmp += "CST"; goto append;
547 case -7: tmp += "MST"; goto append;
548 case -8: tmp += "PST"; goto append;
549 }
550 // TODO: use Olson timezone names
551 goto fallback;
552
553 case modifier::military_tz:
554 //
555 // Ibid: If the first presentation modifier is Z, then the timezone is
556 // formatted as a military timezone letter, using the convention Z =
557 // +00:00, A = +01:00, B = +02:00, ..., M = +12:00, N = -01:00, O =
558 // -02:00, ... Y = -12:00.
559 //
560 if ( tz.timeZoneNotSet() ) {
561 //
562 // Ibid: The letter J (meaning local time) is used in the case of a
563 // value that does not specify a timezone offset.
564 //
565 tmp += 'J';
566 break;
567 }
568 if ( hour >= -12 && hour <= 12 && !min ) {
569 tmp += time::get_military_tz( hour );
570 break;
571 }
572 //
573 // Ibid: Timezone offsets that have no representation in this system
574 // (for example Indian Standard Time, +05:30) are output as if the
575 // format 01:01 had been requested.
576 //
577 // no break;
578
579fallback:
580 format = "01:01";
581 // no break;
582
583 default:
584 if ( component == 'z' ) {
585 //
586 // Ibid: When the component specifier is z, the output is the same as
587 // for component specifier Z, except that it is prefixed by the
588 // characters GMT or some localized equivalent. The prefix is omitted,
589 // however, in cases where the timezone is identified by name rather
590 // than by a numeric offset from UTC.
591 //
592 tmp = "GMT";
593 }
594
595 if ( mod.second.at_type == modifier::traditional && !hour && !min ) {
596 //
597 // Ibid: If the first presentation modifier is numeric, in any of the
598 // above formats, and the second presentation modifier is t, then a
599 // zero timezone offset (that is, UTC) is output as Z instead of a
600 // signed numeric value.
601 //
602 tmp += 'Z';
603 break;
604 }
605
606 if ( tz.isNegative() )
607 tmp += '-', hour = std::abs( hour );
608 else
609 tmp += '+';
610
611 if ( has_grouping_separators ) {
612 //
613 // Ibid: If the first presentation modifier is numeric with a grouping-
614 // separator (for example 1:01 or 01.01), then the timezone offset is
615 // output in hours and minutes, separated by the grouping separator,
616 // even if the number of minutes is zero: for example +5:00 or +10.30.
617 //
618 int grouping_separators = 0;
619 bool got_digit = false;
620 int hm_width[] = { 0, 0 }; // hour/minute widths
621 utf8_string<zstring const> const u_format( format );
622 utf8_string<zstring> u_tmp( tmp );
623
624 FOR_EACH( utf8_string<zstring const>, i, u_format ) {
625 unicode::code_point const cp = *i;
626 if ( unicode::is_Nd( cp ) ) {
627 got_digit = true;
628 if ( grouping_separators < 2 )
629 ++hm_width[ grouping_separators ];
630 continue;
631 }
632 if ( got_digit && is_grouping_separator( cp ) ) {
633 if ( ++grouping_separators == 1 ) {
634 zstring tmp2( utf8::itou( hour, buf, mod.first.zero ) );
635 tmp += utf8::left_pad( &tmp2, hm_width[0], mod.first.zero );
636 }
637 } else if ( grouping_separators )
638 grouping_separators = 99;
639 u_tmp += cp;
640 }
641
642 if ( hm_width[1] ) {
643 zstring tmp2( utf8::itou( min, buf, mod.first.zero ) );
644 tmp += utf8::left_pad( &tmp2, hm_width[1], mod.first.zero );
645 }
646 } else {
647 utf8_string<zstring const> const u_format( format );
648 utf8_string<zstring const>::size_type const u_size( u_format.size() );
649
650 if ( u_size <= 2 ) {
651 //
652 // Ibid: If the first presentation modifier is numeric and comprises
653 // one or two digits with no grouping-separator (for example 1 or
654 // 01), then the timezone is formatted as a displacement from UTC in
655 // hours, preceded by a plus or minus sign: for example -5 or +03. If
656 // the actual timezone offset is not an integral number of hours,
657 // then the minutes part of the offset is appended, separated by a
658 // colon: for example +10:30 or -1:15.
659 //
660 zstring tmp2( utf8::itou( hour, buf, mod.first.zero ) );
661 tmp += utf8::left_pad( &tmp2, u_size, mod.first.zero );
662 if ( min ) {
663 tmp2 = utf8::itou( min, buf, mod.first.zero );
664 tmp += ':';
665 tmp += utf8::left_pad( &tmp2, 2, mod.first.zero );
666 }
667 break;
668 }
669 if ( u_size <= 4 ) {
670 //
671 // Ibid: If the first presentation modifier is numeric and comprises
672 // three or four digits with no grouping-separator, for example 001
673 // or 0001, then the timezone offset is shown in hours and minutes
674 // with no separator, for example -0500 or +1030.
675 //
676 int const hhmm = hour * 100 + min;
677 zstring tmp2( utf8::itou( hhmm, buf, mod.first.zero ) );
678 tmp += utf8::left_pad( &tmp2, u_size, mod.first.zero );
679 break;
680 }
681 } // else
682 } // switch
683
684append:
685 *dest += tmp;
686}
687
688static void append_weekday( unsigned mday, unsigned mon, unsigned year,
689 modifier const &mod, zstring *dest ) {
690 int wday = time::calc_wday( mday, mon, year );
691
692 modifier mod_copy( mod );
693 if ( !mod.first.parsed )
694 mod_copy.first.type = modifier::name;
695
696 switch ( mod_copy.first.type ) {
697 case modifier::name:
698 case modifier::Name:
699 case modifier::NAME: {
700 zstring name( locale::get_weekday_name( wday, mod.lang, mod.country ) );
701 utf8_string<zstring> u_name( name );
702 if ( mod.gt_max_width( u_name.size() ) ) {
703 //
704 // XQuery 3.0 F&O: 9.8.4.1: If the full representation of the value
705 // exceeds the specified maximum width, then the processor should
706 // attempt to use an alternative shorter representation that fits
707 // within the maximum width. Where the presentation modifier is N, n,
708 // or Nn, this is done by abbreviating the name, using either
709 // conventional abbreviations if available, or crude right-truncation
710 // if not.
711 //
712 name = locale::get_weekday_abbr( wday, mod.lang, mod.country );
713 if ( mod.gt_max_width( u_name.size() ) )
714 u_name = u_name.substr( 0, mod.max_width );
715 }
716 mod.append_if_fallback_lang( dest );
717 append_string( name, mod_copy, dest );
718 break;
719 }
720 default: {
721 int const new_wday = calendar::convert_wday_to( wday, mod.cal );
722 if ( mod.cal_is_fallback || new_wday == -1 ) {
723 //
724 // Ibid: If the fallback representation uses a different calendar from
725 // that requested, the output string must identify the calendar
726 // actually used, for example by prefixing the string with [Calendar:
727 // X] (where X is the calendar actually used), localized as appropriate
728 // to the requested language.
729 //
730 ostringstream oss;
731 // TODO: localize "Calendar"
732 oss << "[Calendar: "
733 << ( new_wday == -1 ? calendar::get_default() : mod.cal ) << ']';
734 *dest += oss.str();
735 } else
736 wday = new_wday;
737 append_number( wday, mod_copy, dest );
738 }
739 }
740}
741
742static void append_week_in_year( unsigned mday, unsigned mon, unsigned year,
743 modifier const &mod, zstring *dest ) {
744 int week = time::calendar::calc_week_in_year( mday, mon, year, mod.cal );
745 if ( week == -1 ) {
746 week = time::calendar::calc_week_in_year( mday, mon, year, calendar::ISO );
747 ostringstream oss;
748 // TODO: localize "Calendar"
749 oss << "[Calendar: " << calendar::string_of[ calendar::ISO ] << ']';
750 *dest += oss.str();
751 }
752 append_number( week, mod, dest );
753}
754
755static void append_year( int year, modifier const &mod, zstring *s ) {
756 zstring tmp;
757 append_number( year, mod, &tmp );
758
759 if ( mod.first.type == modifier::arabic ) {
760 utf8_string<zstring> u_tmp( tmp );
761 utf8_string<zstring>::size_type const u_size = u_tmp.size();
762 if ( mod.gt_max_width( u_size ) ) {
763 //
764 // XQuery 3.0 F&O: 9.8.4.1: If the full representation of the value
765 // exceeds the specified maximum width, then the processor should attempt
766 // to use an alternative shorter representation that fits within the
767 // maximum width. ... In the case of the year component, setting
768 // max-width requests omission of high-order digits from the year, for
769 // example, if max-width is set to 2 then the year 2003 will be output as
770 // 03.
771 //
772 u_tmp = u_tmp.substr( u_size - mod.max_width );
773 }
774 }
775 *s += tmp;
776}
777
778static void parse_first_modifier( zstring const &picture_str,
779 zstring::const_iterator *i,
780 modifier *mod, QueryLoc const &loc ) {
781 zstring::const_iterator &j = *i;
782 ascii::skip_whitespace( picture_str, &j );
783 if ( j == picture_str.end() || *j == ',' ) {
784 //
785 // Assume that the ',' is the start of the width modifier (hence there is
786 // neither a first nor second modifier).
787 //
788 return;
789 }
790
791 utf8_string<zstring const> const u_picture_str( picture_str );
792 utf8_string<zstring const>::const_iterator u( u_picture_str.current( j ) );
793 utf8_string<zstring> u_mod_format( mod->first.format );
794 unicode::code_point cp = *u;
795
796 if ( cp != '#' && is_grouping_separator( cp ) ) {
797 //
798 // XQuery 3.0 F&O: 4.6.1: A grouping-separator-sign must not appear
799 // at the start ... of the decimal-digit-pattern ....
800 //
801 throw XQUERY_EXCEPTION(
802 err::FOFD1340,
803 ERROR_PARAMS(
804 picture_str,
805 ZED( FOFD1340_NoGroupSepAtStart_3 ),
806 unicode::printable_cp( cp )
807 ),
808 ERROR_LOC( loc )
809 );
810 }
811
812 //
813 // Because of:
814 //
815 // Ibid: if a variable marker contains one or more commas, then the last
816 // comma is treated as introducing the width modifier, and all others are
817 // treated as grouping separators.
818 //
819 // we have to count the number of commas in order to know when we've reached
820 // the last one.
821 //
822 int commas = 0;
823 for ( zstring::const_iterator c( *i ); c != picture_str.end(); ++c )
824 if ( *c == ',' )
825 ++commas;
826
827 unicode::code_point zero[2];
828
829 if ( cp == '#' || unicode::is_Nd( cp, &zero[0] ) ) {
830 bool got_grouping_separator = false;
831 bool got_mandatory_digit = cp != '#';
832
833 u_mod_format = *u;
834 while ( ++u != u_picture_str.end() ) {
835 cp = *u;
836 if ( cp == '#' ) {
837 if ( got_mandatory_digit ) {
838 //
839 // Ibid: There may be zero or more optional-digit-signs, and (if
840 // present) these must precede all mandatory-digit-signs.
841 //
842 throw XQUERY_EXCEPTION(
843 err::FOFD1340,
844 ERROR_PARAMS(
845 picture_str,
846 ZED( FOFD1340_NoOptDigitAfterMandatory )
847 ),
848 ERROR_LOC( loc )
849 );
850 }
851 got_grouping_separator = false;
852 } else if ( unicode::is_Nd( cp, &zero[ got_mandatory_digit ] ) ) {
853 if ( got_mandatory_digit ) {
854 if ( zero[1] != zero[0] ) {
855 //
856 // Ibid: All mandatory-digit-signs within the format token must be
857 // from the same digit family, where a digit family is a sequence
858 // of ten consecutive characters in Unicode category Nd, having
859 // digit values 0 through 9.
860 //
861 throw XQUERY_EXCEPTION(
862 err::FOFD1340,
863 ERROR_PARAMS(
864 picture_str,
865 ZED( FOFD1340_DigitNotSameFamily_34 ),
866 unicode::printable_cp( cp ),
867 unicode::printable_cp( zero[1] )
868 ),
869 ERROR_LOC( loc )
870 );
871 }
872 //
873 // Ibid: A format token containing more than one digit, such as 001
874 // or 9999, sets the minimum and maximum width to the number of
875 // digits appearing in the format token.
876 //
877 if ( !mod->min_width )
878 mod->min_width = mod->max_width = 2;
879 else
880 mod->min_width = ++mod->max_width;
881 } else
882 got_mandatory_digit = true;
883 got_grouping_separator = false;
884 } else if ( cp == ';' || cp == ']' )
885 break;
886 else if ( unicode::is_space( cp ) )
887 continue;
888 else if ( is_grouping_separator( cp ) ) {
889 if ( cp == ',' && !--commas ) {
890 //
891 // Ibid: if a variable marker contains one or more commas, then the
892 // last comma is treated as introducing the width modifier, and all
893 // others are treated as grouping separators.
894 //
895 break;
896 }
897 if ( got_grouping_separator ) {
898 //
899 // Ibid: A grouping-separator-sign must not appear ... adjacent to
900 // another grouping-separator-sign.
901 //
902 throw XQUERY_EXCEPTION(
903 err::FOFD1340,
904 ERROR_PARAMS(
905 picture_str,
906 ZED( FOFD1340_NoAdjacentGroupSep_3 ),
907 unicode::printable_cp( cp )
908 ),
909 ERROR_LOC( loc )
910 );
911 }
912 got_grouping_separator = true;
913 mod->first.has_grouping_separators = true;
914 } else
915 break;
916
917 u_mod_format += cp;
918 } // while
919 if ( got_grouping_separator ) {
920 //
921 // Ibid: A grouping-separator-sign must not appear at the ... end of the
922 // decimal-digit-pattern ....
923 //
924 throw XQUERY_EXCEPTION(
925 err::FOFD1340,
926 ERROR_PARAMS(
927 picture_str,
928 ZED( FOFD1340_NoGroupSepAtEnd_3 ),
929 unicode::printable_cp( cp )
930 ),
931 ERROR_LOC( loc )
932 );
933 }
934 if ( !got_mandatory_digit ) {
935 //
936 // Ibid: There must be at least one mandatory-digit-sign.
937 //
938 throw XQUERY_EXCEPTION(
939 err::FOFD1340,
940 ERROR_PARAMS( picture_str, ZED( FOFD1340_MustBeOneMandatoryDigit ) ),
941 ERROR_LOC( loc )
942 );
943 }
944 mod->first.zero = zero[0];
945 j = u.base();
946 } else {
947 switch ( *j++ ) {
948 case 'A':
949 mod->first.type = modifier::ALPHA;
950 break;
951 case 'a':
952 mod->first.type = modifier::alpha;
953 break;
954 case 'I':
955 mod->first.type = modifier::ROMAN;
956 break;
957 case 'i':
958 mod->first.type = modifier::roman;
959 break;
960 case 'N':
961 if ( j != picture_str.end() && *j == 'n' )
962 mod->first.type = modifier::Name, ++j;
963 else
964 mod->first.type = modifier::NAME;
965 break;
966 case 'n':
967 mod->first.type = modifier::name;
968 break;
969 case 'W':
970 if ( j != picture_str.end() && *j == 'w' )
971 mod->first.type = modifier::Words, ++j;
972 else
973 mod->first.type = modifier::WORDS;
974 break;
975 case 'w':
976 mod->first.type = modifier::words;
977 break;
978 case 'Z':
979 mod->first.type = modifier::military_tz;
980 break;
981 default:
982 //
983 // Ibid: If an implementation does not support a numbering sequence
984 // represented by the given token, it must use a format token of 1.
985 //
986 mod->first.type = modifier::arabic;
987 } // switch
988 }
989 mod->first.parsed = true;
990}
991
992static void parse_second_modifier( zstring const &picture_str,
993 zstring::const_iterator *i, modifier *mod,
994 QueryLoc const &loc ) {
995 zstring::const_iterator &j = *i;
996 ascii::skip_whitespace( picture_str, &j );
997 if ( j == picture_str.end() )
998 return;
999 switch ( *j ) {
1000 case 'c': mod->second.co_type = modifier::cardinal ; break;
1001 case 'o': mod->second.co_type = modifier::ordinal ; break;
1002 case 'a': mod->second.at_type = modifier::alphabetic ; ++j; return;
1003 case 't': mod->second.at_type = modifier::traditional; ++j; return;
1004 default : return;
1005 }
1006 if ( ++j == picture_str.end() )
1007 return;
1008 if ( *j == '(' ) {
1009 while ( true ) {
1010 if ( ++j == picture_str.end() )
1011 throw XQUERY_EXCEPTION(
1012 err::FOFD1340,
1013 ERROR_PARAMS( picture_str, ZED( CharExpected_3 ), ')' ),
1014 ERROR_LOC( loc )
1015 );
1016 if ( *j == ')' )
1017 break;
1018 mod->second.co_string += *j;
1019 }
1020 ++j;
1021 }
1022}
1023
1024static void parse_width_modifier( zstring const &picture_str,
1025 zstring::const_iterator *i, modifier *mod,
1026 QueryLoc const &loc ) {
1027 zstring::const_iterator &j = *i;
1028
1029 ascii::skip_whitespace( picture_str, &j );
1030 if ( j == picture_str.end() || (*j != ',' && *j != ';') )
1031 return;
1032 ascii::skip_whitespace( picture_str, &++j );
1033 if ( j == picture_str.end() )
1034 goto bad_width_modifier;
1035 if ( *j == '*' ) {
1036 mod->min_width = 0;
1037 ++j;
1038 } else {
1039 try {
1040 mod->min_width = static_cast<modifier::width_type>(
1041 ztd::atoull( j, picture_str.end(), &j )
1042 );
1043 }
1044 catch ( std::exception const& ) {
1045 goto bad_width_modifier;
1046 }
1047 }
1048
1049 mod->max_width = 0;
1050
1051 ascii::skip_whitespace( picture_str, &j );
1052 if ( j == picture_str.end() || *j != '-' )
1053 return;
1054 ascii::skip_whitespace( picture_str, &++j );
1055 if ( j == picture_str.end() )
1056 goto bad_width_modifier;
1057 if ( *j == '*' )
1058 ++j;
1059 else {
1060 try {
1061 mod->max_width = static_cast<modifier::width_type>(
1062 ztd::atoull( j, picture_str.end(), &j )
1063 );
1064 }
1065 catch ( std::exception const& ) {
1066 goto bad_width_modifier;
1067 }
1068 }
1069
1070 return;
1071
1072bad_width_modifier:
1073 throw XQUERY_EXCEPTION(
1074 err::FOFD1340,
1075 ERROR_PARAMS( picture_str, ZED( FOFD1340_BadWidthModifier ) ),
1076 ERROR_LOC( loc )
1077 );
1078}
1079
1080static int get_data_type( char component ) {
1081 switch ( component ) {
1082 case 'D': return DateTime::DAY_DATA;
1083 case 'd': return DateTime::DAY_DATA;
1084 case 'E': return DateTime::YEAR_DATA;
1085 case 'F': return DateTime::DAY_DATA;
1086 case 'f': return DateTime::FRACSECONDS_DATA;
1087 case 'H': return DateTime::HOUR_DATA;
1088 case 'h': return DateTime::HOUR_DATA;
1089 case 'm': return DateTime::MINUTE_DATA;
1090 case 'M': return DateTime::MONTH_DATA;
1091 case 'P': return DateTime::HOUR_DATA;
1092 case 's': return DateTime::SECONDS_DATA;
1093 case 'W': return DateTime::DAY_DATA;
1094 case 'w': return DateTime::DAY_DATA;
1095 case 'Y': return DateTime::YEAR_DATA;
1096 default : return -1;
1097 }
1098}
1099
1100bool FnFormatDateTimeIterator::nextImpl( store::Item_t& result,
1101 PlanState &planState ) const {
1102 zstring picture_str, result_str, item_str;
1103 xs_dateTime dateTime;
1104 calendar::type cal = calendar::unknown;
1105 iso639_1::type lang = iso639_1::unknown;
1106 iso3166_1::type country = iso3166_1::unknown;
1107 bool cal_is_fallback = false, lang_is_fallback = false;
1108 bool in_variable_marker;
1109 store::Item_t item;
1110 PlanIteratorState *state;
1111
1112 DEFAULT_STACK_INIT( PlanIteratorState, state, planState);
1113
1114 if ( !consumeNext( item, theChildren[0].getp(), planState ) ) {
1115 // Got the empty sequence -- return same
1116 STACK_PUSH( false, state );
1117 } else {
1118 dateTime = item->getDateTimeValue();
1119 consumeNext( item, theChildren[1].getp(), planState );
1120 item->getStringValue2( picture_str );
1121
1122 if ( theChildren.size() > 2 ) {
1123 consumeNext( item, theChildren[2].getp(), planState );
1124 if ( !locale::parse( item->getStringValue(), &lang, &country ) ||
1125 !locale::is_supported( lang, country ) ) {
1126 lang = iso639_1::unknown;
1127 lang_is_fallback = true;
1128 }
1129
1130 consumeNext( item, theChildren[3].getp(), planState );
1131 item->getStringValue2( item_str );
1132 // TODO: handle calendar being a QName.
1133 cal = calendar::find( item_str );
1134 if ( !cal )
1135 cal_is_fallback = true;
1136
1137 consumeNext( item, theChildren[4].getp(), planState );
1138 item->getStringValue2( item_str );
1139 // TODO: do something with place
1140 }
1141
1142 if ( !cal ) {
1143 //
1144 // XQuery 3.0 F&O: 9.8.4.3: If the $calendar argument is omitted or is
1145 // set to an empty sequence then the default calendar defined in the
1146 // dynamic context is used.
1147 //
1148 cal = planState.theLocalDynCtx->get_calendar();
1149 }
1150
1151 if ( !lang ) {
1152 //
1153 // Ibid: If the $language argument is omitted or is set to an empty
1154 // sequence, or if it is set to an invalid value or a value that the
1155 // implementation does not recognize, then the processor uses the default
1156 // language defined in the dynamic context.
1157 //
1158 planState.theLocalDynCtx->get_locale( &lang, &country );
1159 }
1160
1161 char component;
1162 in_variable_marker = false;
1163
1164 FOR_EACH( zstring, i, picture_str ) {
1165 if ( !in_variable_marker ) {
1166 switch ( *i ) {
1167 case '[':
1168 if ( ztd::peek( picture_str, i ) == '[' )
1169 ++i;
1170 else {
1171 component = 0;
1172 in_variable_marker = true;
1173 continue;
1174 }
1175 break;
1176 case ']':
1177 if ( ztd::peek( picture_str, i ) == ']' )
1178 ++i;
1179 break;
1180 }
1181 result_str += *i;
1182 continue;
1183 }
1184
1185 if ( ascii::is_space( *i ) )
1186 continue; // ignore all whitespace
1187
1188 switch ( *i ) {
1189 case ']':
1190 if ( !component )
1191 throw XQUERY_EXCEPTION(
1192 err::FOFD1340,
1193 ERROR_PARAMS( picture_str, ZED( FOFD1340_NoComponent ) ),
1194 ERROR_LOC( loc )
1195 );
1196 component = 0;
1197 in_variable_marker = false;
1198 continue;
1199 case 'C':
1200 case 'D':
1201 case 'd':
1202 case 'E':
1203 case 'F':
1204 case 'f':
1205 case 'H':
1206 case 'h':
1207 case 'M':
1208 case 'm':
1209 case 'P':
1210 case 's':
1211 case 'W':
1212 case 'w':
1213 case 'Y':
1214 case 'Z':
1215 case 'z':
1216#if 0
1217 if ( component )
1218 throw XQUERY_EXCEPTION(
1219 err::FOFD1340,
1220 ERROR_PARAMS(
1221 picture_str, ZED( FOFD1340_MultipleComponent_3 ), *i
1222 ),
1223 ERROR_LOC( loc )
1224 );
1225#endif
1226 component = *i;
1227 break;
1228 default:
1229 throw XQUERY_EXCEPTION(
1230 err::FOFD1340,
1231 ERROR_PARAMS( picture_str, ZED( FOFD1340_BadComponent_3 ), *i ),
1232 ERROR_LOC( loc )
1233 );
1234 } // switch
1235 if ( ++i == picture_str.end() )
1236 goto eos;
1237
1238 modifier mod;
1239 mod.lang = lang;
1240 mod.lang_is_fallback = lang_is_fallback;
1241 mod.country = country;
1242 mod.cal = cal;
1243 mod.cal_is_fallback = cal_is_fallback;
1244
1245 if ( *i != ']' ) {
1246 parse_first_modifier( picture_str, &i, &mod, loc );
1247 if ( i == picture_str.end() )
1248 goto eos;
1249 if ( *i != ']' ) {
1250 parse_second_modifier( picture_str, &i, &mod, loc );
1251 if ( i == picture_str.end() )
1252 goto eos;
1253 parse_width_modifier( picture_str, &i, &mod, loc );
1254 if ( i == picture_str.end() )
1255 goto eos;
1256 }
1257 }
1258 if ( *i == ']' )
1259 --i;
1260
1261 int const data_type = get_data_type( component );
1262 if ( data_type != -1 && !DateTime::FACET_MEMBERS[facet_type][data_type] )
1263 throw XQUERY_EXCEPTION(
1264 err::FOFD1350, ERROR_PARAMS( component ), ERROR_LOC( loc )
1265 );
1266
1267 switch ( component ) {
1268 case 'C': { // calendar
1269 modifier mod_copy( mod );
1270 if ( !mod.first.parsed )
1271 mod_copy.first.type = modifier::name;
1272 append_string( "gregorian", mod_copy, &result_str );
1273 break;
1274 }
1275 case 'D':
1276 append_number( dateTime.getDay(), mod, &result_str );
1277 break;
1278 case 'd':
1279 append_number( dateTime.getDayOfYear(), mod, &result_str );
1280 break;
1281 case 'E': { // era
1282 modifier mod_copy( mod );
1283 if ( !mod.first.parsed )
1284 mod_copy.first.type = modifier::name;
1285 int const year = dateTime.getYear();
1286 zstring const era( year > 0 ? "ad" : year < 0 ? "bc" : "" );
1287 append_string( era, mod_copy, &result_str );
1288 break;
1289 }
1290 case 'F': {
1291 modifier mod_copy( mod );
1292 if ( !mod.first.parsed )
1293 mod_copy.first.type = modifier::name;
1294 append_weekday(
1295 dateTime.getDay(), dateTime.getMonth() - 1, dateTime.getYear(),
1296 mod_copy, &result_str
1297 );
1298 break;
1299 }
1300 case 'f':
1301 append_fractional_seconds(
1302 dateTime.getFractionalSeconds(), mod, &result_str
1303 );
1304 break;
1305 case 'H': // hour (24 hours)
1306 append_number( dateTime.getHours(), mod, &result_str );
1307 break;
1308 case 'h': // hour (12 hours)
1309 // Convert hour from: 0 1 ... 12 13 ... 23
1310 // to: 12 1 ... 12 1 ... 11
1311 append_number(
1312 1 + (11 + dateTime.getHours()) % 12, mod, &result_str
1313 );
1314 break;
1315 case 'M':
1316 append_month( dateTime.getMonth() - 1, mod, &result_str );
1317 break;
1318 case 'm': {
1319 modifier mod_copy( mod );
1320 mod_copy.set_default_width( 2 );
1321 append_number( dateTime.getMinutes(), mod_copy, &result_str );
1322 break;
1323 }
1324 case 'P': {
1325 modifier mod_copy( mod );
1326 if ( !mod.first.parsed )
1327 mod_copy.first.type = modifier::name;
1328 append_string(
1329 locale::get_time_ampm( dateTime.getHours() >= 12, lang, country ),
1330 mod_copy, &result_str
1331 );
1332 break;
1333 }
1334 case 's': {
1335 modifier mod_copy( mod );
1336 mod_copy.set_default_width( 2 );
1337 append_number( dateTime.getIntSeconds(), mod_copy, &result_str );
1338 break;
1339 }
1340 case 'W':
1341 append_week_in_year(
1342 dateTime.getDay(), dateTime.getMonth() - 1, dateTime.getYear(),
1343 mod, &result_str
1344 );
1345 break;
1346 case 'w':
1347 append_number( dateTime.getWeekInMonth(), mod, &result_str );
1348 break;
1349 case 'Y':
1350 append_year( std::abs( dateTime.getYear() ), mod, &result_str );
1351 break;
1352 case 'Z':
1353 case 'z':
1354 append_timezone(
1355 component, dateTime.getTimezone(), mod, &result_str
1356 );
1357 break;
1358 } // switch
1359 } // for
1360
1361 if ( in_variable_marker )
1362eos: throw XQUERY_EXCEPTION(
1363 err::FOFD1340,
1364 ERROR_PARAMS( picture_str, ZED( CharExpected_3 ), ']' ),
1365 ERROR_LOC( loc )
1366 );
1367
1368 STACK_PUSH( GENV_ITEMFACTORY->createString( result, result_str ), state );
1369 }
1370
1371 STACK_END( state );
1372}
1373
1374///////////////////////////////////////////////////////////////////////////////
1375
1376} // namespace zorba
1377/* vim:set et sw=2 ts=2: */
01378
=== added file 'src/runtime/durations_dates_times/format_dateTime.h'
--- src/runtime/durations_dates_times/format_dateTime.h 1970-01-01 00:00:00 +0000
+++ src/runtime/durations_dates_times/format_dateTime.h 2013-03-21 16:00:34 +0000
@@ -0,0 +1,81 @@
1/*
2 * Copyright 2006-2008 The FLWOR Foundation.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#ifndef ZORBA_RUNTIME_FORMAT_DATETIME_H
18#define ZORBA_RUNTIME_FORMAT_DATETIME_H
19
20#include "common/shared_types.h"
21#include "zorbatypes/datetime.h"
22
23#include "runtime/base/binarybase.h"
24#include "runtime/base/unarybase.h"
25#include "runtime/base/narybase.h"
26
27namespace zorba {
28
29///////////////////////////////////////////////////////////////////////////////
30
31// XQuery 3.0 DateTime formatting
32class FnFormatDateTimeIterator :
33 public NaryBaseIterator<FnFormatDateTimeIterator,PlanIteratorState>
34{
35
36public:
37 SERIALIZABLE_CLASS(FnFormatDateTimeIterator);
38
39 SERIALIZABLE_CLASS_CONSTRUCTOR2T(
40 FnFormatDateTimeIterator,
41 NaryBaseIterator<FnFormatDateTimeIterator, PlanIteratorState >);
42
43 void serialize( ::zorba::serialization::Archiver &ar )
44 {
45 serialize_baseclass(ar,
46 (NaryBaseIterator<FnFormatDateTimeIterator, PlanIteratorState >*)this);
47
48 SERIALIZE_ENUM(DateTime::FACET_TYPE, facet_type);
49 }
50
51public:
52 FnFormatDateTimeIterator(
53 static_context *sctx,
54 QueryLoc const &loc,
55 std::vector<PlanIter_t> &aChildren,
56 DateTime::FACET_TYPE a_facet_type = DateTime::DATETIME_FACET)
57 :
58 NaryBaseIterator<FnFormatDateTimeIterator, PlanIteratorState>(sctx, loc, aChildren),
59 facet_type(a_facet_type)
60 {
61 }
62
63 void accept( PlanIterVisitor& ) const;
64
65 bool nextImpl( store::Item_t&, PlanState& ) const;
66
67private:
68 DateTime::FACET_TYPE facet_type;
69};
70
71///////////////////////////////////////////////////////////////////////////////
72
73} // namespace zorba
74
75#endif /* ZORBA_RUNTIME_FORMAT_DATETIME_H */
76/*
77 * Local variables:
78 * mode: c++
79 * End:
80 */
81/* vim:set et sw=2 ts=2: */
082
=== modified file 'src/runtime/visitors/printer_visitor_impl.cpp'
--- src/runtime/visitors/printer_visitor_impl.cpp 2013-03-05 12:34:19 +0000
+++ src/runtime/visitors/printer_visitor_impl.cpp 2013-03-21 16:00:34 +0000
@@ -46,6 +46,7 @@
46#include "runtime/core/arithmetic_impl.h"46#include "runtime/core/arithmetic_impl.h"
47#include "runtime/sequences/SequencesImpl.h"47#include "runtime/sequences/SequencesImpl.h"
48#include "runtime/durations_dates_times/DurationsDatesTimesImpl.h"48#include "runtime/durations_dates_times/DurationsDatesTimesImpl.h"
49#include "runtime/durations_dates_times/format_dateTime.h"
49#ifdef ZORBA_WITH_DEBUGGER50#ifdef ZORBA_WITH_DEBUGGER
50#include "runtime/debug/debug_iterator.h"51#include "runtime/debug/debug_iterator.h"
51#endif52#endif
5253
=== modified file 'src/unit_tests/CMakeLists.txt'
--- src/unit_tests/CMakeLists.txt 2013-03-17 04:47:01 +0000
+++ src/unit_tests/CMakeLists.txt 2013-03-21 16:00:34 +0000
@@ -22,6 +22,7 @@
22 test_mem_sizeof.cpp22 test_mem_sizeof.cpp
23 test_parameters.cpp23 test_parameters.cpp
24 test_string.cpp24 test_string.cpp
25 test_time.cpp
25 test_time_parse.cpp26 test_time_parse.cpp
26 test_uri.cpp27 test_uri.cpp
27 test_uuid.cpp28 test_uuid.cpp
2829
=== added file 'src/unit_tests/test_time.cpp'
--- src/unit_tests/test_time.cpp 1970-01-01 00:00:00 +0000
+++ src/unit_tests/test_time.cpp 2013-03-21 16:00:34 +0000
@@ -0,0 +1,118 @@
1/*
2 * Copyright 2006-2008 The FLWOR Foundation.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "stdafx.h"
18
19#include <cstring>
20#include <functional>
21#include <iostream>
22#include <stdexcept>
23#include <string>
24
25#include "util/ascii_util.h"
26#include "util/stl_util.h"
27#include "util/time_util.h"
28#include "zorbatypes/zstring.h"
29
30using namespace std;
31using namespace zorba;
32using namespace zorba::time;
33
34///////////////////////////////////////////////////////////////////////////////
35
36static int failures;
37static int test_no;
38
39static bool assert_true( int no, char const *expr, int line, bool result ) {
40 if ( !result ) {
41 cout << '#' << no << " FAILED, line " << line << ": " << expr << endl;
42 ++failures;
43 }
44 return result;
45}
46
47#define ASSERT_TRUE( NO, EXPR ) assert_true( NO, #EXPR, __LINE__, !!(EXPR) )
48
49///////////////////////////////////////////////////////////////////////////////
50
51static void test_calc_week_in_year() {
52 struct test_type {
53 unsigned mday, mon, year;
54 time::calendar::type cal;
55 int expected;
56 };
57 static test_type const test[] = {
58 /* 1 */ { 1, time::jan, 2013, calendar::AD, 1 },
59 /* 2 */ { 2, time::jan, 2013, calendar::AD, 1 },
60 /* 3 */ { 3, time::jan, 2013, calendar::AD, 1 },
61 /* 4 */ { 4, time::jan, 2013, calendar::AD, 1 },
62 /* 5 */ { 5, time::jan, 2013, calendar::AD, 1 },
63 /* 6 */ { 6, time::jan, 2013, calendar::AD, 2 },
64 /* 7 */ { 28, time::dec, 2013, calendar::AD, 52 },
65 /* 8 */ { 31, time::dec, 2013, calendar::AD, 53 },
66
67 /* 9 */ { 1, time::jan, 2013, calendar::ISO, 1 },
68 /* 10 */ { 2, time::jan, 2013, calendar::ISO, 1 },
69 /* 11 */ { 3, time::jan, 2013, calendar::ISO, 1 },
70 /* 12 */ { 4, time::jan, 2013, calendar::ISO, 1 },
71 /* 13 */ { 5, time::jan, 2013, calendar::ISO, 1 },
72 /* 14 */ { 6, time::jan, 2013, calendar::ISO, 1 },
73 /* 15 */ { 7, time::jan, 2013, calendar::ISO, 2 },
74
75 // Test cases taken from http://en.wikipedia.org/wiki/ISO_week_date
76 /* 16 */ { 1, time::jan, 2005, calendar::ISO, 53 },
77 /* 17 */ { 2, time::jan, 2005, calendar::ISO, 53 },
78 /* 18 */ { 31, time::dec, 2005, calendar::ISO, 52 },
79 /* 19 */ { 1, time::jan, 2007, calendar::ISO, 1 },
80 /* 20 */ { 30, time::dec, 2007, calendar::ISO, 52 },
81 /* 21 */ { 31, time::dec, 2007, calendar::ISO, 1 },
82 /* 22 */ { 1, time::jan, 2008, calendar::ISO, 1 },
83 /* 23 */ { 28, time::dec, 2008, calendar::ISO, 52 },
84 /* 24 */ { 29, time::dec, 2008, calendar::ISO, 1 },
85 /* 25 */ { 30, time::dec, 2008, calendar::ISO, 1 },
86 /* 26 */ { 31, time::dec, 2008, calendar::ISO, 1 },
87 /* 27 */ { 31, time::dec, 2009, calendar::ISO, 53 },
88 /* 28 */ { 1, time::jan, 2010, calendar::ISO, 53 },
89 /* 29 */ { 2, time::jan, 2010, calendar::ISO, 53 },
90 /* 30 */ { 3, time::jan, 2010, calendar::ISO, 53 },
91 /* 31 */ { 4, time::jan, 2010, calendar::ISO, 1 },
92
93 { 0 },
94 };
95
96 for ( test_type const *t = test; t->mday; ++t ) {
97 int w = calendar::calc_week_in_year( t->mday, t->mon, t->year, t->cal );
98 ++test_no;
99 ASSERT_TRUE( test_no, w == t->expected );
100 }
101}
102
103///////////////////////////////////////////////////////////////////////////////
104
105namespace zorba {
106namespace UnitTests {
107
108int test_time( int, char*[] ) {
109
110 test_calc_week_in_year();
111
112 cout << failures << " test(s) failed\n";
113 return failures ? 1 : 0;
114}
115
116} // namespace UnitTests
117} // namespace zorba
118/* vim:set et sw=2 ts=2: */
0119
=== modified file 'src/unit_tests/unit_test_list.h'
--- src/unit_tests/unit_test_list.h 2013-03-17 04:47:01 +0000
+++ src/unit_tests/unit_test_list.h 2013-03-21 16:00:34 +0000
@@ -41,6 +41,7 @@
41 int test_mem_sizeof( int, char*[] );41 int test_mem_sizeof( int, char*[] );
42 int test_parameters( int, char*[] );42 int test_parameters( int, char*[] );
43 int test_string( int, char*[] );43 int test_string( int, char*[] );
44 int test_time( int, char*[] );
44 int test_time_parse( int, char*[] );45 int test_time_parse( int, char*[] );
4546
46#ifdef ZORBA_WITH_FILE_ACCESS47#ifdef ZORBA_WITH_FILE_ACCESS
4748
=== modified file 'src/unit_tests/unit_tests.cpp'
--- src/unit_tests/unit_tests.cpp 2013-03-17 04:47:01 +0000
+++ src/unit_tests/unit_tests.cpp 2013-03-21 16:00:34 +0000
@@ -56,6 +56,7 @@
56 libunittests["json_parser"] = test_json_parser;56 libunittests["json_parser"] = test_json_parser;
57 libunittests["parameters"] = test_parameters;57 libunittests["parameters"] = test_parameters;
58 libunittests["string"] = test_string;58 libunittests["string"] = test_string;
59 libunittests["time"] = test_time;
59 libunittests["time_parse"] = test_time_parse;60 libunittests["time_parse"] = test_time_parse;
6061
61#ifndef ZORBA_NO_FULL_TEXT62#ifndef ZORBA_NO_FULL_TEXT
6263
=== modified file 'src/util/ascii_util.h'
--- src/util/ascii_util.h 2013-03-19 04:22:49 +0000
+++ src/util/ascii_util.h 2013-03-21 16:00:34 +0000
@@ -22,6 +22,7 @@
22#include <cctype>22#include <cctype>
23#include <cstddef>23#include <cstddef>
24#include <cstring>24#include <cstring>
25#include <iterator>
2526
26// local27// local
27#include "omanip.h"28#include "omanip.h"
@@ -1147,9 +1148,62 @@
1147 *pos = trim_start_whitespace( s + *pos, s_len - *pos ) - s;1148 *pos = trim_start_whitespace( s + *pos, s_len - *pos ) - s;
1148}1149}
11491150
1151/**
1152 * Skips any consecutive whitespace chars that are found at a given starting
1153 * position within a given string.
1154 *
1155 * @tparam StringType The string type.
1156 * @param s The string.
1157 * @param i A pointer to the iterator to advance past the whitespace.
1158 * On return, \a *i is updated with the position of the 1st non-whitespace
1159 * char.
1160 */
1161template<class StringType> inline
1162void skip_whitespace( StringType const &s,
1163 typename StringType::const_iterator *i ) {
1164 typename StringType::difference_type const d = *i - s.begin();
1165 char const *const sd = s.data() + d;
1166 std::advance( *i, trim_start_whitespace( sd, s.size() - d ) - sd );
1167}
1168
1150////////// Miscellaneous //////////////////////////////////////////////////////1169////////// Miscellaneous //////////////////////////////////////////////////////
11511170
1152/**1171/**
1172 * Pads a string to the left with a given character until the string is the
1173 * given width.
1174 *
1175 * @param s The string to pad.
1176 * @param width The width to pad to.
1177 * @param c The character to pad with.
1178 * @return Returns \c *s.
1179 */
1180template<class StringType> inline
1181StringType& left_pad( StringType *s, typename StringType::size_type width,
1182 char c ) {
1183 typedef typename StringType::size_type size_type;
1184 if ( s->size() < width )
1185 s->insert( static_cast<size_type>( 0 ), width - s->size(), c );
1186 return *s;
1187}
1188
1189/**
1190 * Pads a string to the right with a given character until the string is the
1191 * given width.
1192 *
1193 * @param s The string to pad.
1194 * @param width The width to pad to.
1195 * @param c The character to pad with.
1196 * @return Returns \c *s.
1197 */
1198template<class StringType> inline
1199StringType& right_pad( StringType *s, typename StringType::size_type width,
1200 char c ) {
1201 if ( s->size() < width )
1202 s->append( width - s->size(), c );
1203 return *s;
1204}
1205
1206/**
1153 * Prints the given character in a printable way: if \c is_print(c) is \c true,1207 * Prints the given character in a printable way: if \c is_print(c) is \c true,
1154 * prints \a c as-is; otherwise prints \c #x followed by the hexadecimal value1208 * prints \a c as-is; otherwise prints \c #x followed by the hexadecimal value
1155 * of the character.1209 * of the character.
11561210
=== modified file 'src/util/stream_util.cpp'
--- src/util/stream_util.cpp 2013-03-16 20:44:27 +0000
+++ src/util/stream_util.cpp 2013-03-21 16:00:34 +0000
@@ -70,6 +70,37 @@
70 return buf - buf_orig;70 return buf - buf_orig;
71}71}
7272
73ostream& roman( ostream &o, unsigned n ) {
74 //
75 // Based on http://rosettacode.org/wiki/Roman_numerals/Encode#C.2B.2B
76 //
77 struct roman_data {
78 unsigned value;
79 char const *numeral[2];
80 };
81 static roman_data const data[] = {
82 1000, { "m", "M" },
83 900, { "cm", "CM" },
84 500, { "d", "D" },
85 400, { "cd", "CD" },
86 100, { "c", "C" },
87 90, { "xc", "XC" },
88 50, { "l", "L" },
89 40, { "xl", "XL" },
90 10, { "x", "X" },
91 9, { "ix", "IX" },
92 5, { "v", "V" },
93 4, { "iv", "IV" },
94 1, { "i", "I" },
95 0, { 0, 0 }
96 };
97 bool const uc = !!(o.flags() & ios::uppercase);
98 for ( roman_data const *r = data; r->value > 0; ++r )
99 for ( ; n >= r->value; n -= r->value )
100 o << r->numeral[ uc ];
101 return o;
102}
103
73///////////////////////////////////////////////////////////////////////////////104///////////////////////////////////////////////////////////////////////////////
74105
75} // namespace zorba106} // namespace zorba
76107
=== modified file 'src/util/stream_util.h'
--- src/util/stream_util.h 2013-03-16 20:44:27 +0000
+++ src/util/stream_util.h 2013-03-21 16:00:34 +0000
@@ -20,6 +20,7 @@
2020
21#include <iostream>21#include <iostream>
2222
23#include "omanip.h"
23#include "string_util.h"24#include "string_util.h"
2425
25namespace zorba {26namespace zorba {
@@ -73,6 +74,19 @@
73std::streamsize read_without_whitespace( std::istream &is, char *buf,74std::streamsize read_without_whitespace( std::istream &is, char *buf,
74 std::streamsize n );75 std::streamsize n );
7576
77/**
78 * Emits an integer as Roman numerals to the given ostream. By default,
79 * numerals are emitted in lower-case. To emit in upper-case, set the
80 * \c uppercase format flag on the stream.
81 *
82 * @param o The ostream to emit to.
83 * @param n The integer to emit.
84 * @return Returns \a o.
85 */
86std::ostream& roman( std::ostream &o, unsigned n );
87
88DEF_OMANIP1( roman, unsigned )
89
76///////////////////////////////////////////////////////////////////////////////90///////////////////////////////////////////////////////////////////////////////
7791
78} // namespace zorba92} // namespace zorba
7993
=== modified file 'src/util/time_util.cpp'
--- src/util/time_util.cpp 2013-02-13 01:57:47 +0000
+++ src/util/time_util.cpp 2013-03-21 16:00:34 +0000
@@ -16,7 +16,9 @@
1616
17#include "stdafx.h"17#include "stdafx.h"
1818
19#include <algorithm>
19#include <cassert>20#include <cassert>
21#include <cstring>
20#ifdef WIN3222#ifdef WIN32
21# include <windows.h>23# include <windows.h>
22# include <time.h> /* for gmtime_s() */24# include <time.h> /* for gmtime_s() */
@@ -31,13 +33,138 @@
31#endif /* WIN32 */33#endif /* WIN32 */
3234
33// local35// local
36#include "less.h"
34#include "time_util.h"37#include "time_util.h"
3538
39#define DEF_END(CHAR_ARRAY) \
40 static char const *const *const end = \
41 CHAR_ARRAY + sizeof( CHAR_ARRAY ) / sizeof( char* )
42
43#define FIND(WHAT) \
44 static_cast<type>( find_index( string_of, end, WHAT ) )
45
46using namespace std;
47
48/**
49 * A less-verbose way to use std::lower_bound.
50 */
51inline int find_index( char const *const *begin, char const *const *end,
52 char const *s ) {
53 char const *const *const entry =
54 ::lower_bound( begin, end, s, less<char const*>() );
55 return entry != end && ::strcmp( s, *entry ) == 0 ? entry - begin : 0;
56}
57
36namespace zorba {58namespace zorba {
37namespace time {59namespace time {
3860
39///////////////////////////////////////////////////////////////////////////////61///////////////////////////////////////////////////////////////////////////////
4062
63namespace iso8601 {
64 /**
65 * Weekday values as used by the ISO 8601 specification.
66 */
67 enum weekday {
68 mon = 1,
69 tue = 2,
70 wed = 3,
71 thu = 4,
72 fri = 5,
73 sat = 6,
74 sun = 7
75 };
76}
77
78namespace calendar {
79
80char const *const string_of[] = {
81 "#UNKNOWN",
82 "AD", // Anno Domini (Christian Era)
83 "AH", // Anno Hegirae (Muhammedan Era)
84 "AM", // Anno Mundi (Jewish)
85 "AME", // Mauludi Era (solar years since Mohammed's birth)
86 "AP", // Anno Persici
87 "AS", // Aji Saka Era (Java)
88 "BE", // Buddhist Era
89 "CB", // Cooch Behar Era
90 "CE", // Common Era
91 "CL", // Chinese Lunar Era
92 "CS", // Chula Sakarat Era
93 "EE", // Ethiopian Era
94 "FE", // Fasli Era
95 "ISO", // ISO 8601 calendar
96 "JE", // Japanese
97 "KE", // Khalsa Era (Sikh calendar)
98 "KY", // Kali Yuga
99 "ME", // Malabar Era
100 "MS", // Monarchic Solar Era
101 "OS", // Old Style (Julian)
102 "RS", // Rattanakosin (Bangkok) Era
103 "SE", // Saka Era
104 "SH", // Mohammedan Solar Era (Iran)
105 "SS", // Saka Samvat
106 "TE", // Tripurabda Era
107 "VE", // Vikrama Era
108 "VS" // Vikrama Samvat Era
109};
110
111int calc_week_in_year( unsigned mday, unsigned mon, unsigned year, type cal ) {
112 int yday = time::calc_yday( mday, mon, year );
113 int jan1_wday = time::calc_wday( 1, time::jan, year );
114
115 switch ( cal ) {
116 case AD:
117 return (jan1_wday + yday) / 7 + 1;
118 case ISO: {
119 // Based on http://www.personal.ecu.edu/mccartyr/ISOwdALG.txt
120 ++yday; // code assumes [1-366]
121 jan1_wday = convert_wday_to( jan1_wday, cal );
122
123 if ( jan1_wday > iso8601::thu && jan1_wday + yday <= 8 ) {
124 // date falls in week 52 or 53 of the previous year
125 return 52
126 + (jan1_wday == iso8601::fri ||
127 (jan1_wday == iso8601::sat && time::is_leap_year( year - 1 )));
128 }
129 int const wday =
130 convert_wday_to( time::calc_wday( mday, mon, year ), cal );
131 if ( time::days_in_year( year ) - yday < 4 - wday ) {
132 // date falls in week 1 of the next year
133 return 1;
134 }
135 return (yday + (7 - wday) + (jan1_wday - 1)) / 7
136 - (jan1_wday > iso8601::thu);
137 }
138 default:
139 return -1;
140 }
141}
142
143int convert_wday_from( unsigned wday, type from ) {
144 switch ( from ) {
145 case AD : return static_cast<int>( wday );
146 case ISO: return wday == iso8601::sun ? time::sun : wday;
147 default : return -1;
148 }
149}
150
151int convert_wday_to( unsigned wday, type to ) {
152 switch ( to ) {
153 case AD : return static_cast<int>( wday );
154 case ISO: return wday == time::sun ? iso8601::sun : wday;
155 default : return -1;
156 }
157}
158
159type find( char const *calendar ) {
160 DEF_END( string_of );
161 return FIND( calendar );
162}
163
164} // namespace calendar
165
166///////////////////////////////////////////////////////////////////////////////
167
41static unsigned const yday_mon[][13] = {168static unsigned const yday_mon[][13] = {
42 // 0 1 2 3 4 5 6 7 8 9 10 11 12169 // 0 1 2 3 4 5 6 7 8 9 10 11 12
43 { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 }, // non-leap170 { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 }, // non-leap
@@ -48,7 +175,7 @@
48175
49bool calc_mday_mon( unsigned yday, unsigned *mday, unsigned *mon,176bool calc_mday_mon( unsigned yday, unsigned *mday, unsigned *mon,
50 unsigned year ) {177 unsigned year ) {
51 assert( yday < 365 + is_leap_year( year ) );178 assert( yday < days_in_year( year ) );
52179
53 unsigned const *const ym = yday_mon[ is_leap_year( year ) ];180 unsigned const *const ym = yday_mon[ is_leap_year( year ) ];
54 for ( unsigned m = 1; m <= 12; ++m ) 181 for ( unsigned m = 1; m <= 12; ++m )
@@ -102,31 +229,31 @@
102 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE229 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
103 * USE OR OTHER DEALINGS IN THE SOFTWARE.230 * USE OR OTHER DEALINGS IN THE SOFTWARE.
104 *231 *
105 * @param mday Month day: 1-31.232 * @param mday The month day [1-31].
106 * @param mon Month: 0-11.233 * @param mon The month [0-11].
107 * @param year Year.234 * @param year The year.
108 * @return Returns the weekday where 0 = Sunday.235 * @return Returns the weekday [0-6] where 0 = Sunday.
109 */236 */
110unsigned calc_wday( unsigned mday, unsigned mon, unsigned year ) {237int calc_wday( unsigned mday, unsigned mon, unsigned year ) {
111 assert( mday >= 1 );238 assert( mday >= 1 );
112 assert( mday <= days_in_month( mon, year ) );239 assert( mday <= days_in_month( mon, year ) );
113 assert( mon < 12 );240 assert( mon < 12 );
114241
115 ++mon; // Tondering's algorithm assumes month value in range 1-12.242 ++mon; // Tondering's algorithm assumes month value in range 1-12.
116 unsigned const a = (14 - mon) / 12;243 int const a = (14 - mon) / 12;
117 unsigned const y = year - a;244 int const y = year - a;
118 unsigned const m = mon + 12 * a - 2;245 int const m = mon + 12 * a - 2;
119 return (mday + y + y/4 - y/100 + y/400 + (31 * m) / 12) % 7;246 return (mday + y + y/4 - y/100 + y/400 + (31 * m) / 12) % 7;
120}247}
121248
122unsigned calc_yday( unsigned mday, unsigned mon, unsigned year ) {249int calc_yday( unsigned mday, unsigned mon, unsigned year ) {
123 assert( mday >= 1 );250 assert( mday >= 1 );
124 assert( mday <= days_in_month( mon, year ) );251 assert( mday <= days_in_month( mon, year ) );
125 return yday_mon[ is_leap_year( year ) ][ mon ] + mday - 1;252 return (int)yday_mon[ is_leap_year( year ) ][ mon ] + mday - 1;
126}253}
127254
128unsigned days_in_month( unsigned mon, unsigned year ) {255int days_in_month( unsigned mon, unsigned year ) {
129 static unsigned const days[] = {256 static int const days[] = {
130 31, // 0: Jan257 31, // 0: Jan
131 28, // 1: Feb258 28, // 1: Feb
132 31, // 2: Mar259 31, // 2: Mar
@@ -141,7 +268,7 @@
141 31 // 11: Dec268 31 // 11: Dec
142 };269 };
143 assert( mon < 12 );270 assert( mon < 12 );
144 return days[ mon ] + (mon == 1 /* Feb */ && is_leap_year( year ));271 return days[ mon ] + (mon == feb && is_leap_year( year ));
145}272}
146273
147void get_epoch( sec_type *sec, usec_type *usec ) {274void get_epoch( sec_type *sec, usec_type *usec ) {
@@ -202,6 +329,17 @@
202#endif /* WIN32 */329#endif /* WIN32 */
203}330}
204331
332char get_military_tz( int hour ) {
333 hour %= 24;
334 if ( hour > 12 )
335 hour -= 24;
336 else if ( hour < -12 )
337 hour += 24;
338 if ( hour >= 0 && hour <= 12 )
339 return "ZABCDEFGHIKLM" [ hour ]; // no 'J' here (it means "no timezone")
340 return " NOPQRSTUVWXY" [ -hour ];
341}
342
205///////////////////////////////////////////////////////////////////////////////343///////////////////////////////////////////////////////////////////////////////
206344
207} // namespace time345} // namespace time
208346
=== modified file 'src/util/time_util.h'
--- src/util/time_util.h 2013-02-13 01:57:47 +0000
+++ src/util/time_util.h 2013-03-21 16:00:34 +0000
@@ -25,7 +25,9 @@
2525
26// Zorba26// Zorba
27#include <zorba/config.h>27#include <zorba/config.h>
28#include <zorba/time.h>
28#include "cxx_util.h"29#include "cxx_util.h"
30#include "string_util.h"
2931
30#ifndef TM_YEAR_BASE32#ifndef TM_YEAR_BASE
31# define TM_YEAR_BASE 190033# define TM_YEAR_BASE 1900
@@ -36,14 +38,22 @@
3638
37///////////////////////////////////////////////////////////////////////////////39///////////////////////////////////////////////////////////////////////////////
3840
41/**
42 * A type to hold a number of seconds (at least since epoch).
43 */
39typedef time_t sec_type;44typedef time_t sec_type;
4045
46/**
47 * A type to hold a number of microseconds.
48 */
41#ifdef WIN3249#ifdef WIN32
42typedef unsigned long usec_type;50typedef unsigned long usec_type;
43#else51#else
44typedef suseconds_t usec_type;52typedef suseconds_t usec_type;
45#endif /* WIN32 */53#endif /* WIN32 */
4654
55///////////////////////////////////////////////////////////////////////////////
56
47//57//
48// If the OS's tm struct has a GMT-timezone offset field, simply typedef tm as58// If the OS's tm struct has a GMT-timezone offset field, simply typedef tm as
49// ztm; otherwise declare ztm as a struct derived from tm that adds a59// ztm; otherwise declare ztm as a struct derived from tm that adds a
@@ -71,12 +81,129 @@
71///////////////////////////////////////////////////////////////////////////////81///////////////////////////////////////////////////////////////////////////////
7282
73/**83/**
84 * XQuery 3.0 F&O: 9.8.4.3: The calendars listed below were known to be in use
85 * during the last hundred years.
86 */
87namespace calendar {
88 extern char const* const string_of[];
89
90 /**
91 * Emits a calendar::type to an ostream.
92 *
93 * @param o The ostream to emit to.
94 * @param t The type to emit.
95 * @return Returns \a o.
96 */
97 inline std::ostream& operator<<( std::ostream &o, type t ) {
98 return o << string_of[ t ];
99 }
100
101 /**
102 * Calculates the week number for the given date and calendar.
103 *
104 * @param mday The month day [1-31].
105 * @param mon The month [0-11].
106 * @param year The year.
107 * @param cal The calendar.
108 * @return Returns the week [1-53] or -1 if it is unknown how to perform the
109 * calculation for \a cal.
110 */
111 int calc_week_in_year( unsigned mday, unsigned mon, unsigned year, type cal );
112
113 /**
114 * Converts a weekday number from a given calendar to the Unix interpretation
115 * [0-6] where 0 = Sunday.
116 *
117 * @param wday The weekday to convert where the meaning of the value is
118 * determined by \a from.
119 * @param from The calendar designator to convert \a wday from.
120 * @return Returns \a wday converted to \a to or -1 if it is unknown how to
121 * perform the conversion.
122 */
123 int convert_wday_from( unsigned wday, type from );
124
125 /**
126 * Converts a Unix weekday number to a specific calendar.
127 *
128 * @param wday The weekday to convert: [0-6] where 0 = Sunday.
129 * @param to The calendar designator to convert \a wday to.
130 * @return Returns \a wday converted to \a to or -1 if it is unknown how to
131 * perform the conversion.
132 */
133 int convert_wday_to( unsigned wday, type to );
134
135 /**
136 * Finds a calendar designator from the given string.
137 *
138 * @param calendar The calendar designator to find. It is presumed to be in
139 * upper-case.
140 * @return Returns said enumeration or \c unknown.
141 */
142 type find( char const *calendar );
143
144 //
145 // Template version of find().
146 //
147 template<class StringType> inline
148 typename std::enable_if<
149 ztd::has_c_str<StringType,char const* (StringType::*)() const>::value,
150 type
151 >::type
152 find( StringType const &calendar ) {
153 return find( calendar.c_str() );
154 }
155
156 /**
157 * Gets the default calendar to use.
158 *
159 * @return Returns said calendar.
160 */
161 inline type get_default() {
162 return AD; // i.e., the Gregorian calendar
163 }
164
165} // namespace calendar
166
167///////////////////////////////////////////////////////////////////////////////
168
169/**
170 * Month (<code>mod</code>) values as used by the \c tm structure.
171 */
172enum month {
173 jan = 0,
174 feb = 1,
175 mar = 2,
176 apr = 3,
177 may = 4,
178 jun = 5,
179 jul = 6,
180 aug = 7,
181 sep = 8,
182 oct = 9,
183 nov = 10,
184 dec = 11
185};
186
187/**
188 * Weekday (<code>wday</code>) values as used by the \c tm structure.
189 */
190enum weekday {
191 sun = 0,
192 mon = 1,
193 tue = 2,
194 wed = 3,
195 thu = 4,
196 fri = 5,
197 sat = 6
198};
199
200/**
74 * Calculates the day of the month and month from the given day of the year.201 * Calculates the day of the month and month from the given day of the year.
75 *202 *
76 * @param yday The year day (0-365) where 0 = January 1.203 * @param yday The year day [0-365] where 0 = January 1.
77 * @param mday A pointer to the result for the month day (1-31) or \c null if204 * @param mday A pointer to the result for the month day [1-31] or \c null if
78 * this is not desired.205 * this is not desired.
79 * @param mon A pointer to the result for the month (0-11) or \c null if this206 * @param mon A pointer to the result for the month [0-11] or \c null if this
80 * is not desired.207 * is not desired.
81 * @param year The year.208 * @param year The year.
82 * @return Returns \c true if \a yday and \a year are a valid combination and209 * @return Returns \c true if \a yday and \a year are a valid combination and
@@ -88,31 +215,31 @@
88/**215/**
89 * Calculates the weekday for the given date.216 * Calculates the weekday for the given date.
90 *217 *
91 * @param mday The month day (1-31).218 * @param mday The month day [1-31].
92 * @param mon The month (0-11).219 * @param mon The month [0-11].
93 * @param year The year.220 * @param year The year.
94 * @return Returns the weekday (0-6) where 0 = Sunday.221 * @return Returns the weekday [0-6] where 0 = Sunday.
95 */222 */
96unsigned calc_wday( unsigned mday, unsigned mon, unsigned year );223int calc_wday( unsigned mday, unsigned mon, unsigned year );
97224
98/**225/**
99 * Calculates the day of the year for the given date.226 * Calculates the day of the year for the given date.
100 *227 *
101 * @param mday The month day (1-31).228 * @param mday The month day [1-31].
102 * @param mon The month (0-11).229 * @param mon The month [0-11].
103 * @param year The year.230 * @param year The year.
104 * @return Returns the day of the year (0-365) where 0 = January 1.231 * @return Returns the day of the year [0-365] where 0 = January 1.
105 */232 */
106unsigned calc_yday( unsigned mday, unsigned mon, unsigned year );233int calc_yday( unsigned mday, unsigned mon, unsigned year );
107234
108/**235/**
109 * Gets the number of days in the given month.236 * Gets the number of days in the given month.
110 *237 *
111 * @param mon The month (0-11).238 * @param mon The month [0-11].
112 * @param year The year.239 * @param year The year.
113 * @return Returns said number of days (1-31).240 * @return Returns said number of days, one of: 28, 29, 30, or 31.
114 */241 */
115unsigned days_in_month( unsigned mon, unsigned year );242int days_in_month( unsigned mon, unsigned year );
116243
117/**244/**
118 * Gets the number of seconds and microseconds since epoch.245 * Gets the number of seconds and microseconds since epoch.
@@ -150,6 +277,14 @@
150void get_localtime( ztm *tm, sec_type when = 0 );277void get_localtime( ztm *tm, sec_type when = 0 );
151278
152/**279/**
280 * Gets the military timezone letter code for the given GMT hour offset.
281 *
282 * @param hour The number of hours offset from GMT.
283 * @return Returns one of ABCDEFGHIKLMNOPQRSTUVWXYZ (no J).
284 */
285char get_military_tz( int hour );
286
287/**
153 * Checks whether the given year is a leap year.288 * Checks whether the given year is a leap year.
154 *289 *
155 * @param year The year to check.290 * @param year The year to check.
@@ -160,43 +295,53 @@
160}295}
161296
162/**297/**
298 * Gets the number of days in the given year.
299 *
300 * @param year The year.
301 * @return Returns said number of days, either: 365 or 366.
302 */
303inline int days_in_year( unsigned year ) {
304 return 365 + is_leap_year( year );
305}
306
307/**
163 * Checks whether the given day of the month is valid.308 * Checks whether the given day of the month is valid.
164 *309 *
165 * @param mday The month day (1-31).310 * @param mday The month day [1-31].
166 * @param mon The month (0-11).311 * @param mon The month [0-11].
167 * @param year The year.312 * @param year The year.
168 * @return Returns \a true only if the given day of the month is valid.313 * @return Returns \a true only if the given day of the month is valid.
169 */314 */
170inline bool is_mday_valid( unsigned mday, unsigned mon, unsigned year ) {315inline bool is_mday_valid( unsigned mday, unsigned mon, unsigned year ) {
171 return mday >= 1 && mday <= days_in_month( mon, year );316 return mday >= 1 && (int)mday <= days_in_month( mon, year );
172}317}
173318
174/**319/**
175 * Checks whether the given weekday is valid.320 * Checks whether the given weekday is valid.
176 *321 *
177 * @param wday The weekday (0-6) where 0 = Sunday.322 * @param wday The weekday [0-6] where 0 = Sunday.
178 * @param mday The month day (1-31).323 * @param mday The month day [1-31].
179 * @param mon The month (0-11).324 * @param mon The month [0-11].
180 * @param year The year.325 * @param year The year.
181 * @return Returns \a true only if the given weekday is valid.326 * @return Returns \a true only if the given weekday is valid.
182 */327 */
183inline bool is_wday_valid( unsigned wday, unsigned mday, unsigned mon,328inline bool is_wday_valid( unsigned wday, unsigned mday, unsigned mon,
184 unsigned year ) {329 unsigned year ) {
185 return wday == calc_wday( mday, mon, year );330 return (int)wday == calc_wday( mday, mon, year );
186}331}
187332
188/**333/**
189 * Checks whether the given day of the year is valid.334 * Checks whether the given day of the year is valid.
190 *335 *
191 * @param yday The day of the year (0-365).336 * @param yday The day of the year [0-365].
192 * @param mday The month day (1-31).337 * @param mday The month day [1-31].
193 * @param mon The month (0-11).338 * @param mon The month [0-11].
194 * @param year The year.339 * @param year The year.
195 * @return Returns \a true only if the given day of the year is valid.340 * @return Returns \a true only if the given day of the year is valid.
196 */341 */
197inline bool is_yday_valid( unsigned yday, unsigned mday, unsigned mon,342inline bool is_yday_valid( unsigned yday, unsigned mday, unsigned mon,
198 unsigned year ) {343 unsigned year ) {
199 return yday == calc_yday( mday, mon, year );344 return (int)yday == calc_yday( mday, mon, year );
200}345}
201346
202///////////////////////////////////////////////////////////////////////////////347///////////////////////////////////////////////////////////////////////////////
203348
=== modified file 'src/util/unicode_util.cpp'
--- src/util/unicode_util.cpp 2013-02-07 17:24:36 +0000
+++ src/util/unicode_util.cpp 2013-03-21 16:00:34 +0000
@@ -28,6 +28,7 @@
28# include <unicode/ustring.h>28# include <unicode/ustring.h>
29#endif /* ZORBA_NO_ICU */29#endif /* ZORBA_NO_ICU */
3030
31#include "ascii_util.h"
31#include "cxx_util.h"32#include "cxx_util.h"
32#include "unicode_util.h"33#include "unicode_util.h"
33#include "utf8_util.h"34#include "utf8_util.h"
@@ -2205,6 +2206,23 @@
2205 return is_case<upper>( c );2206 return is_case<upper>( c );
2206}2207}
22072208
2209ostream& printable_cp( ostream &o, code_point cp ) {
2210 if ( ascii::is_print( cp ) )
2211 o << static_cast<char>( cp );
2212 else
2213 switch ( cp ) {
2214 case '\n': o << "\\n"; break;
2215 case '\r': o << "\\r"; break;
2216 case '\t': o << "\\t"; break;
2217 default: {
2218 ios::fmtflags const old_flags = o.flags();
2219 o << "#x" << uppercase << hex << static_cast<uint32_t>( cp );
2220 o.flags( old_flags );
2221 }
2222 }
2223 return o;
2224}
2225
2208code_point to_lower( code_point c ) {2226code_point to_lower( code_point c ) {
2209 return to_case<lower>( c );2227 return to_case<lower>( c );
2210}2228}
22112229
=== modified file 'src/util/unicode_util.h'
--- src/util/unicode_util.h 2013-02-28 11:15:32 +0000
+++ src/util/unicode_util.h 2013-03-21 16:00:34 +0000
@@ -32,6 +32,7 @@
32# include <unicode/unistr.h>32# include <unicode/unistr.h>
33#endif /* ZORBA_NO_ICU */33#endif /* ZORBA_NO_ICU */
3434
35#include "omanip.h"
35#include "stl_util.h"36#include "stl_util.h"
3637
37namespace zorba {38namespace zorba {
@@ -426,6 +427,22 @@
426 return c >= 0x10000 && c <= 0x10FFFF;427 return c >= 0x10000 && c <= 0x10FFFF;
427}428}
428429
430////////// Miscellaneous //////////////////////////////////////////////////////
431
432/**
433 * Prints the given code-point in a printable way: if \c ascii::is_print(c) is
434 * \c true, prints \a c as-is; otherwise prints \c #x followed by the
435 * hexadecimal value of the character.
436 *
437 * @param o The ostream to print to.
438 * @param cp The \c code-point to print.
439 * @return Returns \a o.
440 */
441std::ostream& printable_cp( std::ostream &o, code_point cp );
442
443// An ostream manipulator version of the above.
444DEF_OMANIP1( printable_cp, code_point )
445
429///////////////////////////////////////////////////////////////////////////////446///////////////////////////////////////////////////////////////////////////////
430447
431} // namespace unicode448} // namespace unicode
432449
=== modified file 'src/util/utf8_string.h'
--- src/util/utf8_string.h 2013-02-07 17:24:36 +0000
+++ src/util/utf8_string.h 2013-03-21 16:00:34 +0000
@@ -207,8 +207,12 @@
207 typedef typename StringType::const_pointer const_storage_pointer;207 typedef typename StringType::const_pointer const_storage_pointer;
208 typedef typename StringType::reference storage_reference;208 typedef typename StringType::reference storage_reference;
209 typedef typename StringType::const_reference const_storage_reference;209 typedef typename StringType::const_reference const_storage_reference;
210
210 typedef typename StringType::iterator storage_iterator;211 typedef typename StringType::iterator storage_iterator;
211 typedef typename StringType::const_iterator const_storage_iterator;212 typedef typename StringType::const_iterator const_storage_iterator;
213 typedef typename StringType::reverse_iterator storage_reverse_iterator;
214 typedef typename StringType::const_reverse_iterator
215 const_storage_reverse_iterator;
212216
213 typedef typename utf8::iterator<storage_iterator> iterator;217 typedef typename utf8::iterator<storage_iterator> iterator;
214 typedef typename utf8::iterator<const_storage_iterator> const_iterator;218 typedef typename utf8::iterator<const_storage_iterator> const_iterator;
@@ -1005,6 +1009,16 @@
1005 }1009 }
10061010
1007 /**1011 /**
1012 * Returns a read-only iterator positioned at the same byte as the given
1013 * iterator of the string.
1014 *
1015 * @return Returns said iterator.
1016 */
1017 const_iterator current( const_storage_iterator const &i ) const {
1018 return const_iterator( i );
1019 }
1020
1021 /**
1008 * Returns a read-only reverse iterator positioned at the first character1022 * Returns a read-only reverse iterator positioned at the first character
1009 * (not byte) of the string.1023 * (not byte) of the string.
1010 * 1024 *
@@ -1024,6 +1038,17 @@
1024 return const_reverse_iterator( begin() );1038 return const_reverse_iterator( begin() );
1025 }1039 }
10261040
1041 /**
1042 * Returns a read-only reverse iterator positioned at the same byte as the
1043 * given reverse iterator of the string.
1044 *
1045 * @return Returns said iterator.
1046 */
1047 const_reverse_iterator
1048 current( const_storage_reverse_iterator const &i ) const {
1049 return const_reverse_iterator( i );
1050 }
1051
1027 ////////// miscellaneous ////////////////////////////////////////////////////1052 ////////// miscellaneous ////////////////////////////////////////////////////
10281053
1029 /**1054 /**
10301055
=== modified file 'src/util/utf8_util.cpp'
--- src/util/utf8_util.cpp 2013-02-07 17:24:36 +0000
+++ src/util/utf8_util.cpp 2013-03-21 16:00:34 +0000
@@ -15,6 +15,9 @@
15 */15 */
16#include "stdafx.h"16#include "stdafx.h"
1717
18#include <algorithm>
19#include <cstring>
20
18#ifndef ZORBA_NO_ICU21#ifndef ZORBA_NO_ICU
19#include <unicode/ustring.h>22#include <unicode/ustring.h>
20#endif /* ZORBA_NO_ICU */23#endif /* ZORBA_NO_ICU */
@@ -144,6 +147,35 @@
144 return len;147 return len;
145}148}
146149
150storage_type* itou( unsigned long long n, storage_type *buf,
151 unicode::code_point zero ) {
152 storage_type *s = buf;
153 encoded_char_type utf8_digit[10]; // cache of UTF-8 bytes for each digit
154 size_type utf8_size[10]; // number of UTF-8 bytes for each digit
155
156 std::fill( utf8_size, utf8_size + 10, 0 );
157 do {
158 unsigned long long const n_prev = n;
159 n /= 10;
160 unsigned const digit = n_prev - n * 10;
161 if ( !utf8_size[ digit ] ) // didn't cache previously: cache now
162 utf8_size[ digit ] = encode( zero + digit, utf8_digit[ digit ] );
163 //
164 // Copy the UTF-8 bytes into buf backwards so when we reverse the entire
165 // buffer later (to reverse the digit order to put them the right way
166 // around), we can treat buf as a simple string and ignore multi-byte UTF-8
167 // character boundaries.
168 //
169 for ( size_type i = utf8_size[ digit ]; i; )
170 *s++ = utf8_digit[ digit ][ --i ];
171
172 } while ( n );
173
174 *s = '\0';
175 std::reverse( buf, s );
176 return buf;
177}
178
147size_type length( storage_type const *begin, storage_type const *end ) {179size_type length( storage_type const *begin, storage_type const *end ) {
148 size_type len = 0;180 size_type len = 0;
149 while ( begin < end && *begin ) {181 while ( begin < end && *begin ) {
150182
=== modified file 'src/util/utf8_util.h'
--- src/util/utf8_util.h 2013-02-07 17:24:36 +0000
+++ src/util/utf8_util.h 2013-03-21 16:00:34 +0000
@@ -306,6 +306,31 @@
306 std::copy( u.begin(), u.end(), std::back_inserter( *c ) );306 std::copy( u.begin(), u.end(), std::back_inserter( *c ) );
307}307}
308308
309////////// Integer-to-string conversion ///////////////////////////////////////
310
311/**
312 * A type that can hold the largest possible C string equivalent of the largest
313 * possible integral value using any Unicode numeric range within the Nd
314 * ("Number, Decimal Digit") category.
315 */
316typedef storage_type itou_buf_type[
317 (sizeof( encoded_char_type ) - 1 /* subtract null */) * 20 + 1 /* add null */
318];
319
320/**
321 * Converts an <code>unsigned long long</code> to a UTF-8 encoded string.
322 *
323 * @param n The <code>unsigned long long</code> to convert.
324 * @param buf The buffer for the result. The caller must ensure it's of
325 * sufficient size.
326 * @param zero The Unicode code-point of the zero at the start of a 10
327 * code-point range [zero,zero+9] for the digits to use in the Nd ("Number,
328 * Decimal Digit") category.
329 * @return Returns \a buf for convenience.
330 */
331storage_type* itou( unsigned long long n, storage_type *buf,
332 unicode::code_point zero );
333
309////////// Encoding conversion ////////////////////////////////////////////////334////////// Encoding conversion ////////////////////////////////////////////////
310335
311#ifndef ZORBA_NO_ICU336#ifndef ZORBA_NO_ICU
@@ -737,6 +762,48 @@
737////////// Miscellaneous //////////////////////////////////////////////////////762////////// Miscellaneous //////////////////////////////////////////////////////
738763
739/**764/**
765 * Pads a string to the left with a given code-point until the string is the
766 * given width.
767 *
768 * @param s The string to pad.
769 * @param width The width to pad to.
770 * @param cp The code-point to pad with.
771 * @return Returns \c *s.
772 */
773template<class StringType> inline
774StringType& left_pad( StringType *s, typename StringType::size_type width,
775 unicode::code_point cp ) {
776 typedef typename utf8_stringify<StringType>::type u_type;
777 typedef typename u_type::size_type u_size_type;
778 u_type u( *s );
779 u_size_type const u_size( u.size() );
780 if ( u_size < width )
781 u.insert( static_cast<size_type>( 0 ), width - u_size, cp );
782 return *s;
783}
784
785/**
786 * Pads a string to the right with a given code-point until the string is the
787 * given width.
788 *
789 * @param s The string to pad.
790 * @param width The width to pad to.
791 * @param cp The code-point to pad with.
792 * @return Returns \c *s.
793 */
794template<class StringType> inline
795StringType& right_pad( StringType *s, typename StringType::size_type width,
796 unicode::code_point cp ) {
797 typedef typename utf8_stringify<StringType>::type u_type;
798 typedef typename u_type::size_type u_size_type;
799 u_type u( *s );
800 u_size_type const u_size( u.size() );
801 if ( u_size < width )
802 u.append( width - u_size, cp );
803 return *s;
804}
805
806/**
740 * Reverses the characters in a string.807 * Reverses the characters in a string.
741 *808 *
742 * @tparam InputStringType The input string type.809 * @tparam InputStringType The input string type.
743810
=== modified file 'src/zorbatypes/datetime.h'
--- src/zorbatypes/datetime.h 2013-03-12 17:03:31 +0000
+++ src/zorbatypes/datetime.h 2013-03-21 16:00:34 +0000
@@ -250,16 +250,10 @@
250 */250 */
251 static int parseGDay(const char* str, ascii::size_type strlen, DateTime& dt);251 static int parseGDay(const char* str, ascii::size_type strlen, DateTime& dt);
252252
253 static int getDayOfWeek(int year, int month, int day);
254
255 static int getDayOfYear(int year, int month, int day);253 static int getDayOfYear(int year, int month, int day);
256254
257 static int getWeekInYear(int year, int month, int day);
258
259 static int getWeekInMonth(int year, int month, int day);255 static int getWeekInMonth(int year, int month, int day);
260256
261 static bool isLeapYear(int year);
262
263protected:257protected:
264 static int parse_date(258 static int parse_date(
265 const char* str,259 const char* str,
@@ -361,11 +355,8 @@
361 * with the index being 0 based, with 0 being Sunday, 1 Monday, etc. If the give 355 * with the index being 0 based, with 0 being Sunday, 1 Monday, etc. If the give
362 * DateTime does not have a Date or DateTime facet, the function will return -1.356 * DateTime does not have a Date or DateTime facet, the function will return -1.
363 */ 357 */
364 int getDayOfWeek() const;
365 int getDayOfYear() const;358 int getDayOfYear() const;
366 int getWeekInYear() const;
367 int getWeekInMonth() const;359 int getWeekInMonth() const;
368 bool isLeapYear() const;
369 360
370protected:361protected:
371 Duration* toDayTimeDuration() const;362 Duration* toDayTimeDuration() const;
372363
=== modified file 'src/zorbatypes/datetime/datetimetype.cpp'
--- src/zorbatypes/datetime/datetimetype.cpp 2013-03-12 17:03:31 +0000
+++ src/zorbatypes/datetime/datetimetype.cpp 2013-03-21 16:00:34 +0000
@@ -39,6 +39,7 @@
39#include "zorbatypes/datetime/parse.h"39#include "zorbatypes/datetime/parse.h"
4040
41#include "util/ascii_util.h"41#include "util/ascii_util.h"
42#include "util/time_util.h"
4243
4344
44namespace zorba45namespace zorba
@@ -47,7 +48,7 @@
47static const char separators[] = { '-', '-', 'T', ':', ':', '.'};48static const char separators[] = { '-', '-', 'T', ':', ':', '.'};
4849
49static const char min_length[] = { 4, 2, 2, 2, 2, 2, 0};50static const char min_length[] = { 4, 2, 2, 2, 2, 2, 0};
50 51
5152
52const int DateTime::FACET_MEMBERS[][8] = 53const int DateTime::FACET_MEMBERS[][8] =
53{54{
@@ -79,7 +80,7 @@
7980
80 for (int i = YEAR_DATA; i <= DAY_DATA; i++)81 for (int i = YEAR_DATA; i <= DAY_DATA; i++)
81 data[i] = 1;82 data[i] = 1;
82 83
83 for (int i = HOUR_DATA; i <= FRACSECONDS_DATA; i++)84 for (int i = HOUR_DATA; i <= FRACSECONDS_DATA; i++)
84 data[i] = 0;85 data[i] = 0;
8586
@@ -158,10 +159,10 @@
158 dt.data[MINUTE_DATA] = std::abs(minutes);159 dt.data[MINUTE_DATA] = std::abs(minutes);
159 dt.data[SECONDS_DATA] = std::floor(std::fabs(seconds));160 dt.data[SECONDS_DATA] = std::floor(std::fabs(seconds));
160 dt.data[FRACSECONDS_DATA] = round(frac(std::fabs(seconds)) * FRAC_SECONDS_UPPER_LIMIT);161 dt.data[FRACSECONDS_DATA] = round(frac(std::fabs(seconds)) * FRAC_SECONDS_UPPER_LIMIT);
161 162
162 if (tz != NULL)163 if (tz != NULL)
163 dt.the_time_zone = *tz;164 dt.the_time_zone = *tz;
164 165
165 return 0;166 return 0;
166}167}
167168
@@ -185,7 +186,7 @@
185 dt.data[MINUTE_DATA] = std::abs(minutes);186 dt.data[MINUTE_DATA] = std::abs(minutes);
186 dt.data[SECONDS_DATA] = std::abs(seconds);187 dt.data[SECONDS_DATA] = std::abs(seconds);
187 dt.data[FRACSECONDS_DATA] = std::abs(fractional_seconds);188 dt.data[FRACSECONDS_DATA] = std::abs(fractional_seconds);
188 189
189 if (tz != NULL)190 if (tz != NULL)
190 dt.the_time_zone = *tz;191 dt.the_time_zone = *tz;
191192
@@ -211,7 +212,7 @@
211212
212 if (tz != NULL)213 if (tz != NULL)
213 dt.the_time_zone = *tz;214 dt.the_time_zone = *tz;
214 215
215 return 0;216 return 0;
216}217}
217218
@@ -231,10 +232,10 @@
231 dt.data[MINUTE_DATA] = std::abs(minutes);232 dt.data[MINUTE_DATA] = std::abs(minutes);
232 dt.data[SECONDS_DATA] = std::floor(std::fabs(seconds));233 dt.data[SECONDS_DATA] = std::floor(std::fabs(seconds));
233 dt.data[FRACSECONDS_DATA] = round(frac(std::fabs(seconds)) * FRAC_SECONDS_UPPER_LIMIT);234 dt.data[FRACSECONDS_DATA] = round(frac(std::fabs(seconds)) * FRAC_SECONDS_UPPER_LIMIT);
234 235
235 if (tz != NULL)236 if (tz != NULL)
236 dt.the_time_zone = *tz;237 dt.the_time_zone = *tz;
237 238
238 return 0;239 return 0;
239}240}
240241
@@ -352,7 +353,7 @@
352 ascii::skip_whitespace(str, len, &pos);353 ascii::skip_whitespace(str, len, &pos);
353354
354 dt.facet = DATETIME_FACET;355 dt.facet = DATETIME_FACET;
355 356
356 if (parse_date(str,357 if (parse_date(str,
357 len,358 len,
358 pos,359 pos,
@@ -363,7 +364,7 @@
363364
364 if (pos == len || str[pos++] != 'T')365 if (pos == len || str[pos++] != 'T')
365 return 1;366 return 1;
366 367
367 if (parse_time(str,368 if (parse_time(str,
368 len,369 len,
369 pos,370 pos,
@@ -372,7 +373,7 @@
372 dt.data[SECONDS_DATA],373 dt.data[SECONDS_DATA],
373 dt.data[FRACSECONDS_DATA]))374 dt.data[FRACSECONDS_DATA]))
374 return 1;375 return 1;
375 376
376 ascii::size_type savepos = pos;377 ascii::size_type savepos = pos;
377378
378 ascii::skip_whitespace(str, len, &pos);379 ascii::skip_whitespace(str, len, &pos);
@@ -387,7 +388,7 @@
387 dt.the_time_zone))388 dt.the_time_zone))
388 return 1;389 return 1;
389 }390 }
390 391
391 if (dt.data[HOUR_DATA] == 24)392 if (dt.data[HOUR_DATA] == 24)
392 {393 {
393 dt.data[HOUR_DATA] = 0;394 dt.data[HOUR_DATA] = 0;
@@ -408,7 +409,7 @@
408 ascii::skip_whitespace(str, len, &pos);409 ascii::skip_whitespace(str, len, &pos);
409410
410 dt.facet = DATE_FACET;411 dt.facet = DATE_FACET;
411 412
412 if (parse_date(str,413 if (parse_date(str,
413 len,414 len,
414 pos,415 pos,
@@ -429,7 +430,7 @@
429 if (0 != TimeZone::parseTimeZone(str + pos, len - pos, dt.the_time_zone))430 if (0 != TimeZone::parseTimeZone(str + pos, len - pos, dt.the_time_zone))
430 return 1;431 return 1;
431 }432 }
432 433
433 return 0;434 return 0;
434}435}
435436
@@ -441,14 +442,14 @@
441 ascii::skip_whitespace(str, len, &pos);442 ascii::skip_whitespace(str, len, &pos);
442443
443 dt.facet = TIME_FACET;444 dt.facet = TIME_FACET;
444 445
445 if (parse_time(str, len, pos,446 if (parse_time(str, len, pos,
446 dt.data[HOUR_DATA],447 dt.data[HOUR_DATA],
447 dt.data[MINUTE_DATA],448 dt.data[MINUTE_DATA],
448 dt.data[SECONDS_DATA],449 dt.data[SECONDS_DATA],
449 dt.data[FRACSECONDS_DATA]))450 dt.data[FRACSECONDS_DATA]))
450 return 1;451 return 1;
451 452
452 ascii::size_type savepos = pos;453 ascii::size_type savepos = pos;
453454
454 ascii::skip_whitespace(str, len, &pos);455 ascii::skip_whitespace(str, len, &pos);
@@ -461,7 +462,7 @@
461 if (0 != TimeZone::parseTimeZone(str + pos, len - pos, dt.the_time_zone))462 if (0 != TimeZone::parseTimeZone(str + pos, len - pos, dt.the_time_zone))
462 return 1;463 return 1;
463 }464 }
464 465
465 if (dt.data[HOUR_DATA] == 24)466 if (dt.data[HOUR_DATA] == 24)
466 dt.data[HOUR_DATA] = 0;467 dt.data[HOUR_DATA] = 0;
467468
@@ -476,11 +477,11 @@
476 zstring temp;477 zstring temp;
477478
478 // GYearMonth of form: '-'? yyyy '-' mm zzzzzz?479 // GYearMonth of form: '-'? yyyy '-' mm zzzzzz?
479 480
480 ascii::skip_whitespace(str, len, &pos);481 ascii::skip_whitespace(str, len, &pos);
481482
482 dt.facet = GYEARMONTH_FACET;483 dt.facet = GYEARMONTH_FACET;
483 484
484 if (str[pos] == '-')485 if (str[pos] == '-')
485 {486 {
486 temp.append(str + pos, (8 < len - pos ? 8 : len - pos));487 temp.append(str + pos, (8 < len - pos ? 8 : len - pos));
@@ -500,7 +501,7 @@
500 dt.data[MONTH_DATA],501 dt.data[MONTH_DATA],
501 dt.data[DAY_DATA]))502 dt.data[DAY_DATA]))
502 return 1;503 return 1;
503 504
504 pos += 7;505 pos += 7;
505506
506 ascii::size_type savepos = pos;507 ascii::size_type savepos = pos;
@@ -527,11 +528,11 @@
527 zstring temp;528 zstring temp;
528529
529 // GYear of form: '-'? yyyy zzzzzz?530 // GYear of form: '-'? yyyy zzzzzz?
530 531
531 ascii::skip_whitespace(str, len, &pos);532 ascii::skip_whitespace(str, len, &pos);
532533
533 dt.facet = GYEAR_FACET;534 dt.facet = GYEAR_FACET;
534 535
535 temp.reserve(12);536 temp.reserve(12);
536537
537 if (str[pos] == '-')538 if (str[pos] == '-')
@@ -553,7 +554,7 @@
553 dt.data[MONTH_DATA],554 dt.data[MONTH_DATA],
554 dt.data[DAY_DATA]))555 dt.data[DAY_DATA]))
555 return 1;556 return 1;
556 557
557 pos += 4;558 pos += 4;
558559
559 ascii::size_type savepos = pos;560 ascii::size_type savepos = pos;
@@ -581,11 +582,11 @@
581582
582 // GMonth of form: --MM zzzzzz?583 // GMonth of form: --MM zzzzzz?
583 // preceding - is not allowed.584 // preceding - is not allowed.
584 585
585 ascii::skip_whitespace(str, len, &pos);586 ascii::skip_whitespace(str, len, &pos);
586587
587 dt.facet = GMONTH_FACET;588 dt.facet = GMONTH_FACET;
588 589
589 if (str[pos++] != '-')590 if (str[pos++] != '-')
590 return 1;591 return 1;
591592
@@ -601,7 +602,7 @@
601 dt.data[MONTH_DATA],602 dt.data[MONTH_DATA],
602 dt.data[DAY_DATA]))603 dt.data[DAY_DATA]))
603 return 1;604 return 1;
604 605
605 pos += 3;606 pos += 3;
606607
607 ascii::size_type savepos = pos;608 ascii::size_type savepos = pos;
@@ -633,10 +634,10 @@
633 ascii::skip_whitespace(str, len, &pos);634 ascii::skip_whitespace(str, len, &pos);
634635
635 dt.facet = GMONTHDAY_FACET;636 dt.facet = GMONTHDAY_FACET;
636 637
637 if (str[pos++] != '-')638 if (str[pos++] != '-')
638 return 1;639 return 1;
639 640
640 temp.reserve(12);641 temp.reserve(12);
641 temp = "0004";642 temp = "0004";
642 temp.append(str + pos, 6); // Year 4 to make it a leap year, to allow the MonthDay of 29 February643 temp.append(str + pos, 6); // Year 4 to make it a leap year, to allow the MonthDay of 29 February
@@ -650,7 +651,7 @@
650 return 1;651 return 1;
651652
652 dt.data[YEAR_DATA] = 1;653 dt.data[YEAR_DATA] = 1;
653 654
654 pos += 6;655 pos += 6;
655656
656 ascii::size_type savepos = pos;657 ascii::size_type savepos = pos;
@@ -678,17 +679,17 @@
678679
679 // GDay of form: ---DD zzzzzz?680 // GDay of form: ---DD zzzzzz?
680 // preceding - is not allowed.681 // preceding - is not allowed.
681 682
682 ascii::skip_whitespace(str, len, &pos);683 ascii::skip_whitespace(str, len, &pos);
683684
684 dt.facet = GDAY_FACET;685 dt.facet = GDAY_FACET;
685 686
686 if (str[pos++] != '-')687 if (str[pos++] != '-')
687 return 1;688 return 1;
688689
689 if (str[pos++] != '-')690 if (str[pos++] != '-')
690 return 1;691 return 1;
691 692
692 temp = "0001-01";693 temp = "0001-01";
693 temp.append(str + pos, 3);694 temp.append(str + pos, 3);
694695
@@ -699,7 +700,7 @@
699 dt.data[MONTH_DATA],700 dt.data[MONTH_DATA],
700 dt.data[DAY_DATA]))701 dt.data[DAY_DATA]))
701 return 1;702 return 1;
702 703
703 pos += 3;704 pos += 3;
704705
705 ascii::size_type savepos = pos;706 ascii::size_type savepos = pos;
@@ -730,7 +731,7 @@
730{731{
731 bool is_negative = false;732 bool is_negative = false;
732 ascii::size_type temp_pos;733 ascii::size_type temp_pos;
733 734
734 if (pos == len)735 if (pos == len)
735 return 1;736 return 1;
736737
@@ -765,18 +766,18 @@
765 // Parse day766 // Parse day
766 if (pos == len || parse_long(str, len, pos, day, 2, 2))767 if (pos == len || parse_long(str, len, pos, day, 2, 2))
767 return 1;768 return 1;
768 769
769 // Validate the date770 // Validate the date
770 // year may not be 0771 // year may not be 0
771 if (year == 0)772 if (year == 0)
772 return 1;773 return 1;
773 774
774 if (month < 1 || month > 12)775 if (month < 1 || month > 12)
775 return 1;776 return 1;
776777
777 if (day < 1 || day > get_last_day(year, month))778 if (day < 1 || day > get_last_day(year, month))
778 return 1;779 return 1;
779 780
780 return 0;781 return 0;
781}782}
782783
@@ -793,7 +794,7 @@
793{794{
794 if (position == len)795 if (position == len)
795 return 1;796 return 1;
796 797
797 // Parse hour798 // Parse hour
798 if (position == len || parse_long(str, len, position, hour, 2, 2))799 if (position == len || parse_long(str, len, position, hour, 2, 2))
799 return 1;800 return 1;
@@ -811,7 +812,7 @@
811 // Parse seconds812 // Parse seconds
812 if (position == len || parse_long(str, len, position, seconds, 2, 2))813 if (position == len || parse_long(str, len, position, seconds, 2, 2))
813 return 1;814 return 1;
814 815
815 if (position < len && str[position] == '.')816 if (position < len && str[position] == '.')
816 {817 {
817 double temp_frac_seconds;818 double temp_frac_seconds;
@@ -830,19 +831,19 @@
830 // Validate the time831 // Validate the time
831 if (hour > 24)832 if (hour > 24)
832 return 1;833 return 1;
833 834
834 if (minute > 59)835 if (minute > 59)
835 return 1;836 return 1;
836837
837 if (hour == 24 && minute != 0)838 if (hour == 24 && minute != 0)
838 return 1;839 return 1;
839 840
840 if (seconds > 59)841 if (seconds > 59)
841 return 1;842 return 1;
842843
843 if (hour == 24 && (seconds != 0 || frac_seconds != 0))844 if (hour == 24 && (seconds != 0 || frac_seconds != 0))
844 return 1;845 return 1;
845 846
846 return 0;847 return 0;
847}848}
848849
@@ -871,18 +872,18 @@
871zstring DateTime::toString() const872zstring DateTime::toString() const
872{873{
873 zstring result;874 zstring result;
874 875
875 // output sign876 // output sign
876 if (FACET_MEMBERS[facet][0])877 if (FACET_MEMBERS[facet][0])
877 if (data[YEAR_DATA] < 0)878 if (data[YEAR_DATA] < 0)
878 result.append("-", 1);879 result.append("-", 1);
879 880
880 // output preceding '-' for Gregorian dates, when needed881 // output preceding '-' for Gregorian dates, when needed
881 if (facet == GMONTH_FACET || facet == GMONTHDAY_FACET)882 if (facet == GMONTH_FACET || facet == GMONTHDAY_FACET)
882 result.append("--", 2);883 result.append("--", 2);
883 if (facet == GDAY_FACET)884 if (facet == GDAY_FACET)
884 result.append("---", 3);885 result.append("---", 3);
885 886
886 for (int i=0; i<=5; i++)887 for (int i=0; i<=5; i++)
887 {888 {
888 if (FACET_MEMBERS[facet][i])889 if (FACET_MEMBERS[facet][i])
@@ -892,12 +893,12 @@
892 result.push_back(separators[i]);893 result.push_back(separators[i]);
893 }894 }
894 }895 }
895 896
896 if (FACET_MEMBERS[facet][FRACSECONDS_DATA] && (data[FRACSECONDS_DATA] != 0))897 if (FACET_MEMBERS[facet][FRACSECONDS_DATA] && (data[FRACSECONDS_DATA] != 0))
897 {898 {
898 int temp;899 int temp;
899 result.append(".", 1);900 result.append(".", 1);
900 901
901 // print leading 0s, if any902 // print leading 0s, if any
902 temp = FRAC_SECONDS_UPPER_LIMIT / 10;903 temp = FRAC_SECONDS_UPPER_LIMIT / 10;
903 while (temp > data[FRACSECONDS_DATA] && temp > 0)904 while (temp > data[FRACSECONDS_DATA] && temp > 0)
@@ -905,17 +906,17 @@
905 result.append("0", 1);906 result.append("0", 1);
906 temp /= 10;907 temp /= 10;
907 }908 }
908 909
909 // strip trailing 0s, if any910 // strip trailing 0s, if any
910 temp = data[FRACSECONDS_DATA];911 temp = data[FRACSECONDS_DATA];
911 while (temp%10 == 0 && temp > 0)912 while (temp%10 == 0 && temp > 0)
912 temp = temp / 10;913 temp = temp / 10;
913 914
914 result.append(ztd::to_string(temp));915 result.append(ztd::to_string(temp));
915 }916 }
916 917
917 result.append(the_time_zone.toString());918 result.append(the_time_zone.toString());
918 919
919 return result;920 return result;
920}921}
921922
@@ -984,7 +985,7 @@
984 assert(data[SECONDS_DATA] >= 0);985 assert(data[SECONDS_DATA] >= 0);
985 return data[SECONDS_DATA];986 return data[SECONDS_DATA];
986}987}
987 988
988989
989int DateTime::getFractionalSeconds() const990int DateTime::getFractionalSeconds() const
990{991{
@@ -1003,21 +1004,21 @@
1003{1004{
1004 return !the_time_zone.timeZoneNotSet();1005 return !the_time_zone.timeZoneNotSet();
1005}1006}
1006 1007
1007 1008
1008int DateTime::compare(const DateTime* dt, long timezone_seconds) const1009int DateTime::compare(const DateTime* dt, long timezone_seconds) const
1009{1010{
1010 std::auto_ptr<DateTime> d1_t;1011 std::auto_ptr<DateTime> d1_t;
1011 std::auto_ptr<DateTime> d2_t;1012 std::auto_ptr<DateTime> d2_t;
1012 1013
1013 d1_t.reset(normalizeTimeZone(timezone_seconds));1014 d1_t.reset(normalizeTimeZone(timezone_seconds));
1014 d2_t.reset(dt->normalizeTimeZone(timezone_seconds));1015 d2_t.reset(dt->normalizeTimeZone(timezone_seconds));
1015 1016
1016 if (d1_t->data[YEAR_DATA] < d2_t->data[YEAR_DATA])1017 if (d1_t->data[YEAR_DATA] < d2_t->data[YEAR_DATA])
1017 return -1;1018 return -1;
1018 else if (d1_t->data[YEAR_DATA] > d2_t->data[YEAR_DATA])1019 else if (d1_t->data[YEAR_DATA] > d2_t->data[YEAR_DATA])
1019 return 1;1020 return 1;
1020 1021
1021 // compare the rest of the data1022 // compare the rest of the data
1022 if (d1_t->data[YEAR_DATA] < 0 && d2_t->data[YEAR_DATA] < 0)1023 if (d1_t->data[YEAR_DATA] < 0 && d2_t->data[YEAR_DATA] < 0)
1023 {1024 {
@@ -1039,7 +1040,7 @@
1039 return 1;1040 return 1;
1040 }1041 }
1041 }1042 }
1042 1043
1043 return 0;1044 return 0;
1044}1045}
10451046
@@ -1048,7 +1049,7 @@
1048{1049{
1049 uint32_t hval = 0;1050 uint32_t hval = 0;
1050 std::auto_ptr<DateTime> dt(normalizeTimeZone(implicit_timezone_seconds));1051 std::auto_ptr<DateTime> dt(normalizeTimeZone(implicit_timezone_seconds));
1051 1052
1052 hval = hashfun::h32<int>((int)dt->facet, hval);1053 hval = hashfun::h32<int>((int)dt->facet, hval);
1053 hval = hashfun::h32<int>(dt->data[YEAR_DATA], hval);1054 hval = hashfun::h32<int>(dt->data[YEAR_DATA], hval);
1054 hval = hashfun::h32<int>(dt->data[MONTH_DATA], hval);1055 hval = hashfun::h32<int>(dt->data[MONTH_DATA], hval);
@@ -1057,9 +1058,9 @@
1057 hval = hashfun::h32<int>(dt->data[MINUTE_DATA], hval);1058 hval = hashfun::h32<int>(dt->data[MINUTE_DATA], hval);
1058 hval = hashfun::h32<int>(dt->data[SECONDS_DATA], hval);1059 hval = hashfun::h32<int>(dt->data[SECONDS_DATA], hval);
1059 hval = hashfun::h32<int>(dt->data[FRACSECONDS_DATA], hval);1060 hval = hashfun::h32<int>(dt->data[FRACSECONDS_DATA], hval);
1060 1061
1061 hval = dt->the_time_zone.hash(hval);1062 hval = dt->the_time_zone.hash(hval);
1062 1063
1063 return hval;1064 return hval;
1064}1065}
10651066
@@ -1086,13 +1087,13 @@
1086 data[MONTH_DATA],1087 data[MONTH_DATA],
1087 data[DAY_DATA])-1,1088 data[DAY_DATA])-1,
1088 0, 0, 0, 0);1089 0, 0, 0, 0);
1089 1090
1090 Duration remainder(Duration::DAYTIMEDURATION_FACET, false, 0, 0, 0,1091 Duration remainder(Duration::DAYTIMEDURATION_FACET, false, 0, 0, 0,
1091 data[HOUR_DATA],1092 data[HOUR_DATA],
1092 data[MINUTE_DATA],1093 data[MINUTE_DATA],
1093 data[SECONDS_DATA],1094 data[SECONDS_DATA],
1094 data[FRACSECONDS_DATA]);1095 data[FRACSECONDS_DATA]);
1095 1096
1096 return days + remainder;1097 return days + remainder;
1097 }1098 }
1098}1099}
@@ -1106,7 +1107,7 @@
11061107
1107 // For the algorithm, see XML Schema 2 spec, Appendix E1108 // For the algorithm, see XML Schema 2 spec, Appendix E
1108 // http://www.w3.org/TR/xmlschema-2/#adding-durations-to-dateTimes1109 // http://www.w3.org/TR/xmlschema-2/#adding-durations-to-dateTimes
1109 1110
1110 months = modulo<int>(data[MONTH_DATA] + d.getMonths() - 1, 12) + 1;1111 months = modulo<int>(data[MONTH_DATA] + d.getMonths() - 1, 12) + 1;
11111112
1112 years = data[YEAR_DATA] + d.getYears() +1113 years = data[YEAR_DATA] + d.getYears() +
@@ -1118,7 +1119,7 @@
1118 int_seconds = modulo<int>(total_seconds, 60);1119 int_seconds = modulo<int>(total_seconds, 60);
11191120
1120 frac_seconds = modulo<int>(temp_frac_seconds, DateTime::FRAC_SECONDS_UPPER_LIMIT);1121 frac_seconds = modulo<int>(temp_frac_seconds, DateTime::FRAC_SECONDS_UPPER_LIMIT);
1121 1122
1122 minutes = data[MINUTE_DATA] + d.getMinutes() + quotient<int>(total_seconds, 60);1123 minutes = data[MINUTE_DATA] + d.getMinutes() + quotient<int>(total_seconds, 60);
11231124
1124 hours = data[HOUR_DATA] + d.getHours() + quotient<int>(minutes, 60);1125 hours = data[HOUR_DATA] + d.getHours() + quotient<int>(minutes, 60);
@@ -1155,7 +1156,7 @@
1155 years += quotient<int>(months + carry-1, 12);1156 years += quotient<int>(months + carry-1, 12);
1156 months = modulo<int>(months + carry -1, 12) + 1;1157 months = modulo<int>(months + carry -1, 12) + 1;
1157 }1158 }
1158 1159
1159 if (data[YEAR_DATA] > 0 && d.isNegative() && years <= 0)1160 if (data[YEAR_DATA] > 0 && d.isNegative() && years <= 0)
1160 years--;1161 years--;
1161 if (data[YEAR_DATA] < 0 && !d.isNegative() && years >= 0)1162 if (data[YEAR_DATA] < 0 && !d.isNegative() && years >= 0)
@@ -1167,7 +1168,7 @@
1167 int_seconds, frac_seconds, &the_time_zone,1168 int_seconds, frac_seconds, &the_time_zone,
1168 *new_dt))1169 *new_dt))
1169 assert(0);1170 assert(0);
1170 1171
1171 new_dt->facet = facet;1172 new_dt->facet = facet;
1172 if (adjust_facet)1173 if (adjust_facet)
1173 new_dt->adjustToFacet();1174 new_dt->adjustToFacet();
@@ -1199,13 +1200,13 @@
1199{1200{
1200 DateTime* dt;1201 DateTime* dt;
1201 Duration d;1202 Duration d;
1202 1203
1203 if( the_time_zone.timeZoneNotSet() )1204 if( the_time_zone.timeZoneNotSet() )
1204 {1205 {
1205 // validate timezone value (-14 .. +14 H)1206 // validate timezone value (-14 .. +14 H)
1206 if (tz_seconds > 14*3600 || tz_seconds < -14*3600)1207 if (tz_seconds > 14*3600 || tz_seconds < -14*3600)
1207 throw InvalidTimezoneException( tz_seconds );1208 throw InvalidTimezoneException( tz_seconds );
1208 1209
1209 d = Duration(Duration::DAYTIMEDURATION_FACET,1210 d = Duration(Duration::DAYTIMEDURATION_FACET,
1210 (tz_seconds < 0), 0, 0, 0, 0, 0, tz_seconds, 0);1211 (tz_seconds < 0), 0, 0, 0, 0, 0, tz_seconds, 0);
1211 }1212 }
@@ -1214,10 +1215,10 @@
1214 if (0 != Duration::fromTimezone(the_time_zone, d))1215 if (0 != Duration::fromTimezone(the_time_zone, d))
1215 assert(0);1216 assert(0);
1216 }1217 }
1217 1218
1218 dt = subtractDuration(d, false); // do not adjust to facet1219 dt = subtractDuration(d, false); // do not adjust to facet
1219 dt->the_time_zone = TimeZone(0);1220 dt->the_time_zone = TimeZone(0);
1220 1221
1221 return dt;1222 return dt;
1222}1223}
12231224
@@ -1227,7 +1228,7 @@
1227 std::auto_ptr<Duration> dtduration;1228 std::auto_ptr<Duration> dtduration;
1228 std::auto_ptr<Duration> context_tz;1229 std::auto_ptr<Duration> context_tz;
1229 std::auto_ptr<DateTime> dt;1230 std::auto_ptr<DateTime> dt;
1230 1231
1231 // validate timezone value (-14 .. +14 H)1232 // validate timezone value (-14 .. +14 H)
1232 if (tz_seconds > 14*3600 || tz_seconds < -14*3600)1233 if (tz_seconds > 14*3600 || tz_seconds < -14*3600)
1233 throw InvalidTimezoneException( tz_seconds );1234 throw InvalidTimezoneException( tz_seconds );
@@ -1236,7 +1237,7 @@
1236 context_tz = std::auto_ptr<Duration>(new Duration(Duration::DAYTIMEDURATION_FACET, (tz_seconds<0), 0, 0, 0, 0, 0, tz_seconds, 0));1237 context_tz = std::auto_ptr<Duration>(new Duration(Duration::DAYTIMEDURATION_FACET, (tz_seconds<0), 0, 0, 0, 0, 0, tz_seconds, 0));
12371238
1238 dt = std::auto_ptr<DateTime>(new DateTime(*this));1239 dt = std::auto_ptr<DateTime>(new DateTime(*this));
1239 1240
1240 // If $arg does not have a timezone component and $timezone is not the empty sequence,1241 // If $arg does not have a timezone component and $timezone is not the empty sequence,
1241 // then the result is $arg with $timezone as the timezone component.1242 // then the result is $arg with $timezone as the timezone component.
1242 if (the_time_zone.timeZoneNotSet())1243 if (the_time_zone.timeZoneNotSet())
@@ -1274,9 +1275,9 @@
12741275
1275 // A dynamic error is raised [err:FODT0003] if $timezone is less than -PT14H1276 // A dynamic error is raised [err:FODT0003] if $timezone is less than -PT14H
1276 // or greater than PT14H or if does not contain an integral number of minutes.1277 // or greater than PT14H or if does not contain an integral number of minutes.
1277 1278
1278 dt = std::auto_ptr<DateTime>(new DateTime(*this));1279 dt = std::auto_ptr<DateTime>(new DateTime(*this));
1279 1280
1280 if (d == NULL)1281 if (d == NULL)
1281 {1282 {
1282 if (!the_time_zone.timeZoneNotSet())1283 if (!the_time_zone.timeZoneNotSet())
@@ -1291,7 +1292,7 @@
1291 d->getHours()*3600 + d->getMinutes()*60 > 14*3600 ||1292 d->getHours()*3600 + d->getMinutes()*60 > 14*3600 ||
1292 d->getHours()*3600 + d->getMinutes()*60 < -14*3600)1293 d->getHours()*3600 + d->getMinutes()*60 < -14*3600)
1293 throw InvalidTimezoneException( d->getHours()*3600 + d->getMinutes()*60 );1294 throw InvalidTimezoneException( d->getHours()*3600 + d->getMinutes()*60 );
1294 1295
1295 // If $arg does not have a timezone component and $timezone is not the1296 // If $arg does not have a timezone component and $timezone is not the
1296 // empty sequence, then the result is $arg with $timezone as the timezone1297 // empty sequence, then the result is $arg with $timezone as the timezone
1297 // component.1298 // component.
@@ -1385,79 +1386,18 @@
1385}1386}
13861387
13871388
1388int DateTime::getDayOfWeek(int year, int month, int day)
1389{
1390 if (month < 3)
1391 {
1392 month = month + 12;
1393 year = year - 1;
1394 }
1395
1396 return (day
1397 + (2 * month)
1398 + int(6 * (month + 1) / 10)
1399 + year
1400 + int(year / 4)
1401 - int(year / 100)
1402 + int(year / 400)
1403 + 1 // CalendarSystem, 1 for Gregorian
1404 ) % 7;
1405}
1406
1407
1408int DateTime::getWeekInYear(int year, int month, int day)
1409{
1410 int day_of_year = DateTime::getDayOfYear(year, month, day);
1411 int year_first_day_of_week = DateTime::getDayOfWeek(year, 1, 1);
1412
1413 if (year_first_day_of_week > 4 && (year_first_day_of_week + day_of_year) <= 8)
1414 return getWeekInYear(year-1, 12, 31);
1415
1416 return ((day_of_year + year_first_day_of_week - 2) / 7) + year_first_day_of_week < 5 ? 1 : 0;
1417}
1418
1419
1420int DateTime::getDayOfYear(int year, int month, int day)1389int DateTime::getDayOfYear(int year, int month, int day)
1421{1390{
1422 static const int days[] = {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365};
1423
1424 if (month > 12)1391 if (month > 12)
1425 return -1;1392 return -1;
1426 1393 return time::calc_yday( day, month - 1, year ) + 1;
1427 if (isLeapYear(year) && month >= 3)
1428 day++;
1429
1430 return days[month-1] + day;
1431}
1432
1433
1434bool DateTime::isLeapYear(int year)
1435{
1436 if (((year%4 == 0) && (year%100 != 0))
1437 ||
1438 (year%400 == 0))
1439 return true;
1440 else
1441 return false;
1442}1394}
14431395
14441396
1445int DateTime::getWeekInMonth(int year, int month, int day)1397int DateTime::getWeekInMonth(int year, int month, int day)
1446{1398{
1447 int first_day_of_week = DateTime::getDayOfWeek(year, month, 1);1399 int const wday = time::calc_wday( 1, month - 1, year );
1448 return ((day + first_day_of_week - 2) / 7) + (first_day_of_week < 5 ? 1 : 0);1400 return ((day + wday - 2) / 7) + (wday < 5 ? 1 : 0);
1449}
1450
1451
1452bool DateTime::isLeapYear() const
1453{
1454 return isLeapYear(data[YEAR_DATA]);
1455}
1456
1457
1458int DateTime::getDayOfWeek() const
1459{
1460 return getDayOfWeek(data[YEAR_DATA], data[MONTH_DATA], data[DAY_DATA]);
1461}1401}
14621402
14631403
@@ -1467,12 +1407,6 @@
1467}1407}
14681408
14691409
1470int DateTime::getWeekInYear() const
1471{
1472 return getWeekInYear(data[YEAR_DATA], data[MONTH_DATA], data[DAY_DATA]);
1473}
1474
1475
1476int DateTime::getWeekInMonth() const1410int DateTime::getWeekInMonth() const
1477{1411{
1478 return getWeekInMonth(data[YEAR_DATA], data[MONTH_DATA], data[DAY_DATA]);1412 return getWeekInMonth(data[YEAR_DATA], data[MONTH_DATA], data[DAY_DATA]);
14791413
=== modified file 'src/zorbautils/locale.cpp'
--- src/zorbautils/locale.cpp 2013-03-18 05:13:50 +0000
+++ src/zorbautils/locale.cpp 2013-03-21 16:00:34 +0000
@@ -169,6 +169,8 @@
169 LPCWSTR wlocale_name;169 LPCWSTR wlocale_name;
170 unique_ptr<WCHAR[]> wlocale_name_ptr;170 unique_ptr<WCHAR[]> wlocale_name_ptr;
171171
172 if ( !country )
173 country = iso3166_1::get_default( lang );
172 if ( lang && country ) {174 if ( lang && country ) {
173 wlocale_name_ptr = get_wlocale_name( lang, country );175 wlocale_name_ptr = get_wlocale_name( lang, country );
174 wlocale_name = wlocale_name_ptr.get();176 wlocale_name = wlocale_name_ptr.get();
@@ -278,6 +280,8 @@
278static zstring get_locale_info( nl_item item, iso639_1::type lang,280static zstring get_locale_info( nl_item item, iso639_1::type lang,
279 iso3166_1::type country ) {281 iso3166_1::type country ) {
280 if ( lang ) {282 if ( lang ) {
283 if ( !country )
284 country = iso3166_1::get_default( lang );
281 if ( locale_t const loc = get_unix_locale_t( lang, country ) ) {285 if ( locale_t const loc = get_unix_locale_t( lang, country ) ) {
282 char const *const info = nl_langinfo_l( item, loc );286 char const *const info = nl_langinfo_l( item, loc );
283 ::freelocale( loc );287 ::freelocale( loc );
@@ -549,6 +553,205 @@
549 return FIND( country );553 return FIND( country );
550}554}
551555
556type get_default( iso639_1::type lang ) {
557 //
558 // In cases where a language maps to multiple countries, if the language is
559 // the official language of a single country, that country is the one the
560 // language is mapped to.
561 //
562 static type const lang_to_country[] = {
563 unknown,
564 DJ , // aa: Afar => Djibouti
565 GE , // ab: Abkhazian => Georgia
566 IR , // ae: Avestan => Iran
567 ZA , // af: Afrikaans => South Africa
568 GH , // ak: Akan => Ghana
569 ET , // am: Amharic => Ethiopia
570 ES , // an: Aragonese => Spain
571 unknown, // ar: Arabic => (maps to multiple countries)
572 IN_ , // as: Assamese => India
573 AZ , // av: Avaric => Azerbaijan
574 BO , // ay: Aymara => Bolivia
575 AZ , // az: Azerbaijani => Azerbaijan
576 RU , // ba: Bashkir => Russian Federation
577 RU , // be: Byelorussian => Russian Federation
578 BG , // bg: Bulgarian => Bulgaria
579 IN_ , // bh: Bihari => India
580 VU , // bi: Bislama => Vanuatu
581 ML , // bm: Bambara => Mali
582 BD , // bn: Bengali; Bangla => Bangladesh
583 CN , // bo: Tibetan => China
584 FR , // br: Breton => France
585 BA , // bs: Bosnian => Bosnia
586 AD , // ca: Catalan => Andorra
587 RU , // ce: Chechen => Russian Federation
588 MP , // ch: Chamorro => Northern Mariana Islands
589 FR , // co: Corsican => France
590 US , // cr: Cree => United States
591 CZ , // cs: Czech => Czech Republic
592 RU , // cu: Church Slavic; Church Slavonic => Russian Federation
593 RU , // cv: Chuvash => Russian Federation
594 GB , // cy: Welsh => United Kingdom
595 DK , // da: Danish => Denmark
596 DE , // de: German => Germany
597 MV , // dv: Divehi => Maldives
598 PK , // dz: Bhutani => Pakistan
599 unknown, // ee: Ewe => (maps to multiple countries)
600 GR , // el: Greek => Greece
601 GB , // en: English => United Kingdom
602 unknown, // eo: Esperanto => (constructed language)
603 ES , // es: Spanish => Spain
604 EE , // et: Estonian => Estonia
605 ES , // eu: Basque => Spain
606 IR , // fa: Persian => Iran
607 unknown, // ff: Fulah => (maps to multiple countries)
608 FI , // fi: Finnish => Finland
609 FJ , // fj: Fiji => Fiji
610 FO , // fo: Faroese => Faroe Islands
611 FR , // fr: French => France
612 NL , // fy: Frisian => Netherlands
613 IE , // ga: Irish => Ireland
614 GB , // gd: Scots Gaelic => United Kingdom
615 ES , // gl: Galician => Spain
616 PY , // gn: Guarani => Paraguay
617 IN_ , // gu: Gujarati => India
618 IM , // gv: Manx => Isle of Man
619 unknown, // ha: Hausa => (maps to multiple languages)
620 IL , // he: Hebrew => Israel
621 IN_ , // hi: Hindi => India
622 PG , // ho: Hiri Motu => Papua New Guinea
623 HR , // hr: Croatian => Croatia
624 HT , // ht: Haitian Creole => Haiti
625 HU , // hu: Hungarian => Hungary
626 AM , // hy: Armenian => Armenia
627 unknown, // hz: Herero => (maps to multiple countries)
628 unknown, // ia: Interlingua => (constructed language)
629 ID , // id: Indonesian => Indonesia
630 unknown, // ie: Interlingue => (constructed language)
631 NG , // ig: Igbo => Nigeria
632 CN , // ii: Nuosu => China
633 US , // ik: Inupiak => United States
634 unknown, // io: Ido => (constructed language)
635 IS , // is: Icelandic => Island
636 IT , // it: Italian => Italy
637 CA , // iu: Inuktitut => Canada
638 JP , // ja: Japanese => Japan
639 ID , // jv: Javanese => Indonesia
640 GE , // ka: Georgian => Georgia
641 unknown, // kg: Kongo => (maps to multiple countries)
642 KE , // ki: Gikuyu => Kenya
643 unknown, // kj: Kuanyama => (maps to multiple countries)
644 KZ , // kk: Kazakh => Kazakhstan
645 GL , // kl: Greenlandic => Greenland
646 KH , // km: Cambodian => Cambodia
647 IN_ , // kn: Kannada => India
648 KR , // ko: Korean => Korea
649 unknown, // kr: Kanuri => (maps to multiple countries)
650 IN_ , // ks: Kashmiri => India
651 IQ , // ku: Kurdish => Iraq
652 RU , // kv: Komi => Russian Federation
653 GB , // kw: Cornish => United Kingdom
654 KG , // ky: Kirghiz => Kyrgyzstan
655 unknown, // la: Latin => (maps to multiple countries)
656 LU , // lb: Letzeburgesch => Luxembourg
657 UG , // lg: Ganda => Uganda
658 NL , // li: Limburgan; Limburger; Limburgish => Netherands
659 unknown, // ln: Lingala => (maps to multiple countries)
660 LA , // lo: Laotian => Lao
661 LT , // lt: Lithuanian => Lithuania
662 CD , // lu: Luba-Katanga => Democratic Republic of the Congo
663 LV , // lv: Latvian => Latvia
664 MG , // mg: Malagasy => Madagascar
665 MH , // mh: Marshallese => Marshall Islands
666 NZ , // mi: Maori => New Zealand
667 MK , // mk: Macedonian => Macedonia
668 IN_ , // ml: Malayalam => India
669 MN , // mn: Mongolian => Mongolia
670 MD , // mo: Moldavian => Moldova
671 IN_ , // mr: Marathi => India
672 MY , // ms: Malay => Malaysia
673 MT , // mt: Maltese => Malta
674 MM , // my: Burmese => Myanmar (Burma)
675 NR , // na: Nauru => Nauru
676 NO , // nb: Norwegian Bokmal => Norway
677 ZW , // nd: Ndebele, North => Zimbabwe
678 NP , // ne: Nepali => Nepal
679 NA , // ng: Ndonga => Namibia
680 NL , // nl: Dutch => Netherlands
681 NO , // nn: Norwegian Nynorsk => Norway
682 NO , // no: Norwegian => Norway
683 ZA , // nr: Ndebele, South => South Africa
684 US , // nv: Navajo; Navaho => United States
685 MW , // ny: Chichewa; Chewa; Nyanja => Malawi
686 unknown, // oc: Occitan => (maps to multiple countries)
687 CA , // oj: Ojibwa => Canada
688 unknown, // om: Oromo => (maps to multiple countries)
689 IN_ , // or: Oriya => India
690 unknown, // os: Ossetian; Ossetic => (maps to multiple countries)
691 PK , // pa: Panjabi; Punjabi => Pakistan
692 unknown, // pi: Pali => (maps to multiple countries)
693 PL , // pl: Polish => Poland
694 AF , // ps: Pashto, Pushto => Afghanistan
695 PT , // pt: Portuguese => Portugal
696 unknown, // qu: Quechua => (maps to multiple countries)
697 CH , // rm: Romansh => Switzerland
698 BI , // rn: Kirundi => Burundi
699 RO , // ro: Romanian => Romania
700 RU , // ru: Russian => Russian Federation
701 RW , // rw: Kinyarwanda => Rwanda
702 IN_ , // sa: Sanskrit => India
703 IT , // sc: Sardinian => Italy
704 PK , // sd: Sindhi => Pakistan
705 NO , // se: Northern Sami => Norway
706 CF , // sg: Sangho => Central African Republic
707 RS , // sh: Serbo-Croatian => Serbia
708 LK , // si: Sinhalese => Sri Lanka
709 SK , // sk: Slovak => Slovakia
710 SI , // sl: Slovenian => Slovenia
711 AS , // sm: Samoan => American Samoa
712 ZW , // sn: Shona => Zimbabwe
713 SO , // so: Somali => Somalia
714 AL , // sq: Albanian => Albania
715 RS , // sr: Serbian => Serbia
716 SZ , // ss: Siswati => Swaziland
717 LS , // st: Sesotho => Lesotho
718 SD , // su: Sundanese => Sudan
719 SE , // sv: Swedish => Sweden
720 KE , // sw: Swahili => Kenya
721 IN_ , // ta: Tamil => India
722 IN_ , // te: Telugu => India
723 TJ , // tg: Tajik => Tajikistan
724 TH , // th: Thai => Thailand
725 ER , // ti: Tigrinya => Eritrea
726 TM , // tk: Turkmen => Turkmenistan
727 PH , // tl: Tagalog => Philippines
728 ZA , // tn: Setswana => South Africa
729 TO , // to: Tonga => Tonga
730 TR , // tr: Turkish => Turkey
731 ZA , // ts: Tsonga => South Africa
732 RU , // tt: Tatar => Russian Federation
733 GH , // tw: Twi => Ghana
734 PF , // ty: Tahitian => French Polynesia
735 CN , // ug: Uighur => China
736 UA , // uk: Ukrainian => Ukrain
737 PK , // ur: Urdu => Pakistan
738 UZ , // uz: Uzbek => Uzbekistan
739 ZA , // ve: Venda => South Africa
740 VN , // vi: Vietnamese => Viet Nam
741 DE , // vo: Volapuk => Germany
742 BE , // wa: Walloon => Belgium
743 SN , // wo: Wolof => Senegal
744 ZA , // xh: Xhosa => South Africa
745 IL , // yi: Yiddish => Israel
746 NG , // yo: Yoruba => Nigeria
747 CN , // za: Zhuang => China
748 CN , // zh: Chinese => China
749 ZA , // zu: Zulu => South Africa
750 };
751 assert( lang < iso639_1::NUM_ENTRIES );
752 return lang_to_country[ lang ];
753}
754
552} // namespace iso3166_1755} // namespace iso3166_1
553756
554///////////////////////////////////////////////////////////////////////////////757///////////////////////////////////////////////////////////////////////////////
@@ -1302,6 +1505,8 @@
1302}1505}
13031506
1304bool is_supported( iso639_1::type lang, iso3166_1::type country ) {1507bool is_supported( iso639_1::type lang, iso3166_1::type country ) {
1508 if ( !country )
1509 country = iso3166_1::get_default( lang );
1305#ifdef WIN321510#ifdef WIN32
1306 unique_ptr<WCHAR[]> const wlocale_name( get_wlocale_name( lang, country ) );1511 unique_ptr<WCHAR[]> const wlocale_name( get_wlocale_name( lang, country ) );
1307 return Zorba_IsValidLocaleName( wlocale_name.get() );1512 return Zorba_IsValidLocaleName( wlocale_name.get() );
13081513
=== modified file 'src/zorbautils/locale.h'
--- src/zorbautils/locale.h 2013-03-08 04:26:02 +0000
+++ src/zorbautils/locale.h 2013-03-21 16:00:34 +0000
@@ -62,6 +62,15 @@
62 find( StringType const &country ) {62 find( StringType const &country ) {
63 return find( country.c_str() );63 return find( country.c_str() );
64 }64 }
65
66 /**
67 * Gets the "default" country that speaks the given language.
68 *
69 * @param lang The language to get the default country for.
70 * @return Returns said country or \c unknown.
71 */
72 type get_default( iso639_1::type lang );
73
65 } // namespace iso3166_174 } // namespace iso3166_1
6675
67 /////////////////////////////////////////////////////////////////////////// 76 ///////////////////////////////////////////////////////////////////////////
6877
=== modified file 'test/fots/CMakeLists.txt'
--- test/fots/CMakeLists.txt 2013-03-20 22:49:58 +0000
+++ test/fots/CMakeLists.txt 2013-03-21 16:00:34 +0000
@@ -158,37 +158,8 @@
158EXPECTED_FOTS_FAILURE (fn-environment-variable environment-variable-005 0)158EXPECTED_FOTS_FAILURE (fn-environment-variable environment-variable-005 0)
159EXPECTED_FOTS_FAILURE (fn-environment-variable environment-variable-006 0)159EXPECTED_FOTS_FAILURE (fn-environment-variable environment-variable-006 0)
160EXPECTED_FOTS_FAILURE (fn-environment-variable environment-variable-007 0)160EXPECTED_FOTS_FAILURE (fn-environment-variable environment-variable-007 0)
161EXPECTED_FOTS_FAILURE (fn-format-date format-date-001d 0)
162EXPECTED_FOTS_FAILURE (fn-format-date format-date-001g 0)
163EXPECTED_FOTS_FAILURE (fn-format-date format-date-005 0)161EXPECTED_FOTS_FAILURE (fn-format-date format-date-005 0)
164EXPECTED_FOTS_FAILURE (fn-format-date format-date-006 0)162EXPECTED_FOTS_FAILURE (fn-format-date format-date-006 0)
165EXPECTED_FOTS_FAILURE (fn-format-date format-date-007a 0)
166EXPECTED_FOTS_FAILURE (fn-format-date format-date-007b 0)
167EXPECTED_FOTS_FAILURE (fn-format-date format-date-007c 0)
168EXPECTED_FOTS_FAILURE (fn-format-date format-date-008a 0)
169EXPECTED_FOTS_FAILURE (fn-format-date format-date-008b 0)
170EXPECTED_FOTS_FAILURE (fn-format-date format-date-008c 0)
171EXPECTED_FOTS_FAILURE (fn-format-date format-date-009 0)
172EXPECTED_FOTS_FAILURE (fn-format-date format-date-010 0)
173EXPECTED_FOTS_FAILURE (fn-format-date format-date-014 0)
174EXPECTED_FOTS_FAILURE (fn-format-date format-date-015 0)
175EXPECTED_FOTS_FAILURE (fn-format-date format-date-016 0)
176EXPECTED_FOTS_FAILURE (fn-format-date format-date-017 0)
177EXPECTED_FOTS_FAILURE (fn-format-date format-date-018 0)
178EXPECTED_FOTS_FAILURE (fn-format-date format-date-019 0)
179EXPECTED_FOTS_FAILURE (fn-format-date format-date-020 0)
180EXPECTED_FOTS_FAILURE (fn-format-date format-date-021 0)
181EXPECTED_FOTS_FAILURE (fn-format-date format-date-022 0)
182EXPECTED_FOTS_FAILURE (fn-format-date format-date-023 0)
183EXPECTED_FOTS_FAILURE (fn-format-date format-date-024 0)
184EXPECTED_FOTS_FAILURE (fn-format-date format-date-025 0)
185EXPECTED_FOTS_FAILURE (fn-format-date format-date-026 0)
186EXPECTED_FOTS_FAILURE (fn-format-date format-date-027 0)
187EXPECTED_FOTS_FAILURE (fn-format-date format-date-en117 0)
188EXPECTED_FOTS_FAILURE (fn-format-date format-date-en118 0)
189EXPECTED_FOTS_FAILURE (fn-format-date format-date-en123 0)
190EXPECTED_FOTS_FAILURE (fn-format-date format-date-en124 0)
191EXPECTED_FOTS_FAILURE (fn-format-date format-date-en125 0)
192EXPECTED_FOTS_FAILURE (fn-format-date format-date-en126 0)163EXPECTED_FOTS_FAILURE (fn-format-date format-date-en126 0)
193EXPECTED_FOTS_FAILURE (fn-format-date format-date-en127 0)164EXPECTED_FOTS_FAILURE (fn-format-date format-date-en127 0)
194EXPECTED_FOTS_FAILURE (fn-format-date format-date-en128 0)165EXPECTED_FOTS_FAILURE (fn-format-date format-date-en128 0)
@@ -198,34 +169,9 @@
198EXPECTED_FOTS_FAILURE (fn-format-date format-date-en132 0)169EXPECTED_FOTS_FAILURE (fn-format-date format-date-en132 0)
199EXPECTED_FOTS_FAILURE (fn-format-date format-date-en133 0)170EXPECTED_FOTS_FAILURE (fn-format-date format-date-en133 0)
200EXPECTED_FOTS_FAILURE (fn-format-date format-date-en134 0)171EXPECTED_FOTS_FAILURE (fn-format-date format-date-en134 0)
201EXPECTED_FOTS_FAILURE (fn-format-date format-date-en141 0)
202EXPECTED_FOTS_FAILURE (fn-format-date format-date-en151 0)
203EXPECTED_FOTS_FAILURE (fn-format-dateTime format-dateTime-001d 0)
204EXPECTED_FOTS_FAILURE (fn-format-dateTime format-dateTime-001g 0)
205EXPECTED_FOTS_FAILURE (fn-format-dateTime format-dateTime-002g 0)
206EXPECTED_FOTS_FAILURE (fn-format-dateTime format-dateTime-002h 0)
207EXPECTED_FOTS_FAILURE (fn-format-dateTime format-dateTime-002i 0)
208EXPECTED_FOTS_FAILURE (fn-format-dateTime format-dateTime-003d 0)
209EXPECTED_FOTS_FAILURE (fn-format-dateTime format-dateTime-003g 0)
210EXPECTED_FOTS_FAILURE (fn-format-dateTime format-dateTime-003m 0)
211EXPECTED_FOTS_FAILURE (fn-format-dateTime format-dateTime-003n 0)
212EXPECTED_FOTS_FAILURE (fn-format-dateTime format-dateTime-003p 0)
213EXPECTED_FOTS_FAILURE (fn-format-dateTime format-dateTime-005 0)172EXPECTED_FOTS_FAILURE (fn-format-dateTime format-dateTime-005 0)
214EXPECTED_FOTS_FAILURE (fn-format-dateTime format-dateTime-006 0)173EXPECTED_FOTS_FAILURE (fn-format-dateTime format-dateTime-006 0)
215EXPECTED_FOTS_FAILURE (fn-format-dateTime format-dateTime-009 0)
216EXPECTED_FOTS_FAILURE (fn-format-dateTime format-dateTime-010 0)
217EXPECTED_FOTS_FAILURE (fn-format-dateTime format-dateTime-011 0)174EXPECTED_FOTS_FAILURE (fn-format-dateTime format-dateTime-011 0)
218EXPECTED_FOTS_FAILURE (fn-format-dateTime format-dateTime-012 0)
219EXPECTED_FOTS_FAILURE (fn-format-dateTime format-dateTime-013p 0)
220EXPECTED_FOTS_FAILURE (fn-format-dateTime format-dateTime-013s 0)
221EXPECTED_FOTS_FAILURE (fn-format-dateTime format-dateTime-013u 0)
222EXPECTED_FOTS_FAILURE (fn-format-dateTime format-dateTime-014 0)
223EXPECTED_FOTS_FAILURE (fn-format-dateTime format-dateTime-015 0)
224EXPECTED_FOTS_FAILURE (fn-format-dateTime format-dateTime-016 0)
225EXPECTED_FOTS_FAILURE (fn-format-dateTime format-dateTime-017 0)
226EXPECTED_FOTS_FAILURE (fn-format-dateTime format-dateTime-018 0)
227EXPECTED_FOTS_FAILURE (fn-format-dateTime format-dateTime-en141 0)
228EXPECTED_FOTS_FAILURE (fn-format-dateTime format-dateTime-en151 0)
229EXPECTED_FOTS_FAILURE (fn-format-integer format-integer-030 0)175EXPECTED_FOTS_FAILURE (fn-format-integer format-integer-030 0)
230EXPECTED_FOTS_FAILURE (fn-format-integer format-integer-031 0)176EXPECTED_FOTS_FAILURE (fn-format-integer format-integer-031 0)
231EXPECTED_FOTS_FAILURE (fn-format-integer format-integer-033 0)177EXPECTED_FOTS_FAILURE (fn-format-integer format-integer-033 0)
@@ -265,18 +211,6 @@
265EXPECTED_FOTS_FAILURE (fn-format-number numberformat86 0)211EXPECTED_FOTS_FAILURE (fn-format-number numberformat86 0)
266EXPECTED_FOTS_FAILURE (fn-format-number numberformat87 0)212EXPECTED_FOTS_FAILURE (fn-format-number numberformat87 0)
267EXPECTED_FOTS_FAILURE (fn-format-number numberformat88 0)213EXPECTED_FOTS_FAILURE (fn-format-number numberformat88 0)
268EXPECTED_FOTS_FAILURE (fn-format-time format-time-002g 0)
269EXPECTED_FOTS_FAILURE (fn-format-time format-time-002h 0)
270EXPECTED_FOTS_FAILURE (fn-format-time format-time-002i 0)
271EXPECTED_FOTS_FAILURE (fn-format-time format-time-013p 0)
272EXPECTED_FOTS_FAILURE (fn-format-time format-time-013s 0)
273EXPECTED_FOTS_FAILURE (fn-format-time format-time-013u 0)
274EXPECTED_FOTS_FAILURE (fn-format-time format-time-014 0)
275EXPECTED_FOTS_FAILURE (fn-format-time format-time-015 0)
276EXPECTED_FOTS_FAILURE (fn-format-time format-time-016 0)
277EXPECTED_FOTS_FAILURE (fn-format-time format-time-017 0)
278EXPECTED_FOTS_FAILURE (fn-format-time format-time-018 0)
279EXPECTED_FOTS_FAILURE (fn-format-time format-time-816err 0)
280EXPECTED_FOTS_FAILURE (fn-generate-id generate-id-001 0)214EXPECTED_FOTS_FAILURE (fn-generate-id generate-id-001 0)
281EXPECTED_FOTS_FAILURE (fn-generate-id generate-id-002 0)215EXPECTED_FOTS_FAILURE (fn-generate-id generate-id-002 0)
282EXPECTED_FOTS_FAILURE (fn-generate-id generate-id-003 0)216EXPECTED_FOTS_FAILURE (fn-generate-id generate-id-003 0)
283217
=== removed file 'test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/FormatDateFuncYearMonth1.xml.res'
--- test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/FormatDateFuncYearMonth1.xml.res 2013-02-07 17:24:36 +0000
+++ test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/FormatDateFuncYearMonth1.xml.res 1970-01-01 00:00:00 +0000
@@ -1,1 +0,0 @@
1true
2\ No newline at end of file0\ No newline at end of file
31
=== removed file 'test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/FormatDateFuncYearMonth2.xml.res'
--- test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/FormatDateFuncYearMonth2.xml.res 2013-02-07 17:24:36 +0000
+++ test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/FormatDateFuncYearMonth2.xml.res 1970-01-01 00:00:00 +0000
@@ -1,1 +0,0 @@
1true
2\ No newline at end of file0\ No newline at end of file
31
=== added file 'test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-D.xml.res'
--- test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-D.xml.res 1970-01-01 00:00:00 +0000
+++ test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-D.xml.res 2013-03-21 16:00:34 +0000
@@ -0,0 +1,1 @@
1true
02
=== added file 'test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-D01.xml.res'
--- test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-D01.xml.res 1970-01-01 00:00:00 +0000
+++ test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-D01.xml.res 2013-03-21 16:00:34 +0000
@@ -0,0 +1,1 @@
1true
02
=== added file 'test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-D1o.xml.res'
--- test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-D1o.xml.res 1970-01-01 00:00:00 +0000
+++ test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-D1o.xml.res 2013-03-21 16:00:34 +0000
@@ -0,0 +1,1 @@
1true
02
=== added file 'test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-DW-1.xml.res'
--- test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-DW-1.xml.res 1970-01-01 00:00:00 +0000
+++ test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-DW-1.xml.res 2013-03-21 16:00:34 +0000
@@ -0,0 +1,1 @@
1true
02
=== added file 'test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-DWo-1.xml.res'
--- test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-DWo-1.xml.res 1970-01-01 00:00:00 +0000
+++ test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-DWo-1.xml.res 2013-03-21 16:00:34 +0000
@@ -0,0 +1,1 @@
1true
02
=== added file 'test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-DWw.xml.res'
--- test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-DWw.xml.res 1970-01-01 00:00:00 +0000
+++ test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-DWw.xml.res 2013-03-21 16:00:34 +0000
@@ -0,0 +1,1 @@
1true
02
=== added file 'test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-DWwo.xml.res'
--- test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-DWwo.xml.res 1970-01-01 00:00:00 +0000
+++ test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-DWwo.xml.res 2013-03-21 16:00:34 +0000
@@ -0,0 +1,1 @@
1true
02
=== added file 'test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-Dw-2.xml.res'
--- test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-Dw-2.xml.res 1970-01-01 00:00:00 +0000
+++ test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-Dw-2.xml.res 2013-03-21 16:00:34 +0000
@@ -0,0 +1,1 @@
1true
02
=== added file 'test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-Dwo-2.xml.res'
--- test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-Dwo-2.xml.res 1970-01-01 00:00:00 +0000
+++ test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-Dwo-2.xml.res 2013-03-21 16:00:34 +0000
@@ -0,0 +1,1 @@
1true
02
=== added file 'test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-FN-1.xml.res'
--- test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-FN-1.xml.res 1970-01-01 00:00:00 +0000
+++ test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-FN-1.xml.res 2013-03-21 16:00:34 +0000
@@ -0,0 +1,1 @@
1true
02
=== added file 'test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-FN-3.xml.res'
--- test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-FN-3.xml.res 1970-01-01 00:00:00 +0000
+++ test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-FN-3.xml.res 2013-03-21 16:00:34 +0000
@@ -0,0 +1,1 @@
1true
02
=== added file 'test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-FNn-1.xml.res'
--- test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-FNn-1.xml.res 1970-01-01 00:00:00 +0000
+++ test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-FNn-1.xml.res 2013-03-21 16:00:34 +0000
@@ -0,0 +1,1 @@
1true
02
=== added file 'test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-FNn-2.xml.res'
--- test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-FNn-2.xml.res 1970-01-01 00:00:00 +0000
+++ test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-FNn-2.xml.res 2013-03-21 16:00:34 +0000
@@ -0,0 +1,1 @@
1true
02
=== added file 'test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-Fn-2.xml.res'
--- test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-Fn-2.xml.res 1970-01-01 00:00:00 +0000
+++ test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-Fn-2.xml.res 2013-03-21 16:00:34 +0000
@@ -0,0 +1,1 @@
1true
02
=== added file 'test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-Fn-4.xml.res'
--- test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-Fn-4.xml.res 1970-01-01 00:00:00 +0000
+++ test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-Fn-4.xml.res 2013-03-21 16:00:34 +0000
@@ -0,0 +1,1 @@
1true
02
=== renamed file 'test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/FormatDateFuncMonthDefault.xml.res' => 'test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-M.xml.res'
--- test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/FormatDateFuncMonthDefault.xml.res 2013-02-07 17:24:36 +0000
+++ test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-M.xml.res 2013-03-21 16:00:34 +0000
@@ -1,1 +1,1 @@
1true
2\ No newline at end of file1\ No newline at end of file
2true
33
=== renamed file 'test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/FormatDateFuncMonthNumber.xml.res' => 'test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-M01.xml.res'
--- test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/FormatDateFuncMonthNumber.xml.res 2013-02-07 17:24:36 +0000
+++ test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-M01.xml.res 2013-03-21 16:00:34 +0000
@@ -1,1 +1,1 @@
1true
2\ No newline at end of file1\ No newline at end of file
2true
33
=== renamed file 'test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/FormatDateFuncMonthUpperCase.xml.res' => 'test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-MN-1.xml.res'
--- test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/FormatDateFuncMonthUpperCase.xml.res 2013-02-07 17:24:36 +0000
+++ test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-MN-1.xml.res 2013-03-21 16:00:34 +0000
@@ -1,1 +1,1 @@
1true
2\ No newline at end of file1\ No newline at end of file
2true
33
=== renamed file 'test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/FormatDateFuncMonthTitleCase.xml.res' => 'test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-MNn.xml.res'
--- test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/FormatDateFuncMonthTitleCase.xml.res 2013-02-07 17:24:36 +0000
+++ test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-MNn.xml.res 2013-03-21 16:00:34 +0000
@@ -1,1 +1,1 @@
1true
2\ No newline at end of file1\ No newline at end of file
2true
33
=== renamed file 'test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/FormatDateFuncMonthLowerCase.xml.res' => 'test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-Mn-2.xml.res'
--- test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/FormatDateFuncMonthLowerCase.xml.res 2013-02-07 17:24:36 +0000
+++ test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-Mn-2.xml.res 2013-03-21 16:00:34 +0000
@@ -1,1 +1,1 @@
1true
2\ No newline at end of file1\ No newline at end of file
2true
33
=== renamed file 'test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/FormatDateFuncYearMaxWidth.xml.res' => 'test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-Y-2-2.xml.res'
--- test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/FormatDateFuncYearMaxWidth.xml.res 2013-02-07 17:24:36 +0000
+++ test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-Y-2-2.xml.res 2013-03-21 16:00:34 +0000
@@ -1,1 +1,1 @@
1true
2\ No newline at end of file1\ No newline at end of file
2true
33
=== renamed file 'test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/FormatDateFuncReflexivity.xml.res' => 'test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-Y-M01-D01.xml.res'
--- test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/FormatDateFuncReflexivity.xml.res 2013-02-07 17:24:36 +0000
+++ test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-Y-M01-D01.xml.res 2013-03-21 16:00:34 +0000
@@ -1,1 +1,1 @@
1true
2\ No newline at end of file1\ No newline at end of file
2true
33
=== added file 'test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-Y-Thai-1.xml.res'
--- test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-Y-Thai-1.xml.res 1970-01-01 00:00:00 +0000
+++ test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-Y-Thai-1.xml.res 2013-03-21 16:00:34 +0000
@@ -0,0 +1,1 @@
1true
02
=== added file 'test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-Y-Thai-2.xml.res'
--- test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-Y-Thai-2.xml.res 1970-01-01 00:00:00 +0000
+++ test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-Y-Thai-2.xml.res 2013-03-21 16:00:34 +0000
@@ -0,0 +1,1 @@
1true
02
=== renamed file 'test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/FormatDateFuncYearDefault.xml.res' => 'test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-Y.xml.res'
--- test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/FormatDateFuncYearDefault.xml.res 2013-02-07 17:24:36 +0000
+++ test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-Y.xml.res 2013-03-21 16:00:34 +0000
@@ -1,1 +1,1 @@
1true
2\ No newline at end of file1\ No newline at end of file
2true
33
=== added file 'test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-YI-1.xml.res'
--- test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-YI-1.xml.res 1970-01-01 00:00:00 +0000
+++ test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-YI-1.xml.res 2013-03-21 16:00:34 +0000
@@ -0,0 +1,1 @@
1true
02
=== added file 'test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-Yi-2.xml.res'
--- test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-Yi-2.xml.res 1970-01-01 00:00:00 +0000
+++ test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-Yi-2.xml.res 2013-03-21 16:00:34 +0000
@@ -0,0 +1,1 @@
1true
02
=== renamed file 'test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/FormatDateFuncYearDefaultExtraChars.xml.res' => 'test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-chars.xml.res'
--- test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/FormatDateFuncYearDefaultExtraChars.xml.res 2013-02-07 17:24:36 +0000
+++ test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-chars.xml.res 2013-03-21 16:00:34 +0000
@@ -1,1 +1,1 @@
1true
2\ No newline at end of file1\ No newline at end of file
2true
33
=== renamed file 'test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/FormatDateFuncMonthNumberSpaces.xml.res' => 'test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-whitespace.xml.res'
--- test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/FormatDateFuncMonthNumberSpaces.xml.res 2013-02-07 17:24:36 +0000
+++ test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-date-whitespace.xml.res 2013-03-21 16:00:34 +0000
@@ -1,1 +1,1 @@
1true
2\ No newline at end of file1\ No newline at end of file
2true
33
=== renamed file 'test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/FormatDateTimeFuncReflexivity.xml.res' => 'test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-dateTime-01.xml.res'
--- test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/FormatDateTimeFuncReflexivity.xml.res 2013-02-07 17:24:36 +0000
+++ test/rbkt/ExpQueryResults/zorba/durationdatetime/FormatDateTimeFunc/format-dateTime-01.xml.res 2013-03-21 16:00:34 +0000
The diff has been truncated for viewing.

Subscribers

People subscribed via source and target branches