@@ -381,6 +381,12 @@ if(NOT DISABLE_STD_LOCALE) | |||
) | |||
endif() | |||
if(NOT DISABLE_WINAPI_LOCALE OR NOT DISABLE_STD_LOCALE OR NOT DISABLE_POSIX_LOCALE) | |||
set(BOOSTER_SRC ${BOOSTER_SRC} | |||
lib/locale/src/util/gregorian.cpp) | |||
endif() | |||
if(USE_WINDOWS6_API) | |||
check_cxx_source_compiles( | |||
"#include <windows.h> | |||
@@ -1,5 +1,5 @@ | |||
// | |||
// Copyright (c) 2009-2010 Artyom Beilis (Tonkikh) | |||
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) | |||
// | |||
// Distributed under the Boost Software License, Version 1.0. (See | |||
// accompanying file LICENSE_1_0.txt or copy at | |||
@@ -1,5 +1,5 @@ | |||
// | |||
// Copyright (c) 2009-2010 Artyom Beilis (Tonkikh) | |||
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) | |||
// | |||
// Distributed under the Boost Software License, Version 1.0. (See | |||
// accompanying file LICENSE_1_0.txt or copy at | |||
@@ -1,5 +1,5 @@ | |||
// | |||
// Copyright (c) 2009-2010 Artyom Beilis (Tonkikh) | |||
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) | |||
// | |||
// Distributed under the Boost Software License, Version 1.0. (See | |||
// accompanying file LICENSE_1_0.txt or copy at | |||
@@ -1,5 +1,5 @@ | |||
// | |||
// Copyright (c) 2009-2010 Artyom Beilis (Tonkikh) | |||
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) | |||
// | |||
// Distributed under the Boost Software License, Version 1.0. (See | |||
// accompanying file LICENSE_1_0.txt or copy at | |||
@@ -1,5 +1,5 @@ | |||
// | |||
// Copyright (c) 2009-2010 Artyom Beilis (Tonkikh) | |||
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) | |||
// | |||
// Distributed under the Boost Software License, Version 1.0. (See | |||
// accompanying file LICENSE_1_0.txt or copy at | |||
@@ -894,6 +894,11 @@ namespace booster { | |||
/// | |||
int maximum(period::period_type f) const; | |||
/// | |||
/// Check if the current time is in daylight saving time | |||
/// | |||
bool is_in_daylight_saving_time() const; | |||
private: | |||
hold_ptr<abstract_calendar> impl_; | |||
}; | |||
@@ -1,5 +1,5 @@ | |||
// | |||
// Copyright (c) 2009-2010 Artyom Beilis (Tonkikh) | |||
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) | |||
// | |||
// Distributed under the Boost Software License, Version 1.0. (See | |||
// accompanying file LICENSE_1_0.txt or copy at | |||
@@ -24,24 +24,29 @@ namespace booster { | |||
/// Operators like +, - * defined for these period allowing to perform easy calculations over them | |||
/// | |||
typedef enum { | |||
invalid, ///< Special invalid value, should not be used directs | |||
invalid, ///< Special invalid value, should not be used directly | |||
era, ///< Era i.e. AC, BC in Gregorian and Julian calendar, range [0,1] | |||
year, ///< Year, it is calendar specific | |||
year, ///< Year, it is calendar specific, for example 2011 in Gregorian calendar. | |||
extended_year, ///< Extended year for Gregorian/Julian calendars, where 1 BC == 0, 2 BC == -1. | |||
month, ///< The month of year, calendar specific, in Gregorian [0..11] | |||
day, ///< The day of month, calendar specific, in Gregorian [1..31] | |||
day_of_year, ///< The number of day in year, starting from 1 | |||
day_of_week, ///< Day of week, starting from Sunday, [1..7] | |||
day_of_week_in_month, ///< Original number of the day of the week in month. | |||
day_of_year, ///< The number of day in year, starting from 1, in Gregorian [1..366] | |||
day_of_week, ///< Day of week, Sunday=1, Monday=2,..., Saturday=7. | |||
///< Note that that updating this value respects local day of week, so for example, | |||
///< If first day of week is Monday and the current day is Tuesday then setting | |||
///< the value to Sunday (1) would forward the date by 5 days forward and not backward | |||
///< by two days as it could be expected if the numbers were taken as is. | |||
day_of_week_in_month, ///< Original number of the day of the week in month. For example 1st Sunday, | |||
///< 2nd Sunday, etc. in Gregorian [1..5] | |||
day_of_week_local, ///< Local day of week, for example in France Monday is 1, in US Sunday is 1, [1..7] | |||
hour, ///< 24 clock hour [0..23] | |||
hour_12, ///< 12 clock hour [0..11] | |||
am_pm, ///< am or pm marker, [0..1] | |||
am_pm, ///< am or pm marker [0..1] | |||
minute, ///< minute [0..59] | |||
second, ///< second [0..59] | |||
week_of_year, ///< The week number in the year | |||
week_of_month, ///< The week number withing current month | |||
first_day_of_week, ///< For example Sunday in US, Monday in France | |||
first_day_of_week, ///< First day if week, constant, for example Sunday in US = 1, Monday in France = 2 | |||
} period_type; | |||
} // namespace period | |||
@@ -90,7 +95,8 @@ namespace booster { | |||
/// Information about calendar | |||
/// | |||
typedef enum { | |||
is_gregorian, ///< Check if the calendar is Gregorian | |||
is_gregorian, ///< Check if the calendar is Gregorian | |||
is_dst ///< Check if the current time is in daylight time savings | |||
} calendar_option_type; | |||
/// | |||
@@ -1,5 +1,5 @@ | |||
// | |||
// Copyright (c) 2009-2010 Artyom Beilis (Tonkikh) | |||
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) | |||
// | |||
// Distributed under the Boost Software License, Version 1.0. (See | |||
// accompanying file LICENSE_1_0.txt or copy at | |||
@@ -1,5 +1,5 @@ | |||
// | |||
// Copyright (c) 2009-2010 Artyom Beilis (Tonkikh) | |||
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) | |||
// | |||
// Distributed under the Boost Software License, Version 1.0. (See | |||
// accompanying file LICENSE_1_0.txt or copy at | |||
@@ -1,5 +1,5 @@ | |||
// | |||
// Copyright (c) 2009-2010 Artyom Beilis (Tonkikh) | |||
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) | |||
// | |||
// Distributed under the Boost Software License, Version 1.0. (See | |||
// accompanying file LICENSE_1_0.txt or copy at | |||
@@ -1,5 +1,5 @@ | |||
// | |||
// Copyright (c) 2009-2010 Artyom Beilis (Tonkikh) | |||
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) | |||
// | |||
// Distributed under the Boost Software License, Version 1.0. (See | |||
// accompanying file LICENSE_1_0.txt or copy at | |||
@@ -1,5 +1,5 @@ | |||
// | |||
// Copyright (c) 2009-2010 Artyom Beilis (Tonkikh) | |||
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) | |||
// | |||
// Distributed under the Boost Software License, Version 1.0. (See | |||
// accompanying file LICENSE_1_0.txt or copy at | |||
@@ -1,5 +1,5 @@ | |||
// | |||
// Copyright (c) 2009-2010 Artyom Beilis (Tonkikh) | |||
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) | |||
// | |||
// Distributed under the Boost Software License, Version 1.0. (See | |||
// accompanying file LICENSE_1_0.txt or copy at | |||
@@ -98,7 +98,7 @@ namespace booster { | |||
/// | |||
bool utf8() const | |||
{ | |||
return get_ineger_property(utf8_property) != 0; | |||
return get_integer_property(utf8_property) != 0; | |||
} | |||
#if defined (__SUNPRO_CC) && defined (_RWSTD_VER) | |||
@@ -112,7 +112,7 @@ namespace booster { | |||
/// | |||
/// Get integer property by its id \a v | |||
/// | |||
virtual int get_ineger_property(integer_property v) const = 0; | |||
virtual int get_integer_property(integer_property v) const = 0; | |||
}; | |||
} | |||
@@ -1,5 +1,5 @@ | |||
// | |||
// Copyright (c) 2009-2010 Artyom Beilis (Tonkikh) | |||
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) | |||
// | |||
// Distributed under the Boost Software License, Version 1.0. (See | |||
// accompanying file LICENSE_1_0.txt or copy at | |||
@@ -1,5 +1,5 @@ | |||
// | |||
// Copyright (c) 2009-2010 Artyom Beilis (Tonkikh) | |||
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) | |||
// | |||
// Distributed under the Boost Software License, Version 1.0. (See | |||
// accompanying file LICENSE_1_0.txt or copy at | |||
@@ -1,5 +1,5 @@ | |||
// | |||
// Copyright (c) 2009-2010 Artyom Beilis (Tonkikh) | |||
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) | |||
// | |||
// Distributed under the Boost Software License, Version 1.0. (See | |||
// accompanying file LICENSE_1_0.txt or copy at | |||
@@ -1,5 +1,5 @@ | |||
// | |||
// Copyright (c) 2009-2010 Artyom Beilis (Tonkikh) | |||
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) | |||
// | |||
// Distributed under the Boost Software License, Version 1.0. (See | |||
// accompanying file LICENSE_1_0.txt or copy at | |||
@@ -1,5 +1,5 @@ | |||
// | |||
// Copyright (c) 2009-2010 Artyom Beilis (Tonkikh) | |||
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) | |||
// | |||
// Distributed under the Boost Software License, Version 1.0. (See | |||
// accompanying file LICENSE_1_0.txt or copy at | |||
@@ -1,5 +1,5 @@ | |||
// | |||
// Copyright (c) 2009-2010 Artyom Beilis (Tonkikh) | |||
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) | |||
// | |||
// Distributed under the Boost Software License, Version 1.0. (See | |||
// accompanying file LICENSE_1_0.txt or copy at | |||
@@ -1,5 +1,5 @@ | |||
// | |||
// Copyright (c) 2009-2010 Artyom Beilis (Tonkikh) | |||
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) | |||
// | |||
// Distributed under the Boost Software License, Version 1.0. (See | |||
// accompanying file LICENSE_1_0.txt or copy at | |||
@@ -1,5 +1,5 @@ | |||
// | |||
// Copyright (c) 2009-2010 Artyom Beilis (Tonkikh) | |||
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) | |||
// | |||
// Distributed under the Boost Software License, Version 1.0. (See | |||
// accompanying file LICENSE_1_0.txt or copy at | |||
@@ -1,5 +1,5 @@ | |||
// | |||
// Copyright (c) 2009-2010 Artyom Beilis (Tonkikh) | |||
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) | |||
// | |||
// Distributed under the Boost Software License, Version 1.0. (See | |||
// accompanying file LICENSE_1_0.txt or copy at | |||
@@ -1,5 +1,5 @@ | |||
// | |||
// Copyright (c) 2009-2010 Artyom Beilis (Tonkikh) | |||
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) | |||
// | |||
// Distributed under the Boost Software License, Version 1.0. (See | |||
// accompanying file LICENSE_1_0.txt or copy at | |||
@@ -1,5 +1,5 @@ | |||
// | |||
// Copyright (c) 2009-2010 Artyom Beilis (Tonkikh) | |||
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) | |||
// | |||
// Distributed under the Boost Software License, Version 1.0. (See | |||
// accompanying file LICENSE_1_0.txt or copy at | |||
@@ -1,5 +1,5 @@ | |||
// | |||
// Copyright (c) 2009-2010 Artyom Beilis (Tonkikh) | |||
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) | |||
// | |||
// Distributed under the Boost Software License, Version 1.0. (See | |||
// accompanying file LICENSE_1_0.txt or copy at | |||
@@ -1,5 +1,5 @@ | |||
// | |||
// Copyright (c) 2009-2010 Artyom Beilis (Tonkikh) | |||
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) | |||
// | |||
// Distributed under the Boost Software License, Version 1.0. (See | |||
// accompanying file LICENSE_1_0.txt or copy at | |||
@@ -1,5 +1,5 @@ | |||
// | |||
// Copyright (c) 2009-2010 Artyom Beilis (Tonkikh) | |||
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) | |||
// | |||
// Distributed under the Boost Software License, Version 1.0. (See | |||
// accompanying file LICENSE_1_0.txt or copy at | |||
@@ -1,5 +1,5 @@ | |||
// | |||
// Copyright (c) 2009-2010 Artyom Beilis (Tonkikh) | |||
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) | |||
// | |||
// Distributed under the Boost Software License, Version 1.0. (See | |||
// accompanying file LICENSE_1_0.txt or copy at | |||
@@ -1,5 +1,5 @@ | |||
// | |||
// Copyright (c) 2009-2010 Artyom Beilis (Tonkikh) | |||
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) | |||
// | |||
// Distributed under the Boost Software License, Version 1.0. (See | |||
// accompanying file LICENSE_1_0.txt or copy at | |||
@@ -1,5 +1,5 @@ | |||
// | |||
// Copyright (c) 2009-2010 Artyom Beilis (Tonkikh) | |||
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) | |||
// | |||
// Distributed under the Boost Software License, Version 1.0. (See | |||
// accompanying file LICENSE_1_0.txt or copy at | |||
@@ -1,5 +1,5 @@ | |||
// | |||
// Copyright (c) 2009-2010 Artyom Beilis (Tonkikh) | |||
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) | |||
// | |||
// Distributed under the Boost Software License, Version 1.0. (See | |||
// accompanying file LICENSE_1_0.txt or copy at | |||
@@ -1,5 +1,5 @@ | |||
// | |||
// Copyright (c) 2009-2010 Artyom Beilis (Tonkikh) | |||
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) | |||
// | |||
// Distributed under the Boost Software License, Version 1.0. (See | |||
// accompanying file LICENSE_1_0.txt or copy at | |||
@@ -1,5 +1,5 @@ | |||
// | |||
// Copyright (c) 2009-2010 Artyom Beilis (Tonkikh) | |||
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) | |||
// | |||
// Distributed under the Boost Software License, Version 1.0. (See | |||
// accompanying file LICENSE_1_0.txt or copy at | |||
@@ -1,5 +1,5 @@ | |||
// | |||
// Copyright (c) 2009-2010 Artyom Beilis (Tonkikh) | |||
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) | |||
// | |||
// Distributed under the Boost Software License, Version 1.0. (See | |||
// accompanying file LICENSE_1_0.txt or copy at | |||
@@ -1,5 +1,5 @@ | |||
// | |||
// Copyright (c) 2009-2010 Artyom Beilis (Tonkikh) | |||
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) | |||
// | |||
// Distributed under the Boost Software License, Version 1.0. (See | |||
// accompanying file LICENSE_1_0.txt or copy at | |||
@@ -1,5 +1,5 @@ | |||
// | |||
// Copyright (c) 2009-2010 Artyom Beilis (Tonkikh) | |||
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) | |||
// | |||
// Distributed under the Boost Software License, Version 1.0. (See | |||
// accompanying file LICENSE_1_0.txt or copy at | |||
@@ -1,5 +1,5 @@ | |||
// | |||
// Copyright (c) 2009-2010 Artyom Beilis (Tonkikh) | |||
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) | |||
// | |||
// Distributed under the Boost Software License, Version 1.0. (See | |||
// accompanying file LICENSE_1_0.txt or copy at | |||
@@ -156,15 +156,33 @@ namespace impl_icu { | |||
res.nanoseconds = 999999999; | |||
return res; | |||
} | |||
virtual void set_option(calendar_option_type opt,int v) | |||
virtual void set_option(calendar_option_type opt,int /*v*/) | |||
{ | |||
throw booster::invalid_argument("There is no settable options for calendar"); | |||
switch(opt) { | |||
case is_gregorian: | |||
throw date_time_error("is_gregorian is not settable options for calendar"); | |||
case is_dst: | |||
throw date_time_error("is_dst is not settable options for calendar"); | |||
default: | |||
; | |||
} | |||
} | |||
virtual int get_option(calendar_option_type opt) const | |||
{ | |||
if(opt==is_gregorian) | |||
switch(opt) { | |||
case is_gregorian: | |||
return dynamic_cast<icu::GregorianCalendar const *>(calendar_.get())!=0; | |||
throw booster::invalid_argument("Invalid option"); | |||
case is_dst: | |||
{ | |||
guard l(lock_); | |||
UErrorCode err = U_ZERO_ERROR; | |||
bool res = ( calendar_->inDaylightTime(err) != 0 ); | |||
check_and_throw_dt(err); | |||
return res; | |||
} | |||
default: | |||
return 0; | |||
} | |||
} | |||
virtual void adjust_value(period_type p,update_type u,int difference) | |||
{ | |||
@@ -181,15 +199,25 @@ namespace impl_icu { | |||
} | |||
virtual int difference(abstract_calendar const *other_ptr,period::period_type p) const | |||
{ | |||
calendar_impl const &other_cal=dynamic_cast<calendar_impl const &>(*other_ptr); | |||
std::auto_ptr<icu::Calendar> self(calendar_->clone()),other(other_cal.calendar_->clone()); | |||
UErrorCode err=U_ZERO_ERROR; | |||
double other_time = 0; | |||
{ | |||
guard l(other_cal.lock_); | |||
other_time = other->getTime(err); | |||
// | |||
// fieldDifference has side effect of moving calendar (WTF?) | |||
// So we clone it for performing this operation | |||
// | |||
std::auto_ptr<icu::Calendar> self(calendar_->clone()); | |||
calendar_impl const *other_cal=dynamic_cast<calendar_impl const *>(other_ptr); | |||
if(other_cal){ | |||
guard l(other_cal->lock_); | |||
other_time = other_cal->calendar_->getTime(err); | |||
check_and_throw_dt(err); | |||
} | |||
check_and_throw_dt(err); | |||
else { | |||
posix_time p = other_ptr->get_time(); | |||
other_time = p.seconds * 1000.0 + p.nanoseconds / 1000000.0; | |||
} | |||
int diff = 0; | |||
{ | |||
@@ -1,5 +1,5 @@ | |||
// | |||
// Copyright (c) 2009-2010 Artyom Beilis (Tonkikh) | |||
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) | |||
// | |||
// Distributed under the Boost Software License, Version 1.0. (See | |||
// accompanying file LICENSE_1_0.txt or copy at | |||
@@ -1,5 +1,5 @@ | |||
// | |||
// Copyright (c) 2009-2010 Artyom Beilis (Tonkikh) | |||
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) | |||
// | |||
// Distributed under the Boost Software License, Version 1.0. (See | |||
// accompanying file LICENSE_1_0.txt or copy at | |||
@@ -1,5 +1,5 @@ | |||
// | |||
// Copyright (c) 2009-2010 Artyom Beilis (Tonkikh) | |||
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) | |||
// | |||
// Distributed under the Boost Software License, Version 1.0. (See | |||
// accompanying file LICENSE_1_0.txt or copy at | |||
@@ -1,5 +1,5 @@ | |||
// | |||
// Copyright (c) 2009-2010 Artyom Beilis (Tonkikh) | |||
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) | |||
// | |||
// Distributed under the Boost Software License, Version 1.0. (See | |||
// accompanying file LICENSE_1_0.txt or copy at | |||
@@ -1,5 +1,5 @@ | |||
// | |||
// Copyright (c) 2009-2010 Artyom Beilis (Tonkikh) | |||
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) | |||
// | |||
// Distributed under the Boost Software License, Version 1.0. (See | |||
// accompanying file LICENSE_1_0.txt or copy at | |||
@@ -1,5 +1,5 @@ | |||
// | |||
// Copyright (c) 2009-2010 Artyom Beilis (Tonkikh) | |||
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) | |||
// | |||
// Distributed under the Boost Software License, Version 1.0. (See | |||
// accompanying file LICENSE_1_0.txt or copy at | |||
@@ -1,5 +1,5 @@ | |||
// | |||
// Copyright (c) 2009-2010 Artyom Beilis (Tonkikh) | |||
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) | |||
// | |||
// Distributed under the Boost Software License, Version 1.0. (See | |||
// accompanying file LICENSE_1_0.txt or copy at | |||
@@ -1,5 +1,5 @@ | |||
// | |||
// Copyright (c) 2009-2010 Artyom Beilis (Tonkikh) | |||
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) | |||
// | |||
// Distributed under the Boost Software License, Version 1.0. (See | |||
// accompanying file LICENSE_1_0.txt or copy at | |||
@@ -1,5 +1,5 @@ | |||
// | |||
// Copyright (c) 2009-2010 Artyom Beilis (Tonkikh) | |||
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) | |||
// | |||
// Distributed under the Boost Software License, Version 1.0. (See | |||
// accompanying file LICENSE_1_0.txt or copy at | |||
@@ -1,5 +1,5 @@ | |||
// | |||
// Copyright (c) 2009-2010 Artyom Beilis (Tonkikh) | |||
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) | |||
// | |||
// Distributed under the Boost Software License, Version 1.0. (See | |||
// accompanying file LICENSE_1_0.txt or copy at | |||
@@ -1,5 +1,5 @@ | |||
// | |||
// Copyright (c) 2009-2010 Artyom Beilis (Tonkikh) | |||
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) | |||
// | |||
// Distributed under the Boost Software License, Version 1.0. (See | |||
// accompanying file LICENSE_1_0.txt or copy at | |||
@@ -1,5 +1,5 @@ | |||
// | |||
// Copyright (c) 2009-2010 Artyom Beilis (Tonkikh) | |||
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) | |||
// | |||
// Distributed under the Boost Software License, Version 1.0. (See | |||
// accompanying file LICENSE_1_0.txt or copy at | |||
@@ -1,5 +1,5 @@ | |||
// | |||
// Copyright (c) 2009-2010 Artyom Beilis (Tonkikh) | |||
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) | |||
// | |||
// Distributed under the Boost Software License, Version 1.0. (See | |||
// accompanying file LICENSE_1_0.txt or copy at | |||
@@ -1,5 +1,5 @@ | |||
// | |||
// Copyright (c) 2009-2010 Artyom Beilis (Tonkikh) | |||
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) | |||
// | |||
// Distributed under the Boost Software License, Version 1.0. (See | |||
// accompanying file LICENSE_1_0.txt or copy at | |||
@@ -1,5 +1,5 @@ | |||
// | |||
// Copyright (c) 2009-2010 Artyom Beilis (Tonkikh) | |||
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) | |||
// | |||
// Distributed under the Boost Software License, Version 1.0. (See | |||
// accompanying file LICENSE_1_0.txt or copy at | |||
@@ -1,5 +1,5 @@ | |||
// | |||
// Copyright (c) 2009-2010 Artyom Beilis (Tonkikh) | |||
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) | |||
// | |||
// Distributed under the Boost Software License, Version 1.0. (See | |||
// accompanying file LICENSE_1_0.txt or copy at | |||
@@ -1,5 +1,5 @@ | |||
// | |||
// Copyright (c) 2009-2010 Artyom Beilis (Tonkikh) | |||
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) | |||
// | |||
// Distributed under the Boost Software License, Version 1.0. (See | |||
// accompanying file LICENSE_1_0.txt or copy at | |||
@@ -13,6 +13,7 @@ | |||
#include "posix_backend.h" | |||
#include "../util/locale_data.h" | |||
#include "../util/gregorian.h" | |||
#include <booster/locale/util.h> | |||
#include <langinfo.h> | |||
@@ -102,6 +103,12 @@ namespace impl_posix { | |||
return create_parsing(base,lc_,type); | |||
case codepage_facet: | |||
return create_codecvt(base,nl_langinfo_l(CODESET,*lc_),type); | |||
case calendar_facet: | |||
{ | |||
util::locale_data inf; | |||
inf.parse(real_id_); | |||
return util::install_gregorian_calendar(base,inf.country); | |||
} | |||
case message_facet: | |||
{ | |||
gnu_gettext::messages_info minf; | |||
@@ -1,5 +1,5 @@ | |||
// | |||
// Copyright (c) 2009-2010 Artyom Beilis (Tonkikh) | |||
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) | |||
// | |||
// Distributed under the Boost Software License, Version 1.0. (See | |||
// accompanying file LICENSE_1_0.txt or copy at | |||
@@ -1,5 +1,5 @@ | |||
// | |||
// Copyright (c) 2009-2010 Artyom Beilis (Tonkikh) | |||
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) | |||
// | |||
// Distributed under the Boost Software License, Version 1.0. (See | |||
// accompanying file LICENSE_1_0.txt or copy at | |||
@@ -417,6 +417,11 @@ int date_time::minimum(period_type f) const | |||
return impl_->get_value(f,abstract_calendar::actual_minimum); | |||
} | |||
bool date_time::is_in_daylight_saving_time() const | |||
{ | |||
return impl_->get_option(abstract_calendar::is_dst); | |||
} | |||
namespace time_zone { | |||
booster::mutex &tz_mutex() | |||
{ | |||
@@ -1,5 +1,5 @@ | |||
// | |||
// Copyright (c) 2009-2010 Artyom Beilis (Tonkikh) | |||
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) | |||
// | |||
// Distributed under the Boost Software License, Version 1.0. (See | |||
// accompanying file LICENSE_1_0.txt or copy at | |||
@@ -1,5 +1,5 @@ | |||
// | |||
// Copyright (c) 2009-2010 Artyom Beilis (Tonkikh) | |||
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) | |||
// | |||
// Distributed under the Boost Software License, Version 1.0. (See | |||
// accompanying file LICENSE_1_0.txt or copy at | |||
@@ -1,5 +1,5 @@ | |||
// | |||
// Copyright (c) 2009-2010 Artyom Beilis (Tonkikh) | |||
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) | |||
// | |||
// Distributed under the Boost Software License, Version 1.0. (See | |||
// accompanying file LICENSE_1_0.txt or copy at | |||
@@ -1,5 +1,5 @@ | |||
// | |||
// Copyright (c) 2009-2010 Artyom Beilis (Tonkikh) | |||
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) | |||
// | |||
// Distributed under the Boost Software License, Version 1.0. (See | |||
// accompanying file LICENSE_1_0.txt or copy at | |||
@@ -1,5 +1,5 @@ | |||
// | |||
// Copyright (c) 2009-2010 Artyom Beilis (Tonkikh) | |||
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) | |||
// | |||
// Distributed under the Boost Software License, Version 1.0. (See | |||
// accompanying file LICENSE_1_0.txt or copy at | |||
@@ -1,5 +1,5 @@ | |||
// | |||
// Copyright (c) 2009-2010 Artyom Beilis (Tonkikh) | |||
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) | |||
// | |||
// Distributed under the Boost Software License, Version 1.0. (See | |||
// accompanying file LICENSE_1_0.txt or copy at | |||
@@ -1,5 +1,5 @@ | |||
// | |||
// Copyright (c) 2009-2010 Artyom Beilis (Tonkikh) | |||
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) | |||
// | |||
// Distributed under the Boost Software License, Version 1.0. (See | |||
// accompanying file LICENSE_1_0.txt or copy at | |||
@@ -1,5 +1,5 @@ | |||
// | |||
// Copyright (c) 2009-2010 Artyom Beilis (Tonkikh) | |||
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) | |||
// | |||
// Distributed under the Boost Software License, Version 1.0. (See | |||
// accompanying file LICENSE_1_0.txt or copy at | |||
@@ -1,5 +1,5 @@ | |||
// | |||
// Copyright (c) 2009-2010 Artyom Beilis (Tonkikh) | |||
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) | |||
// | |||
// Distributed under the Boost Software License, Version 1.0. (See | |||
// accompanying file LICENSE_1_0.txt or copy at | |||
@@ -1,5 +1,5 @@ | |||
// | |||
// Copyright (c) 2009-2010 Artyom Beilis (Tonkikh) | |||
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) | |||
// | |||
// Distributed under the Boost Software License, Version 1.0. (See | |||
// accompanying file LICENSE_1_0.txt or copy at | |||
@@ -1,5 +1,5 @@ | |||
// | |||
// Copyright (c) 2009-2010 Artyom Beilis (Tonkikh) | |||
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) | |||
// | |||
// Distributed under the Boost Software License, Version 1.0. (See | |||
// accompanying file LICENSE_1_0.txt or copy at | |||
@@ -1,5 +1,5 @@ | |||
// | |||
// Copyright (c) 2009-2010 Artyom Beilis (Tonkikh) | |||
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) | |||
// | |||
// Distributed under the Boost Software License, Version 1.0. (See | |||
// accompanying file LICENSE_1_0.txt or copy at | |||
@@ -1,5 +1,5 @@ | |||
// | |||
// Copyright (c) 2009-2010 Artyom Beilis (Tonkikh) | |||
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) | |||
// | |||
// Distributed under the Boost Software License, Version 1.0. (See | |||
// accompanying file LICENSE_1_0.txt or copy at | |||
@@ -1,5 +1,5 @@ | |||
// | |||
// Copyright (c) 2009-2010 Artyom Beilis (Tonkikh) | |||
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) | |||
// | |||
// Distributed under the Boost Software License, Version 1.0. (See | |||
// accompanying file LICENSE_1_0.txt or copy at | |||
@@ -10,6 +10,7 @@ | |||
#include <booster/locale/gnu_gettext.h> | |||
#include "all_generator.h" | |||
#include "../util/locale_data.h" | |||
#include "../util/gregorian.h" | |||
#include <booster/locale/util.h> | |||
#if defined(BOOSTER_WIN_NATIVE) | |||
@@ -163,6 +164,8 @@ namespace impl_std { | |||
return create_parsing(base,name_,type,utf_mode_); | |||
case codepage_facet: | |||
return create_codecvt(base,name_,type,utf_mode_); | |||
case calendar_facet: | |||
return util::install_gregorian_calendar(base,data_.country); | |||
case message_facet: | |||
{ | |||
gnu_gettext::messages_info minf; | |||
@@ -1,5 +1,5 @@ | |||
// | |||
// Copyright (c) 2009-2010 Artyom Beilis (Tonkikh) | |||
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) | |||
// | |||
// Distributed under the Boost Software License, Version 1.0. (See | |||
// accompanying file LICENSE_1_0.txt or copy at | |||
@@ -1,5 +1,5 @@ | |||
// | |||
// Copyright (c) 2009-2010 Artyom Beilis (Tonkikh) | |||
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) | |||
// | |||
// Distributed under the Boost Software License, Version 1.0. (See | |||
// accompanying file LICENSE_1_0.txt or copy at | |||
@@ -1,5 +1,5 @@ | |||
// | |||
// Copyright (c) 2009-2010 Artyom Beilis (Tonkikh) | |||
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) | |||
// | |||
// Distributed under the Boost Software License, Version 1.0. (See | |||
// accompanying file LICENSE_1_0.txt or copy at | |||
@@ -0,0 +1,834 @@ | |||
// | |||
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) | |||
// | |||
// Distributed under the Boost Software License, Version 1.0. (See | |||
// accompanying file LICENSE_1_0.txt or copy at | |||
// http://www.boost.org/LICENSE_1_0.txt) | |||
// | |||
#define BOOSTER_SOURCE | |||
#include <locale> | |||
#include <string> | |||
#include <ios> | |||
#include <booster/locale/date_time_facet.h> | |||
#include <booster/locale/date_time.h> | |||
#include <stdlib.h> | |||
#include <ctime> | |||
#include <memory> | |||
#include <algorithm> | |||
#include <limits> | |||
#include "timezone.h" | |||
#include "gregorian.h" | |||
namespace booster { | |||
namespace locale { | |||
namespace util { | |||
namespace { | |||
int is_leap(int year) | |||
{ | |||
if(year % 400 == 0) | |||
return 1; | |||
if(year % 100 == 0) | |||
return 0; | |||
if(year % 4 == 0) | |||
return 1; | |||
return 0; | |||
} | |||
int days_in_month(int year,int month) | |||
{ | |||
static const int tbl[2][12] = { | |||
{ 31,28,31,30,31,30,31,31,30,31,30,31 }, | |||
{ 31,29,31,30,31,30,31,31,30,31,30,31 } | |||
}; | |||
return tbl[is_leap(year)][month - 1]; | |||
} | |||
inline int days_from_0(int year) | |||
{ | |||
year--; | |||
return 365 * year + (year / 400) - (year/100) + (year / 4); | |||
} | |||
int days_from_1970(int year) | |||
{ | |||
static const int days_from_0_to_1970 = days_from_0(1970); | |||
return days_from_0(year) - days_from_0_to_1970; | |||
} | |||
int days_from_1jan(int year,int month,int day) | |||
{ | |||
static const int days[2][12] = { | |||
{ 0,31,59,90,120,151,181,212,243,273,304,334 }, | |||
{ 0,31,60,91,121,152,182,213,244,274,305,335 } | |||
}; | |||
return days[is_leap(year)][month-1] + day - 1; | |||
} | |||
time_t internal_timegm(std::tm const *t) | |||
{ | |||
int year = t->tm_year + 1900; | |||
int month = t->tm_mon; | |||
if(month > 11) { | |||
year += month/12; | |||
month %= 12; | |||
} | |||
else if(month < 0) { | |||
int years_diff = (-month + 11)/12; | |||
year -= years_diff; | |||
month+=12 * years_diff; | |||
} | |||
month++; | |||
int day = t->tm_mday; | |||
int day_of_year = days_from_1jan(year,month,day); | |||
int days_since_epoch = days_from_1970(year) + day_of_year; | |||
time_t seconds_in_day = 3600 * 24; | |||
time_t result = seconds_in_day * days_since_epoch + 3600 * t->tm_hour + 60 * t->tm_min + t->tm_sec; | |||
return result; | |||
} | |||
} // anon | |||
namespace { | |||
// Locale dependent data | |||
bool comparator(char const *left,char const *right) | |||
{ | |||
return strcmp(left,right) < 0; | |||
} | |||
// | |||
// Ref: CLDR 1.9 common/supplemental/supplementalData.xml | |||
// | |||
// monday - default | |||
// fri - MV | |||
// sat - AE AF BH DJ DZ EG ER ET IQ IR JO KE KW LY MA OM QA SA SD SO SY TN YE | |||
// sun - AR AS AZ BW CA CN FO GE GL GU HK IL IN JM JP KG KR LA MH MN MO MP MT NZ PH PK SG TH TT TW UM US UZ VI ZW | |||
// | |||
int first_day_of_week(char const *terr) { | |||
static char const * const sat[] = { | |||
"AE","AF","BH","DJ","DZ","EG","ER","ET","IQ","IR", | |||
"JO","KE","KW","LY","MA","OM","QA","SA","SD","SO", | |||
"SY","TN","YE" | |||
}; | |||
static char const * const sun[] = { | |||
"AR","AS","AZ","BW","CA","CN","FO","GE","GL","GU", | |||
"HK","IL","IN","JM","JP","KG","KR","LA","MH","MN", | |||
"MO","MP","MT","NZ","PH","PK","SG","TH","TT","TW", | |||
"UM","US","UZ","VI","ZW" | |||
}; | |||
if(strcmp(terr,"MV") == 0) | |||
return 5; // fri | |||
if(std::binary_search<char const * const *>(sat,sat+sizeof(sat)/(sizeof(sat[0])),terr,comparator)) | |||
return 6; // sat | |||
if(std::binary_search<char const * const *>(sun,sun+sizeof(sun)/(sizeof(sun[0])),terr,comparator)) | |||
return 0; // sun | |||
// default | |||
return 1; // mon | |||
} | |||
} | |||
class gregorian_calendar : public abstract_calendar { | |||
public: | |||
gregorian_calendar(std::string const &terr) | |||
{ | |||
first_day_of_week_ = first_day_of_week(terr.c_str()); | |||
time_ = time(0); | |||
is_local_ = true; | |||
tzoff_ = 0; | |||
from_time(time_); | |||
} | |||
/// | |||
/// Make a polymorphic copy of the calendar | |||
/// | |||
virtual gregorian_calendar *clone() const | |||
{ | |||
return new gregorian_calendar(*this); | |||
} | |||
/// | |||
/// Set specific \a value for period \a p, note not all values are settable. | |||
/// | |||
virtual void set_value(period::period_type p,int value) | |||
{ | |||
using namespace period; | |||
std::tm t = tm_; | |||
switch(p) { | |||
case era: ///< Era i.e. AC, BC in Gregorian and Julian calendar, range [0,1] | |||
return; | |||
case year: ///< Year, it is calendar specific | |||
case extended_year: ///< Extended year for Gregorian/Julian calendars, where 1 BC == 0, 2 BC == -1. | |||
t.tm_year = value - 1900; | |||
break; | |||
case month: | |||
t.tm_mon = value; | |||
break; | |||
case day: | |||
t.tm_mday = value; | |||
break; | |||
case hour: ///< 24 clock hour [0..23] | |||
t.tm_hour = value; | |||
break; | |||
case hour_12: ///< 12 clock hour [0..11] | |||
t.tm_hour = t.tm_hour / 12 * 12 + value; | |||
break; | |||
case am_pm: ///< am or pm marker, [0..1] | |||
t.tm_hour = 12 * value + t.tm_hour % 12; | |||
break; | |||
case minute: ///< minute [0..59] | |||
t.tm_min = value; | |||
break; | |||
case second: | |||
t.tm_sec = value; | |||
break; | |||
case day_of_year: | |||
t.tm_mday += (value - (t.tm_yday + 1)); | |||
break; | |||
case day_of_week: ///< Day of week, starting from Sunday, [1..7] | |||
if(value < 1) // make sure it is positive | |||
value += (-value / 7) * 7 + 7; | |||
// convert to local DOW | |||
value = (value - 1 - first_day_of_week_ + 14) % 7 + 1; | |||
// fall throght | |||
case day_of_week_local: ///< Local day of week, for example in France Monday is 1, in US Sunday is 1, [1..7] | |||
t.tm_mday += (value - 1) - (t.tm_wday - first_day_of_week_ + 7) % 7; | |||
break; | |||
case day_of_week_in_month: ///< Original number of the day of the week in month. (1st sunday, 2nd sunday etc) | |||
case week_of_year: ///< The week number in the year, 4 is the minimal number of days to be in month | |||
case week_of_month: ///< The week number withing current month | |||
{ | |||
int current_week = get_value(p,current); | |||
int diff = 7 * (value - current_week); | |||
t.tm_mday += diff; | |||
} | |||
break; | |||
case period::first_day_of_week: ///< For example Sunday in US, Monday in France | |||
default: | |||
return; | |||
} | |||
from_tm(t); | |||
} | |||
int get_week_number(int day,int wday) const | |||
{ | |||
/// | |||
/// This is the number of days that are considered withing | |||
/// period such that the week belongs there | |||
/// | |||
static const int days_in_full_week = 4; | |||
// Alaways use local week start | |||
int current_dow = (wday - first_day_of_week_ + 7) % 7; | |||
// Calculate local week day of Jan 1st. | |||
int first_week_day = (current_dow + 700 - day) % 7; | |||
// adding something big devidable by 7 | |||
int start_of_period_in_weeks; | |||
if(first_week_day < days_in_full_week) { | |||
start_of_period_in_weeks = - first_week_day; | |||
} | |||
else { | |||
start_of_period_in_weeks = 7 - first_week_day; | |||
} | |||
int week_number_in_days = day - start_of_period_in_weeks; | |||
if(week_number_in_days < 0) | |||
return -1; | |||
return week_number_in_days / 7 + 1; | |||
} | |||
/// | |||
/// Get specific value for period \a p according to a value_type \a v | |||
/// | |||
virtual int get_value(period::period_type p,value_type v) const | |||
{ | |||
using namespace period; | |||
switch(p) { | |||
case era: | |||
return 1; | |||
case year: | |||
case extended_year: | |||
switch(v) { | |||
case absolute_minimum: | |||
case greatest_minimum: | |||
case actual_minimum: | |||
#ifdef BOOSTER_WIN_NATIVE | |||
return 1970; // Unix epoch windows can't handle negative time_t | |||
#else | |||
if(sizeof(time_t) == 4) | |||
return 1901; // minimal year with 32 bit time_t | |||
else | |||
return 1; | |||
#endif | |||
case absolute_maximum: | |||
case least_maximum: | |||
case actual_maximum: | |||
if(sizeof(time_t) == 4) | |||
return 2038; // Y2K38 - maximal with 32 bit time_t | |||
else | |||
return std::numeric_limits<int>::max(); | |||
case current: | |||
return tm_.tm_year + 1900; | |||
}; | |||
break; | |||
case month: | |||
switch(v) { | |||
case absolute_minimum: | |||
case greatest_minimum: | |||
case actual_minimum: | |||
return 0; | |||
case absolute_maximum: | |||
case least_maximum: | |||
case actual_maximum: | |||
return 11; | |||
case current: | |||
return tm_.tm_mon; | |||
}; | |||
break; | |||
case day: | |||
switch(v) { | |||
case absolute_minimum: | |||
case greatest_minimum: | |||
case actual_minimum: | |||
return 1; | |||
case absolute_maximum: | |||
return 31; | |||
case least_maximum: | |||
return 28; | |||
case actual_maximum: | |||
return days_in_month(tm_.tm_year + 1900,tm_.tm_mon + 1); | |||
case current: | |||
return tm_.tm_mday; | |||
}; | |||
break; | |||
case day_of_year: ///< The number of day in year, starting from 1 | |||
switch(v) { | |||
case absolute_minimum: | |||
case greatest_minimum: | |||
case actual_minimum: | |||
return 1; | |||
case absolute_maximum: | |||
return 366; | |||
case least_maximum: | |||
return 365; | |||
case actual_maximum: | |||
return is_leap(tm_.tm_year + 1900) ? 366 : 365; | |||
case current: | |||
return tm_.tm_yday + 1; | |||
} | |||
break; | |||
case day_of_week: ///< Day of week, starting from Sunday, [1..7] | |||
switch(v) { | |||
case absolute_minimum: | |||
case greatest_minimum: | |||
case actual_minimum: | |||
return 1; | |||
case absolute_maximum: | |||
case least_maximum: | |||
case actual_maximum: | |||
return 7; | |||
case current: | |||
return tm_.tm_wday + 1; | |||
} | |||
break; | |||
case day_of_week_local: ///< Local day of week, for example in France Monday is 1, in US Sunday is 1, [1..7] | |||
switch(v) { | |||
case absolute_minimum: | |||
case greatest_minimum: | |||
case actual_minimum: | |||
return 1; | |||
case absolute_maximum: | |||
case least_maximum: | |||
case actual_maximum: | |||
return 7; | |||
case current: | |||
return (tm_.tm_wday - first_day_of_week_ + 7) % 7 + 1; | |||
} | |||
break; | |||
case hour: ///< 24 clock hour [0..23] | |||
switch(v) { | |||
case absolute_minimum: | |||
case greatest_minimum: | |||
case actual_minimum: | |||
return 0; | |||
case absolute_maximum: | |||
case least_maximum: | |||
case actual_maximum: | |||
return 23; | |||
case current: | |||
return tm_.tm_hour; | |||
} | |||
break; | |||
case hour_12: ///< 12 clock hour [0..11] | |||
switch(v) { | |||
case absolute_minimum: | |||
case greatest_minimum: | |||
case actual_minimum: | |||
return 0; | |||
case absolute_maximum: | |||
case least_maximum: | |||
case actual_maximum: | |||
return 11; | |||
case current: | |||
return tm_.tm_hour % 12; | |||
} | |||
break; | |||
case am_pm: ///< am or pm marker, [0..1] | |||
switch(v) { | |||
case absolute_minimum: | |||
case greatest_minimum: | |||
case actual_minimum: | |||
return 0; | |||
case absolute_maximum: | |||
case least_maximum: | |||
case actual_maximum: | |||
return 1; | |||
case current: | |||
return tm_.tm_hour >= 12 ? 1 : 0; | |||
} | |||
break; | |||
case minute: ///< minute [0..59] | |||
switch(v) { | |||
case absolute_minimum: | |||
case greatest_minimum: | |||
case actual_minimum: | |||
return 0; | |||
case absolute_maximum: | |||
case least_maximum: | |||
case actual_maximum: | |||
return 59; | |||
case current: | |||
return tm_.tm_min; | |||
} | |||
break; | |||
case second: ///< second [0..59] | |||
switch(v) { | |||
case absolute_minimum: | |||
case greatest_minimum: | |||
case actual_minimum: | |||
return 0; | |||
case absolute_maximum: | |||
case least_maximum: | |||
case actual_maximum: | |||
return 59; | |||
case current: | |||
return tm_.tm_sec; | |||
} | |||
break; | |||
case period::first_day_of_week: ///< For example Sunday in US, Monday in France | |||
return first_day_of_week_ + 1; | |||
case week_of_year: ///< The week number in the year | |||
switch(v) { | |||
case absolute_minimum: | |||
case greatest_minimum: | |||
case actual_minimum: | |||
return 1; | |||
case absolute_maximum: | |||
return 53; | |||
case least_maximum: | |||
return 52; | |||
case actual_maximum: | |||
{ | |||
int year = tm_.tm_year + 1900; | |||
int end_of_year_days = (is_leap(year) ? 366 : 365) - 1; | |||
int dow_of_end_of_year = (end_of_year_days - tm_.tm_yday + tm_.tm_wday) % 7; | |||
return get_week_number(end_of_year_days,dow_of_end_of_year); | |||
} | |||
case current: | |||
{ | |||
int val = get_week_number(tm_.tm_yday,tm_.tm_wday); | |||
if(val < 0) | |||
return 53; | |||
return val; | |||
} | |||
} | |||
case week_of_month: ///< The week number withing current month | |||
switch(v) { | |||
case absolute_minimum: | |||
case greatest_minimum: | |||
case actual_minimum: | |||
return 1; | |||
case absolute_maximum: | |||
return 5; | |||
case least_maximum: | |||
return 4; | |||
case actual_maximum: | |||
{ | |||
int end_of_month_days = days_in_month(tm_.tm_year + 1900,tm_.tm_mon + 1); | |||
int dow_of_end_of_month = (end_of_month_days - tm_.tm_mday + tm_.tm_wday) % 7; | |||
return get_week_number(end_of_month_days,dow_of_end_of_month); | |||
} | |||
case current: | |||
{ | |||
int val = get_week_number(tm_.tm_mday,tm_.tm_wday); | |||
if(val < 0) | |||
return 5; | |||
return val; | |||
} | |||
} | |||
case day_of_week_in_month: ///< Original number of the day of the week in month. | |||
switch(v) { | |||
case absolute_minimum: | |||
case greatest_minimum: | |||
case actual_minimum: | |||
return 1; | |||
case absolute_maximum: | |||
return 5; | |||
case least_maximum: | |||
return 4; | |||
case actual_maximum: | |||
if(tm_.tm_mon == 1 && !is_leap(tm_.tm_year + 1900)) { | |||
// only in february in non leap year is 28 days, the rest | |||
// conver more then 4 weeks | |||
return 4; | |||
} | |||
return 5; | |||
case current: | |||
return (tm_.tm_mday - 1) / 7 + 1; | |||
default: | |||
; | |||
} | |||
default: | |||
; | |||
} | |||
return 0; | |||
} | |||
/// | |||
/// Set current time point | |||
/// | |||
virtual void set_time(posix_time const &p) | |||
{ | |||
from_time(static_cast<time_t>(p.seconds)); | |||
} | |||
virtual posix_time get_time() const | |||
{ | |||
posix_time pt = { time_, 0}; | |||
return pt; | |||
} | |||
/// | |||
/// Set option for calendar, for future use | |||
/// | |||
virtual void set_option(calendar_option_type opt,int /*v*/) | |||
{ | |||
switch(opt) { | |||
case is_gregorian: | |||
throw date_time_error("is_gregorian is not settable options for calendar"); | |||
case is_dst: | |||
throw date_time_error("is_dst is not settable options for calendar"); | |||
default: | |||
; | |||
} | |||
} | |||
/// | |||
/// Get option for calendar, currently only check if it is Gregorian calendar | |||
/// | |||
virtual int get_option(calendar_option_type opt) const | |||
{ | |||
switch(opt) { | |||
case is_gregorian: | |||
return 1; | |||
case is_dst: | |||
return tm_.tm_isdst == 1; | |||
default: | |||
return 0; | |||
}; | |||
} | |||
/// | |||
/// Adjust period's \a p value by \a difference items using a update_type \a u. | |||
/// Note: not all values are adjustable | |||
/// | |||
virtual void adjust_value(period::period_type p,update_type u,int difference) | |||
{ | |||
switch(u) { | |||
case move: | |||
{ | |||
using namespace period; | |||
std::tm t = tm_; | |||
switch(p) { | |||
case year: ///< Year, it is calendar specific | |||
case extended_year: ///< Extended year for Gregorian/Julian calendars, where 1 BC == 0, 2 BC == -1. | |||
t.tm_year +=difference; | |||
break; | |||
case month: | |||
t.tm_mon +=difference; | |||
break; | |||
case day: | |||
case day_of_year: | |||
case day_of_week: ///< Day of week, starting from Sunday, [1..7] | |||
case day_of_week_local: ///< Local day of week, for example in France Monday is 1, in US Sunday is 1, [1..7] | |||
t.tm_mday +=difference; | |||
break; | |||
case hour: ///< 24 clock hour [0..23] | |||
case hour_12: ///< 12 clock hour [0..11] | |||
t.tm_hour += difference; | |||
break; | |||
case am_pm: ///< am or pm marker, [0..1] | |||
t.tm_hour += 12 * difference; | |||
break; | |||
case minute: ///< minute [0..59] | |||
t.tm_min += difference; | |||
break; | |||
case second: | |||
t.tm_sec += difference; | |||
break; | |||
case week_of_year: ///< The week number in the year | |||
case week_of_month: ///< The week number withing current month | |||
case day_of_week_in_month: ///< Original number of the day of the week in month. | |||
t.tm_mday +=difference * 7; | |||
break; | |||
default: | |||
; // Not all values are adjustable | |||
} | |||
from_tm(t); | |||
} | |||
break; | |||
case roll: | |||
{ // roll | |||
int cur_min = get_value(p,actual_minimum); | |||
int cur_max = get_value(p,actual_maximum); | |||
int max_diff = cur_max - cur_min + 1; | |||
if(max_diff > 0) { | |||
int value = get_value(p,current); | |||
int addon = 0; | |||
if(difference < 0) | |||
addon = ((-difference/max_diff) + 1) * max_diff; | |||
value = (value - cur_min + difference + addon) % max_diff + cur_min; | |||
set_value(p,value); | |||
} | |||
} | |||
default: | |||
; | |||
} | |||
} | |||
int get_diff(period::period_type p,int diff,gregorian_calendar const *other) const | |||
{ | |||
if(diff == 0) | |||
return 0; | |||
std::auto_ptr<gregorian_calendar> self(clone()); | |||
self->adjust_value(p,move,diff); | |||
if(diff > 0){ | |||
if(self->time_ > other->time_) | |||
return diff - 1; | |||
else | |||
return diff; | |||
} | |||
else { | |||
if(self->time_ < other->time_) | |||
return diff + 1; | |||
else | |||
return diff; | |||
} | |||
} | |||
/// | |||
/// Calculate the difference between this calendar and \a other in \a p units | |||
/// | |||
virtual int difference(abstract_calendar const *other_cal,period::period_type p) const | |||
{ | |||
std::auto_ptr<gregorian_calendar> keeper; | |||
gregorian_calendar const *other = dynamic_cast<gregorian_calendar const *>(other_cal); | |||
if(!other) { | |||
keeper.reset(clone()); | |||
keeper->set_time(other_cal->get_time()); | |||
other = keeper.get(); | |||
} | |||
int factor = 1; // for weeks vs days handling | |||
using namespace period; | |||
switch(p) { | |||
case era: | |||
return 0; | |||
case year: | |||
case extended_year: | |||
{ | |||
int diff = other->tm_.tm_year - tm_.tm_year; | |||
return get_diff(period::year,diff,other); | |||
} | |||
case month: | |||
{ | |||
int diff = 12 * (other->tm_.tm_year - tm_.tm_year) | |||
+ other->tm_.tm_mon - tm_.tm_mon; | |||
return get_diff(period::month,diff,other); | |||
} | |||
case day_of_week_in_month: | |||
case week_of_month: | |||
case week_of_year: | |||
factor = 7; | |||
// fall | |||
case day: | |||
case day_of_year: | |||
case day_of_week: | |||
case day_of_week_local: | |||
{ | |||
int diff = other->tm_.tm_yday - tm_.tm_yday; | |||
if(other->tm_.tm_year != tm_.tm_year) { | |||
diff += days_from_0(other->tm_.tm_year + 1900) - | |||
days_from_0(tm_.tm_year + 1900); | |||
} | |||
return get_diff(period::day,diff,other) / factor; | |||
} | |||
case am_pm: | |||
return static_cast<int>( (other->time_ - time_) / (3600*12) ); | |||
case hour: | |||
case hour_12: | |||
return static_cast<int>( (other->time_ - time_) / 3600 ); | |||
case minute: | |||
return static_cast<int>( (other->time_ - time_) / 60 ); | |||
case second: | |||
return static_cast<int>( other->time_ - time_ ); | |||
default: | |||
return 0; | |||
}; | |||
} | |||
/// | |||
/// Set time zone, empty - use system | |||
/// | |||
virtual void set_timezone(std::string const &tz) | |||
{ | |||
if(tz.empty()) { | |||
is_local_ = true; | |||
tzoff_ = 0; | |||
} | |||
else { | |||
is_local_ = false; | |||
tzoff_ = parse_tz(tz); | |||
} | |||
from_time(time_); | |||
time_zone_name_ = tz; | |||
} | |||
virtual std::string get_timezone() const | |||
{ | |||
return time_zone_name_; | |||
} | |||
virtual bool same(abstract_calendar const *other) const | |||
{ | |||
gregorian_calendar const *gcal = dynamic_cast<gregorian_calendar const *>(other); | |||
if(!gcal) | |||
return false; | |||
return | |||
gcal->tzoff_ == tzoff_ | |||
&& gcal->is_local_ == is_local_ | |||
&& gcal->first_day_of_week_ == first_day_of_week_; | |||
} | |||
virtual ~gregorian_calendar() | |||
{ | |||
} | |||
private: | |||
void from_tm(std::tm val) | |||
{ | |||
val.tm_isdst = -1; | |||
val.tm_wday = -1; // indecator of error | |||
time_t point = -1; | |||
if(is_local_) { | |||
point = mktime(&val); | |||
if(point == static_cast<time_t>(-1)){ | |||
#ifndef BOOSTER_WIN_NATIVE | |||
// windows does not handle negative time_t, under other plaforms | |||
// it may be actually valid value in 1969-12-31 23:59:59 | |||
// so we check that a filed was updated - does not happen in case of error | |||
if(val.tm_wday == -1) | |||
#endif | |||
{ | |||
throw date_time_error("boost::locale::gregorian_calendar: invalid time"); | |||
} | |||
} | |||
} | |||
else { | |||
point = internal_timegm(&val); | |||
#ifdef BOOSTER_WIN_NATIVE | |||
// Windows uses TLS, thread safe | |||
std::tm *revert_point = 0; | |||
if(point < 0 || (revert_point = gmtime(&point)) == 0) | |||
throw date_time_error("boost::locale::gregorian_calendar time is out of range"); | |||
val = *revert_point; | |||
#else | |||
if(!gmtime_r(&point,&val)) | |||
throw date_time_error("boost::locale::gregorian_calendar invalid time"); | |||
#endif | |||
} | |||
time_ = point - tzoff_; | |||
tm_ = val; | |||
} | |||
void from_time(time_t point) | |||
{ | |||
time_t real_point = point + tzoff_; | |||
std::tm *t = 0; | |||
#ifdef BOOSTER_WIN_NATIVE | |||
// Windows uses TLS, thread safe | |||
t = is_local_ ? localtime(&real_point) : gmtime(&real_point); | |||
#else | |||
std::tm tmp_tm; | |||
t = is_local_ ? localtime_r(&real_point,&tmp_tm) : gmtime_r(&real_point,&tmp_tm); | |||
#endif | |||
if(!t) { | |||
throw date_time_error("boost::locale::gregorian_calendar: invalid time point"); | |||
} | |||
tm_ = *t; | |||
time_ = point; | |||
} | |||
int first_day_of_week_; | |||
time_t time_; | |||
std::tm tm_; | |||
bool is_local_; | |||
int tzoff_; | |||
std::string time_zone_name_; | |||
}; | |||
abstract_calendar *create_gregorian_calendar(std::string const &terr) | |||
{ | |||
return new gregorian_calendar(terr); | |||
} | |||
class gregorian_facet : public calendar_facet { | |||
public: | |||
gregorian_facet(std::string const &terr,size_t refs = 0) : | |||
calendar_facet(refs), | |||
terr_(terr) | |||
{ | |||
} | |||
virtual abstract_calendar *create_calendar() const | |||
{ | |||
return create_gregorian_calendar(terr_); | |||
} | |||
private: | |||
std::string terr_; | |||
}; | |||
std::locale install_gregorian_calendar(std::locale const &in,std::string const &terr) | |||
{ | |||
return std::locale(in,new gregorian_facet(terr)); | |||
} | |||
} // util | |||
} // locale | |||
} //boost | |||
// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 |
@@ -1,520 +1,25 @@ | |||
// | |||
// Copyright (c) 2009-2010 Artyom Beilis (Tonkikh) | |||
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) | |||
// | |||
// Distributed under the Boost Software License, Version 1.0. (See | |||
// accompanying file LICENSE_1_0.txt or copy at | |||
// http://www.boost.org/LICENSE_1_0.txt) | |||
// | |||
#define BOOSTER_SOURCE | |||
#include <locale> | |||
#include <string> | |||
#include <ios> | |||
#include <booster/locale/date_time_facet.h> | |||
#include <sstream> | |||
#include <stdlib.h> | |||
#ifndef BOOSTER_LOCALE_SRC_UTIL_GREGORIAN_HPP | |||
#define BOOSTER_LOCALE_SRC_UTIL_GREGORIAN_HPP | |||
#include "timezone.h" | |||
#include <locale> | |||
namespace booster { | |||
namespace locale { | |||
namespace util { | |||
namespace { | |||
bool comparator(char const *left,char const *right) | |||
{ | |||
return strcmp(left,right) < 0; | |||
} | |||
// | |||
// Ref: CLDR 1.9 common/supplemental/supplementalData.xml | |||
// | |||
// monday - default | |||
// fri - MV | |||
// sat - AE AF BH DJ DZ EG ER ET IQ IR JO KE KW LY MA OM QA SA SD SO SY TN YE | |||
// sun - AR AS AZ BW CA CN FO GE GL GU HK IL IN JM JP KG KR LA MH MN MO MP MT NZ PH PK SG TH TT TW UM US UZ VI ZW | |||
// | |||
int first_day_of_week(char const *terr) { | |||
static char const * const sat[] = { | |||
"AE","AF","BH","DJ","DZ","EG","ER","ET","IQ","IR", | |||
"JO","KE","KW","LY","MA","OM","QA","SA","SD","SO", | |||
"SY","TN","YE" | |||
}; | |||
static char const * const sun[] = { | |||
"AR","AS","AZ","BW","CA","CN","FO","GE","GL","GU", | |||
"HK","IL","IN","JM","JP","KG","KR","LA","MH","MN", | |||
"MO","MP","MT","NZ","PH","PK","SG","TH","TT","TW", | |||
"UM","US","UZ","VI","ZW" | |||
}; | |||
if(strcmp(terr,"MV") == 0) | |||
return 5; // fri | |||
if(std::binary_search<char const * const *>(sat,sat+sizeof(sat)/(sizeof(sat[0])),terr,comparator)) | |||
return 6; // sat | |||
if(std::binary_search<char const * const *>(sun,sun+sizeof(sun)/(sizeof(sun[0])),terr,comparator)) | |||
return 0; // sun | |||
// default | |||
return 1; // mon | |||
} | |||
} | |||
class gregorian_calendar : public abstract_calendar { | |||
public: | |||
gregorian_calendar(std::string const &terr) | |||
{ | |||
first_day_of_week_ = first_day_of_week(terr.c_str()); | |||
time_ = time(0); | |||
is_local_ = true; | |||
tzoff_ = 0; | |||
from_time(time_); | |||
} | |||
/// | |||
/// Make a polymorphic copy of the calendar | |||
/// | |||
virtual abstract_calendar *clone() const | |||
{ | |||
return new gregorian_calendar(*this); | |||
} | |||
/// | |||
/// Set specific \a value for period \a p, note not all values are settable. | |||
/// | |||
virtual void set_value(period::period_type p,int value) | |||
{ | |||
std::tm t; | |||
switch(p) { | |||
case era: ///< Era i.e. AC, BC in Gregorian and Julian calendar, range [0,1] | |||
return; | |||
case year: ///< Year, it is calendar specific | |||
case extended_year: ///< Extended year for Gregorian/Julian calendars, where 1 BC == 0, 2 BC == -1. | |||
t.tm_year = value - 1900; | |||
break; | |||
case month: | |||
t.tm_mon = value; | |||
break; | |||
case day: | |||
t.tm_mday = value; | |||
break; | |||
case hour: ///< 24 clock hour [0..23] | |||
t.tm_hour = value; | |||
break; | |||
case hour_12: ///< 12 clock hour [0..11] | |||
t.tm_hour = t.tm_hour / 12 * 12 + value; | |||
break; | |||
case am_pm: ///< am or pm marker, [0..1] | |||
t.tm_hour = 12 * value + t.tm_hour % 12; | |||
break; | |||
case minute: ///< minute [0..59] | |||
t.tm_min = value; | |||
break; | |||
case second: | |||
t.tm_sec = value; | |||
break; | |||
case day_of_week: ///< Day of week, starting from Sunday, [1..7] | |||
case day_of_week_local: ///< Local day of week, for example in France Monday is 1, in US Sunday is 1, [1..7] | |||
// FIXME | |||
break; | |||
case day_of_year: | |||
t.tm_mday += (day_of_year - t.tm_yday); | |||
break; | |||
case day_of_week_in_month: ///< Original number of the day of the week in month. | |||
case week_of_year: ///< The week number in the year | |||
case week_of_month: ///< The week number withing current month | |||
// FIXME | |||
break; | |||
case first_day_of_week: ///< For example Sunday in US, Monday in France | |||
return; | |||
} | |||
from_tm(t); | |||
} | |||
/// | |||
/// Get specific value for period \a p according to a value_type \a v | |||
/// | |||
virtual int get_value(period::period_type p,value_type v) const | |||
{ | |||
switch(p) { | |||
case era; | |||
return 1; | |||
case year: | |||
case extended_year: | |||
switch(v) { | |||
case absolute_minimum: | |||
case greatest_minimum: | |||
case actual_minimum: | |||
#ifdef BOOSTER_WIN_NATIVE | |||
return 1970; // Unix epoch windows can't handle negative time_t | |||
#else | |||
if(sizeof(time_t) == 4) | |||
return 1901; // minimal year with 32 bit time_t | |||
else | |||
return 1; | |||
#endif | |||
case absolute_maximum: | |||
case least_maximum: | |||
case actual_maximum: | |||
if(sizeof(time_t) == 4) | |||
return 2038; // Y2K38 - maximal with 32 bit time_t | |||
else | |||
return std::numeric_limits<int>::max(); | |||
case current: | |||
return tm_.tm_year + 1900; | |||
}; | |||
break; | |||
case month: | |||
switch(v) { | |||
case absolute_minimum: | |||
case greatest_minimum: | |||
case actual_minimum: | |||
return 0; | |||
case absolute_maximum: | |||
case least_maximum: | |||
case actual_maximum: | |||
return 11; | |||
case current: | |||
return tm_.tm_mon; | |||
}; | |||
break; | |||
case day: | |||
switch(v) { | |||
case absolute_minimum: | |||
case greatest_minimum: | |||
case actual_minimum: | |||
return 1; | |||
case absolute_maximum: | |||
return 31; | |||
case least_maximum: | |||
return 28; | |||
case actual_maximum: | |||
switch(tm_.tm_mon + 1){ | |||
case 1: | |||
case 3: | |||
case 5: | |||
case 7: | |||
case 8: | |||
case 10: | |||
case 12: | |||
return 31; | |||
case 4: | |||
case 6: | |||
case 9: | |||
case 11: | |||
return 30; | |||
case 2: | |||
return is_leap() ? 29 : 28; | |||
} | |||
break; | |||
case current: | |||
return tm_.tm_mday; | |||
}; | |||
break; | |||
case day_of_year: ///< The number of day in year, starting from 1 | |||
switch(v) { | |||
case absolute_minimum: | |||
case greatest_minimum: | |||
case actual_minimum: | |||
return 1; | |||
case absolute_maximum: | |||
return 366; | |||
case least_maximum: | |||
return 365; | |||
case actual_maximum: | |||
return is_leap() ? 366 : 365; | |||
case current: | |||
return tm_.tm_yday; | |||
} | |||
break; | |||
case day_of_week: ///< Day of week, starting from Sunday, [1..7] | |||
switch(v) { | |||
case absolute_minimum: | |||
case greatest_minimum: | |||
case actual_minimum: | |||
return 1; | |||
case absolute_maximum: | |||
case least_maximum: | |||
case actual_maximum: | |||
return 7; | |||
case current: | |||
return tm_.tm_wday + 1; | |||
} | |||
break; | |||
case day_of_week_local: ///< Local day of week, for example in France Monday is 1, in US Sunday is 1, [1..7] | |||
switch(v) { | |||
case absolute_minimum: | |||
case greatest_minimum: | |||
case actual_minimum: | |||
return 1; | |||
case absolute_maximum: | |||
case least_maximum: | |||
case actual_maximum: | |||
return 7; | |||
case current: | |||
return (tm_.tm_wday - first_day_of_week_) % 7 + 1; | |||
} | |||
break; | |||
case hour: ///< 24 clock hour [0..23] | |||
switch(v) { | |||
case absolute_minimum: | |||
case greatest_minimum: | |||
case actual_minimum: | |||
return 0; | |||
case absolute_maximum: | |||
case least_maximum: | |||
case actual_maximum: | |||
return 23; | |||
case current: | |||
return tm_.tm_hour; | |||
} | |||
break; | |||
case hour_12: ///< 12 clock hour [0..11] | |||
switch(v) { | |||
case absolute_minimum: | |||
case greatest_minimum: | |||
case actual_minimum: | |||
return 0; | |||
case absolute_maximum: | |||
case least_maximum: | |||
case actual_maximum: | |||
return 11; | |||
case current: | |||
return tm_.tm_hour % 12; | |||
} | |||
break; | |||
case am_pm: ///< am or pm marker, [0..1] | |||
switch(v) { | |||
case absolute_minimum: | |||
case greatest_minimum: | |||
case actual_minimum: | |||
return 0; | |||
case absolute_maximum: | |||
case least_maximum: | |||
case actual_maximum: | |||
return 1; | |||
case current: | |||
return tm_.tm_hour >= 12 ? 1 : 0; | |||
} | |||
break; | |||
case minute: ///< minute [0..59] | |||
switch(v) { | |||
case absolute_minimum: | |||
case greatest_minimum: | |||
case actual_minimum: | |||
return 0; | |||
case absolute_maximum: | |||
case least_maximum: | |||
case actual_maximum: | |||
return 59; | |||
case current: | |||
return tm_.tm_min; | |||
} | |||
break; | |||
case second: ///< second [0..59] | |||
switch(v) { | |||
case absolute_minimum: | |||
case greatest_minimum: | |||
case actual_minimum: | |||
return 0; | |||
case absolute_maximum: | |||
case least_maximum: | |||
case actual_maximum: | |||
return 59; | |||
case current: | |||
return tm_.tm_sec; | |||
} | |||
break; | |||
case first_day_of_week: ///< For example Sunday in US, Monday in France | |||
return first_day_of_week_ + 1; | |||
case week_of_year: ///< The week number in the year | |||
case week_of_month: ///< The week number withing current month | |||
case day_of_week_in_month: ///< Original number of the day of the week in month. | |||
// FIXME | |||
; | |||
} | |||
return 0; | |||
} | |||
/// | |||
/// Set current time point | |||
/// | |||
virtual void set_time(posix_time const &p) | |||
{ | |||
from_time(static_cast<time_t>(p.seconds)); | |||
} | |||
virtual posix_time get_time() const | |||
{ | |||
posix_time pt = { time_, 0}; | |||
return pt; | |||
} | |||
/// | |||
/// Set option for calendar, for future use | |||
/// | |||
virtual void set_option(calendar_option_type /*opt*/,int /*v*/) | |||
{ | |||
// Nothing to do now | |||
} | |||
/// | |||
/// Get option for calendar, currently only check if it is Gregorian calendar | |||
/// | |||
virtual int get_option(calendar_option_type opt) const | |||
{ | |||
switch(opt) { | |||
case is_gregorian: | |||
return 1; | |||
default: | |||
return 0; | |||
}; | |||
} | |||
/// | |||
/// Adjust period's \a p value by \a difference items using a update_type \a u. | |||
/// Note: not all values are adjustable | |||
/// | |||
virtual void adjust_value(period::period_type p,update_type u,int difference) | |||
{ | |||
switch(update_type) { | |||
case move: | |||
set_value(p,get_value(p,current) + difference); | |||
break; | |||
case roll: | |||
{ // roll | |||
int cur_min = get_value(p,actual_minimum); | |||
int cur_max = get_value(p,actual_maximum); | |||
int max_diff = cur_max - cur_min; | |||
if(max_diff > 0) { | |||
int value = get_value(p,current); | |||
value = (value - cur_min + difference) % max_diff + cur_min; | |||
set_value(p,value); | |||
} | |||
} | |||
default: | |||
; | |||
} | |||
} | |||
/// | |||
/// Calculate the difference between this calendar and \a other in \a p units | |||
/// | |||
virtual int difference(abstract_calendar const *other_cal,period::period_type p) const | |||
{ | |||
std::auto_ptr<gregorian_calendar> other(clone()); | |||
other->set_time(other_cal->get_time()); | |||
switch(p) { | |||
case year: | |||
case extended_year: | |||
return other->tm_.tm_year - tm_.year; | |||
case month: | |||
return (other->tm_.tm_year - tm_.year) * 12 | |||
+ other->tm_.tm_mon_ - tm_->tm_mon; | |||
case day: | |||
case day_of_year: | |||
case day_of_week: | |||
case day_of_week_in_month: | |||
case day_of_week_local: | |||
case week_of_month: | |||
; | |||
}; | |||
} | |||
/// | |||
/// Set time zone, empty - use system | |||
/// | |||
virtual void set_timezone(std::string const &tz) | |||
{ | |||
if(tz.empty()) { | |||
is_local_ = true; | |||
tzoff_ = 0; | |||
} | |||
else { | |||
is_local_ = false; | |||
tzoff_ = parse_tz(tz); | |||
} | |||
from_time(time_); | |||
time_zone_name_ = tz; | |||
} | |||
virtual std::string get_timezone() const | |||
{ | |||
return time_zone_name_; | |||
} | |||
virtual bool same(abstract_calendar const *other) const | |||
{ | |||
gregorian_calendar const *gcal = dynamic_cast<gregorian_calendar const *>(other); | |||
if(!gcal) | |||
return false; | |||
return | |||
gcal->tzoff_ == tzoff_ | |||
&& gcal_->is_local_ == is_local_ | |||
&& gcal_->first_day_of_week_ == first_day_of_week_; | |||
} | |||
virtual ~abstract_calendar() | |||
{ | |||
} | |||
private: | |||
void from_tm(std::tm val) | |||
{ | |||
val.tm_isdst = -1; | |||
val.tm_wday = -1; // indecatpr of error | |||
time_t point = -1; | |||
if(is_local_) { | |||
point = mktime(&val); | |||
} | |||
else { | |||
point = my_timegm(&val); | |||
} | |||
if(point == static_cast<time_t>(-1)){ | |||
#ifndef BOOSTER_WIN_NATIVE | |||
// windows does not handle negative time_t, under | |||
// linux it may be actually valid so we check other fields | |||
if(val.tm_wday == -1) | |||
#endif | |||
{ | |||
throw booster::invalid_argument("boost::locale::gregorian_calendar: invalid time"); | |||
} | |||
} | |||
time_ = point - tzoff_; | |||
} | |||
void from_time(time_t point) | |||
{ | |||
time_t real_point = point + tzoff_; | |||
std::tm *t = 0; | |||
#ifdef BOOSTER_WIN_NATIVE | |||
t = is_local_ ? localtime(&real_point) : gmtime(&real_point); | |||
#else | |||
std::tm tmp_tm; | |||
t = is_local_ ? localtime_r(&real_point,&tmp_tm) : gmtime_r(&real_point,&tmp_tm); | |||
#endif | |||
if(!t) { | |||
throw booster::invalid_argument("boost::locale::gregorian_calendar: invalid time point"); | |||
} | |||
tm_ = *t; | |||
time_ = point; | |||
} | |||
int first_day_of_week_; | |||
time_t time_; | |||
std::tm tm_; | |||
bool is_local_; | |||
int tzoff_; | |||
std::string time_zone_name_; | |||
}; | |||
std::locale install_gregorian_calendar(std::locale const &in,std::string const &terr); | |||
} // util | |||
} // locale | |||
} //boost | |||
#endif | |||
// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 |
@@ -1,5 +1,5 @@ | |||
// | |||
// Copyright (c) 2009-2010 Artyom Beilis (Tonkikh) | |||
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) | |||
// | |||
// Distributed under the Boost Software License, Version 1.0. (See | |||
// accompanying file LICENSE_1_0.txt or copy at | |||
@@ -1,5 +1,5 @@ | |||
// | |||
// Copyright (c) 2009-2010 Artyom Beilis (Tonkikh) | |||
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) | |||
// | |||
// Distributed under the Boost Software License, Version 1.0. (See | |||
// accompanying file LICENSE_1_0.txt or copy at | |||
@@ -46,7 +46,7 @@ namespace util { | |||
}; | |||
} | |||
virtual int get_ineger_property(integer_property v) const | |||
virtual int get_integer_property(integer_property v) const | |||
{ | |||
switch(v) { | |||
case utf8_property: | |||
@@ -1,5 +1,5 @@ | |||
// | |||
// Copyright (c) 2009-2010 Artyom Beilis (Tonkikh) | |||
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) | |||
// | |||
// Distributed under the Boost Software License, Version 1.0. (See | |||
// accompanying file LICENSE_1_0.txt or copy at | |||
@@ -1,5 +1,5 @@ | |||
// | |||
// Copyright (c) 2009-2010 Artyom Beilis (Tonkikh) | |||
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) | |||
// | |||
// Distributed under the Boost Software License, Version 1.0. (See | |||
// accompanying file LICENSE_1_0.txt or copy at | |||
@@ -1,5 +1,5 @@ | |||
// | |||
// Copyright (c) 2009-2010 Artyom Beilis (Tonkikh) | |||
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) | |||
// | |||
// Distributed under the Boost Software License, Version 1.0. (See | |||
// accompanying file LICENSE_1_0.txt or copy at | |||
@@ -11,6 +11,7 @@ | |||
#include <string> | |||
#include <ios> | |||
#include <booster/locale/formatting.h> | |||
#include <booster/locale/info.h> | |||
#include <sstream> | |||
#include <stdlib.h> | |||
@@ -21,6 +22,38 @@ namespace locale { | |||
namespace util { | |||
template<typename CharType> | |||
struct formatting_size_traits { | |||
static size_t size(std::basic_string<CharType> const &s,std::locale const &/*l*/) | |||
{ | |||
return s.size(); | |||
} | |||
}; | |||
template<> | |||
struct formatting_size_traits<char> { | |||
static size_t size(std::string const &s,std::locale const &l) | |||
{ | |||
if(!std::has_facet<info>(l)) | |||
return s.size(); | |||
if(!std::use_facet<info>(l).utf8()) | |||
return s.size(); | |||
// count code points, poor man's text size | |||
size_t res = 0; | |||
for(size_t i=0;i<s.size();i++) { | |||
unsigned char c = s[i]; | |||
if(c <= 127) | |||
res ++; | |||
else if ((c & 0xC0) == 0xC0) { // first UTF-8 byte | |||
res ++; | |||
} | |||
} | |||
return res; | |||
} | |||
}; | |||
template<typename CharType> | |||
class base_num_format : public std::num_put<CharType> | |||
{ | |||
public: | |||
@@ -179,7 +212,36 @@ private: | |||
} | |||
#endif | |||
} | |||
return std::use_facet<std::time_put<char_type> >(ios.getloc()).put(out,ios,fill,&tm,format.c_str(),format.c_str()+format.size()); | |||
std::basic_ostringstream<char_type> tmp_out; | |||
std::use_facet<std::time_put<char_type> >(ios.getloc()).put(tmp_out,tmp_out,fill,&tm,format.c_str(),format.c_str()+format.size()); | |||
string_type str = tmp_out.str(); | |||
std::streamsize on_left=0,on_right = 0; | |||
std::streamsize points = | |||
formatting_size_traits<char_type>::size(str,ios.getloc()); | |||
if(points < ios.width()) { | |||
std::streamsize n = ios.width() - points; | |||
std::ios_base::fmtflags flags = ios.flags() & std::ios_base::adjustfield; | |||
// | |||
// we do not really know internal point, so we assume that it does not | |||
// exists. so according to standard field should be right aligned | |||
// | |||
if(flags != std::ios_base::left) | |||
on_left = n; | |||
on_right = n - on_left; | |||
} | |||
while(on_left > 0) { | |||
*out++ = fill; | |||
on_left--; | |||
} | |||
std::copy(str.begin(),str.end(),out); | |||
while(on_right > 0) { | |||
*out++ = fill; | |||
on_right--; | |||
} | |||
ios.width(0); | |||
return out; | |||
} | |||
}; /// num_format | |||
@@ -1,5 +1,5 @@ | |||
// | |||
// Copyright (c) 2009-2010 Artyom Beilis (Tonkikh) | |||
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) | |||
// | |||
// Distributed under the Boost Software License, Version 1.0. (See | |||
// accompanying file LICENSE_1_0.txt or copy at | |||
@@ -1,5 +1,5 @@ | |||
// | |||
// Copyright (c) 2009-2010 Artyom Beilis (Tonkikh) | |||
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) | |||
// | |||
// Distributed under the Boost Software License, Version 1.0. (See | |||
// accompanying file LICENSE_1_0.txt or copy at | |||
@@ -1,5 +1,5 @@ | |||
// | |||
// Copyright (c) 2009-2010 Artyom Beilis (Tonkikh) | |||
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) | |||
// | |||
// Distributed under the Boost Software License, Version 1.0. (See | |||
// accompanying file LICENSE_1_0.txt or copy at | |||
@@ -1,5 +1,5 @@ | |||
// | |||
// Copyright (c) 2009-2010 Artyom Beilis (Tonkikh) | |||
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) | |||
// | |||
// Distributed under the Boost Software License, Version 1.0. (See | |||
// accompanying file LICENSE_1_0.txt or copy at | |||
@@ -1,5 +1,5 @@ | |||
// | |||
// Copyright (c) 2009-2010 Artyom Beilis (Tonkikh) | |||
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) | |||
// | |||
// Distributed under the Boost Software License, Version 1.0. (See | |||
// accompanying file LICENSE_1_0.txt or copy at | |||
@@ -1,5 +1,5 @@ | |||
// | |||
// Copyright (c) 2009-2010 Artyom Beilis (Tonkikh) | |||
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) | |||
// | |||
// Distributed under the Boost Software License, Version 1.0. (See | |||
// accompanying file LICENSE_1_0.txt or copy at | |||
@@ -1,5 +1,5 @@ | |||
// | |||
// Copyright (c) 2009-2010 Artyom Beilis (Tonkikh) | |||
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) | |||
// | |||
// Distributed under the Boost Software License, Version 1.0. (See | |||
// accompanying file LICENSE_1_0.txt or copy at | |||
@@ -1,5 +1,5 @@ | |||
// | |||
// Copyright (c) 2009-2010 Artyom Beilis (Tonkikh) | |||
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) | |||
// | |||
// Distributed under the Boost Software License, Version 1.0. (See | |||
// accompanying file LICENSE_1_0.txt or copy at | |||
@@ -1,5 +1,5 @@ | |||
// | |||
// Copyright (c) 2009-2010 Artyom Beilis (Tonkikh) | |||
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) | |||
// | |||
// Distributed under the Boost Software License, Version 1.0. (See | |||
// accompanying file LICENSE_1_0.txt or copy at | |||
@@ -12,6 +12,7 @@ | |||
#include "all_generator.h" | |||
#include "win_backend.h" | |||
#include <booster/locale/util.h> | |||
#include "../util/gregorian.h" | |||
#include "../util/locale_data.h" | |||
#include "api.h" | |||
@@ -92,6 +93,12 @@ namespace impl_win { | |||
return create_formatting(base,lc_,type); | |||
case parsing_facet: | |||
return create_parsing(base,lc_,type); | |||
case calendar_facet: | |||
{ | |||
util::locale_data inf; | |||
inf.parse(real_id_); | |||
return util::install_gregorian_calendar(base,inf.country); | |||
} | |||
case message_facet: | |||
{ | |||
gnu_gettext::messages_info minf; | |||
@@ -1,5 +1,5 @@ | |||
// | |||
// Copyright (c) 2009-2010 Artyom Beilis (Tonkikh) | |||
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) | |||
// | |||
// Distributed under the Boost Software License, Version 1.0. (See | |||
// accompanying file LICENSE_1_0.txt or copy at | |||
@@ -1,5 +1,5 @@ | |||
// | |||
// Copyright (c) 2009-2010 Artyom Beilis (Tonkikh) | |||
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) | |||
// | |||
// Distributed under the Boost Software License, Version 1.0. (See | |||
// accompanying file LICENSE_1_0.txt or copy at | |||
@@ -1,5 +1,5 @@ | |||
// | |||
// Copyright (c) 2009-2010 Artyom Beilis (Tonkikh) | |||
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) | |||
// | |||
// Distributed under the Boost Software License, Version 1.0. (See | |||
// accompanying file LICENSE_1_0.txt or copy at | |||
@@ -1,5 +1,5 @@ | |||
// | |||
// Copyright (c) 2009-2010 Artyom Beilis (Tonkikh) | |||
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) | |||
// | |||
// Distributed under the Boost Software License, Version 1.0. (See | |||
// accompanying file LICENSE_1_0.txt or copy at | |||
@@ -1,5 +1,5 @@ | |||
// | |||
// Copyright (c) 2009-2010 Artyom Beilis (Tonkikh) | |||
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) | |||
// | |||
// Distributed under the Boost Software License, Version 1.0. (See | |||
// accompanying file LICENSE_1_0.txt or copy at | |||
@@ -1,5 +1,5 @@ | |||
// | |||
// Copyright (c) 2009-2010 Artyom Beilis (Tonkikh) | |||
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) | |||
// | |||
// Distributed under the Boost Software License, Version 1.0. (See | |||
// accompanying file LICENSE_1_0.txt or copy at | |||
@@ -1,5 +1,5 @@ | |||
// | |||
// Copyright (c) 2009-2010 Artyom Beilis (Tonkikh) | |||
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) | |||
// | |||
// Distributed under the Boost Software License, Version 1.0. (See | |||
// accompanying file LICENSE_1_0.txt or copy at | |||
@@ -9,6 +9,7 @@ | |||
#include <booster/locale/date_time.h> | |||
#include <booster/locale/generator.h> | |||
#include <booster/locale/formatting.h> | |||
#include <booster/locale/localization_backend.h> | |||
#include <iomanip> | |||
#include "test_locale.h" | |||
@@ -19,148 +20,200 @@ | |||
#define RESET() do { time_point = base_time_point; ss.str(""); } while(0) | |||
#define TESTR(X) do { TEST(X); RESET(); } while(0) | |||
//#define TESTEQSR(t,X) do { ss << (t); TESTR(ss.str() == X); } while(0) | |||
#define TESTEQSR(t,X) do { ss << (t); if(ss.str()!=X) { std::cerr <<"[" << ss.str() <<"]" << std::endl; } TESTR(ss.str() == X); } while(0) | |||
#define TESTEQSR(t,X) do { ss << (t); if(ss.str()!=X) { std::cerr <<"[" << ss.str() <<"]!=[" <<X<<"]" << std::endl; } TESTR(ss.str() == X); } while(0) | |||
int main() | |||
{ | |||
try { | |||
using namespace booster::locale; | |||
using namespace booster::locale::period; | |||
booster::locale::generator g; | |||
std::locale loc=g("en_US.UTF-8"); | |||
std::locale::global(loc); | |||
std::string tz("GMT"); | |||
time_zone::global(tz); | |||
calendar cal(loc,tz); | |||
TEST(calendar() == cal); | |||
TEST(calendar(loc) == cal); | |||
TEST(calendar(tz) == cal); | |||
TEST(calendar(loc,"GMT+01:00") != cal); | |||
TEST(calendar(g("ru_RU.UTF-8")) != cal); | |||
TEST(cal.minimum(month)==0); | |||
TEST(cal.maximum(month)==11); | |||
TEST(cal.minimum(day)==1); | |||
TEST(cal.greatest_minimum(day)==1); | |||
TEST(cal.least_maximum(day)==28); | |||
TEST(cal.maximum(day)==31); | |||
TEST(calendar(g("ar_EG.UTF-8")).first_day_of_week() == 7); | |||
TEST(calendar(g("he_IL.UTF-8")).first_day_of_week() == 1); | |||
TEST(calendar(g("ru_RU.UTF-8")).first_day_of_week() == 2); | |||
std::ostringstream ss; | |||
ss.imbue(loc); | |||
ss<<booster::locale::as::time_zone(tz); | |||
date_time time_point; | |||
time_point=year * 1970 + february + 5 * day; | |||
ss << as::date << time_point; | |||
TEST(ss.str() == "Feb 5, 1970"); | |||
time_point = 3 * hour_12 + 1 * am_pm + 33 * minute + 13 * second; | |||
ss.str(""); | |||
ss << as::datetime << time_point; | |||
std::cerr << ss.str() << std::endl; | |||
TEST( ss.str() == "Feb 5, 1970 3:33:13 PM"); ss.str(""); | |||
time_t a_date = 3600*24*(31+4); // Feb 5th | |||
time_t a_time = 3600*15+60*33; // 15:33:05 | |||
time_t a_timesec = 13; | |||
time_t a_datetime = a_date + a_time + a_timesec; | |||
date_time base_time_point=date_time(a_datetime); | |||
RESET(); | |||
time_point += hour; | |||
TESTEQSR(time_point,"Feb 5, 1970 4:33:13 PM"); | |||
TEST(time_point.minimum(day)==1); | |||
TEST(time_point.maximum(day)==28); | |||
time_point += year * 2 + 1 *month; | |||
TESTEQSR(time_point,"Mar 5, 1972 3:33:13 PM"); | |||
time_point -= minute; | |||
TESTEQSR( time_point, "Feb 5, 1970 3:32:13 PM"); | |||
time_point <<= minute * 30; | |||
TESTEQSR( time_point, "Feb 5, 1970 3:03:13 PM"); | |||
time_point >>= minute * 40; | |||
TESTEQSR( time_point, "Feb 5, 1970 3:53:13 PM"); | |||
TEST((time_point + month) / month == 2); | |||
TEST(time_point / month == 1); | |||
TEST((time_point - month) / month == 0); | |||
TEST(time_point / month == 1); | |||
TEST((time_point << month) / month == 2); | |||
TEST(time_point / month == 1); | |||
TEST((time_point >> month) / month == 0); | |||
TEST(time_point / month == 1); | |||
TEST( (time_point + 2 * hour - time_point) / minute == 120); | |||
TEST( (time_point + month - time_point) / day == 28); | |||
TEST( (time_point + 2* month - (time_point+month)) / day == 31); | |||
TESTEQSR( time_point + hour, "Feb 5, 1970 4:33:13 PM"); | |||
TESTEQSR( time_point - 2 * hour, "Feb 5, 1970 1:33:13 PM"); | |||
TESTEQSR( time_point >> minute, "Feb 5, 1970 3:32:13 PM"); | |||
TESTEQSR( time_point << second, "Feb 5, 1970 3:33:14 PM"); | |||
TEST(time_point == time_point); | |||
TEST(!(time_point != time_point)); | |||
TEST(time_point.get(hour) == 15); | |||
TEST(time_point/hour == 15); | |||
TEST(time_point+year != time_point); | |||
TEST(time_point - minute <= time_point); | |||
TEST(time_point <= time_point); | |||
TEST(time_point + minute >= time_point); | |||
TEST(time_point >= time_point); | |||
TEST(time_point < time_point + second); | |||
TEST(!(time_point < time_point - second)); | |||
TEST(time_point > time_point - second); | |||
TEST(!(time_point > time_point + second)); | |||
TEST(time_point.get(day) == 5); | |||
TEST(time_point.get(year) == 1970); | |||
TEST(time_point.get(era) == 1); | |||
TEST(time_point.get(year) == 1970); | |||
TEST(time_point.get(extended_year) == 1970); | |||
time_point=extended_year * -3; | |||
TEST(time_point.get(era) == 0); | |||
TEST(time_point.get(year) == 4); | |||
RESET(); | |||
TEST(time_point.get(month) == 1); | |||
TEST(time_point.get(day) == 5); | |||
TEST(time_point.get(day_of_year) == 36); | |||
TEST(time_point.get(day_of_week) == 5); | |||
// TODO | |||
// TEST(time_point.get(day_of_week_in_month)==?); | |||
// | |||
time_point=date_time(a_datetime,calendar(g("ru_RU.UTF-8"))); | |||
TEST(time_point.get(day_of_week_local) == 4); | |||
RESET(); | |||
TEST(time_point.get(hour) == 15); | |||
TEST(date_time(a_datetime,calendar("GMT+01:00")).get(hour) ==16); | |||
TEST(time_point.get(hour_12) == 3); | |||
TEST(time_point.get(am_pm) == 1); | |||
TEST(time_point.get(minute) == 33); | |||
TEST(time_point.get(second) == 13); | |||
TEST(date_time(year* 1984 + february + day).get(week_of_year)==5); | |||
TEST(time_point.get(week_of_month) == 1); | |||
std::string def[] = { | |||
#ifdef BOOSTER_LOCALE_WITH_ICU | |||
"icu" , | |||
#endif | |||
#ifndef BOOSTER_LOCALE_NO_STD_BACKEND | |||
"std" , | |||
#endif | |||
#ifndef BOOSTER_LOCALE_NO_POSIX_BACKEND | |||
"posix", | |||
#endif | |||
#ifndef BOOSTER_LOCALE_NO_WINAPI_BACKEND | |||
"winapi", | |||
#endif | |||
}; | |||
for(int type = 0 ; type < int(sizeof(def)/sizeof(def[0])) ; type ++ ) { | |||
booster::locale::localization_backend_manager tmp_backend = booster::locale::localization_backend_manager::global(); | |||
tmp_backend.select(def[type]); | |||
booster::locale::localization_backend_manager::global(tmp_backend); | |||
std::cout << "Testing for backend: " << def[type] << std::endl; | |||
std::string backend_name = def[type]; | |||
{ | |||
booster::locale::generator g; | |||
std::locale loc=g("en_US.UTF-8"); | |||
std::locale::global(loc); | |||
std::string tz("GMT"); | |||
time_zone::global(tz); | |||
calendar cal(loc,tz); | |||
TEST(calendar() == cal); | |||
TEST(calendar(loc) == cal); | |||
TEST(calendar(tz) == cal); | |||
TEST(calendar(loc,"GMT+01:00") != cal); | |||
TEST(calendar(g("ru_RU.UTF-8")) != cal); | |||
TEST(cal.minimum(month)==0); | |||
TEST(cal.maximum(month)==11); | |||
TEST(cal.minimum(day)==1); | |||
TEST(cal.greatest_minimum(day)==1); | |||
TEST(cal.least_maximum(day)==28); | |||
TEST(cal.maximum(day)==31); | |||
TEST(calendar(g("ar_EG.UTF-8")).first_day_of_week() == 7); | |||
TEST(calendar(g("he_IL.UTF-8")).first_day_of_week() == 1); | |||
TEST(calendar(g("ru_RU.UTF-8")).first_day_of_week() == 2); | |||
std::ostringstream ss; | |||
ss.imbue(loc); | |||
ss<<booster::locale::as::time_zone(tz); | |||
date_time time_point; | |||
time_point=year * 1970 + february + 5 * day; | |||
ss << as::ftime("%Y-%m-%d")<< time_point; | |||
TEST(ss.str() == "1970-02-05"); | |||
time_point = 3 * hour_12 + 1 * am_pm + 33 * minute + 13 * second; | |||
ss.str(""); | |||
ss << as::ftime("%Y-%m-%d %H:%M:%S") << time_point; | |||
TEST( ss.str() == "1970-02-05 15:33:13"); ss.str(""); | |||
time_t a_date = 3600*24*(31+4); // Feb 5th | |||
time_t a_time = 3600*15+60*33; // 15:33:05 | |||
time_t a_timesec = 13; | |||
time_t a_datetime = a_date + a_time + a_timesec; | |||
date_time base_time_point=date_time(a_datetime); | |||
RESET(); | |||
time_point += hour; | |||
TESTEQSR(time_point,"1970-02-05 16:33:13"); | |||
TEST(time_point.minimum(day)==1); | |||
TEST(time_point.maximum(day)==28); | |||
time_point += year * 2 + 1 *month; | |||
TESTEQSR(time_point,"1972-03-05 15:33:13"); | |||
time_point -= minute; | |||
TESTEQSR( time_point, "1970-02-05 15:32:13"); | |||
time_point <<= minute * 30; | |||
TESTEQSR( time_point, "1970-02-05 15:03:13"); | |||
time_point >>= minute * 40; | |||
TESTEQSR( time_point, "1970-02-05 15:53:13"); | |||
TEST((time_point + month) / month == 2); | |||
TEST(time_point / month == 1); | |||
TEST((time_point - month) / month == 0); | |||
TEST(time_point / month == 1); | |||
TEST((time_point << month) / month == 2); | |||
TEST(time_point / month == 1); | |||
TEST((time_point >> month) / month == 0); | |||
TEST(time_point / month == 1); | |||
TEST( (time_point + 2 * hour - time_point) / minute == 120); | |||
TEST( (time_point + month - time_point) / day == 28); | |||
TEST( (time_point + 2* month - (time_point+month)) / day == 31); | |||
TESTEQSR( time_point + hour, "1970-02-05 16:33:13"); | |||
TESTEQSR( time_point - 2 * hour, "1970-02-05 13:33:13"); | |||
TESTEQSR( time_point >> minute, "1970-02-05 15:32:13"); | |||
TESTEQSR( time_point << second, "1970-02-05 15:33:14"); | |||
TEST(time_point == time_point); | |||
TEST(!(time_point != time_point)); | |||
TEST(time_point.get(hour) == 15); | |||
TEST(time_point/hour == 15); | |||
TEST(time_point+year != time_point); | |||
TEST(time_point - minute <= time_point); | |||
TEST(time_point <= time_point); | |||
TEST(time_point + minute >= time_point); | |||
TEST(time_point >= time_point); | |||
TEST(time_point < time_point + second); | |||
TEST(!(time_point < time_point - second)); | |||
TEST(time_point > time_point - second); | |||
TEST(!(time_point > time_point + second)); | |||
TEST(time_point.get(day) == 5); | |||
TEST(time_point.get(year) == 1970); | |||
TEST(time_point.get(era) == 1); | |||
TEST(time_point.get(year) == 1970); | |||
TEST(time_point.get(extended_year) == 1970); | |||
if(backend_name == "icu") { | |||
time_point=extended_year * -3; | |||
TEST(time_point.get(era) == 0); | |||
TEST(time_point.get(year) == 4); | |||
} | |||
RESET(); | |||
TEST(time_point.get(month) == 1); | |||
TEST(time_point.get(day) == 5); | |||
TEST(time_point.get(day_of_year) == 36); | |||
TEST(time_point.get(day_of_week) == 5); | |||
TEST(time_point.get(day_of_week_in_month)==1); | |||
time_point=date_time(a_datetime,calendar(g("ru_RU.UTF-8"))); | |||
TEST(time_point.get(day_of_week_local) == 4); | |||
time_point = year*2026 + january + day * 1; | |||
TEST(time_point.get(day_of_week) == 5); | |||
TEST(time_point.get(week_of_year) == 1); | |||
TEST(time_point.get(week_of_month) == 1); | |||
time_point = day_of_week * 1; | |||
TEST(time_point.get(day) == 4); | |||
TEST(time_point.get(week_of_year) == 1); | |||
TEST(time_point.get(week_of_month) == 1); | |||
time_point += day * 1; | |||
TEST(time_point.get(week_of_year) == 2); | |||
TEST(time_point.get(week_of_month) == 2); | |||
time_point = february + day * 2; | |||
TEST(time_point.get(week_of_year) == 6); | |||
TEST(time_point.get(week_of_month) == 1); | |||
time_point = year*2010 + january + day * 3; | |||
TEST(time_point.get(week_of_year) == 53); | |||
time_point = year*2010 + january + day * 4; | |||
TEST(time_point.get(week_of_year) == 1); | |||
time_point = year*2010 + january + day * 10; | |||
TEST(time_point.get(week_of_year) == 1); | |||
time_point = year*2010 + january + day * 11; | |||
TEST(time_point.get(week_of_year) == 2); | |||
RESET(); | |||
TEST(time_point.get(hour) == 15); | |||
TEST(date_time(a_datetime,calendar("GMT+01:00")).get(hour) ==16); | |||
TEST(time_point.get(hour_12) == 3); | |||
TEST(time_point.get(am_pm) == 1); | |||
TEST(time_point.get(minute) == 33); | |||
TEST(time_point.get(second) == 13); | |||
TEST(date_time(year* 1984 + february + day).get(week_of_year)==5); | |||
TEST(time_point.get(week_of_month) == 1); | |||
RESET(); | |||
TEST((time_point + year *1 - hour * 1 - time_point) / year == 0); | |||
TEST((time_point + year *1 - time_point) / year == 1); | |||
TEST((time_point + year *1 + hour * 1 - time_point) / year == 1); | |||
TEST((time_point - year *1 + hour * 1 - time_point) / year == 0); | |||
TEST((time_point - year *1 - time_point) / year == -1); | |||
TEST((time_point - year *1 - hour * 1 - time_point) / year == -1); | |||
} // test | |||
} // for loop | |||
} | |||
catch(std::exception const &e) { | |||
@@ -1,5 +1,5 @@ | |||
// | |||
// Copyright (c) 2009-2010 Artyom Beilis (Tonkikh) | |||
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) | |||
// | |||
// Distributed under the Boost Software License, Version 1.0. (See | |||
// accompanying file LICENSE_1_0.txt or copy at | |||
@@ -1,5 +1,5 @@ | |||
// | |||
// Copyright (c) 2009-2010 Artyom Beilis (Tonkikh) | |||
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) | |||
// | |||
// Distributed under the Boost Software License, Version 1.0. (See | |||
// accompanying file LICENSE_1_0.txt or copy at | |||
@@ -1,5 +1,5 @@ | |||
// | |||
// Copyright (c) 2009-2010 Artyom Beilis (Tonkikh) | |||
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) | |||
// | |||
// Distributed under the Boost Software License, Version 1.0. (See | |||
// accompanying file LICENSE_1_0.txt or copy at | |||
@@ -1,5 +1,5 @@ | |||
// | |||
// Copyright (c) 2009-2010 Artyom Beilis (Tonkikh) | |||
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) | |||
// | |||
// Distributed under the Boost Software License, Version 1.0. (See | |||
// accompanying file LICENSE_1_0.txt or copy at | |||