24#include <boost/utility/string_view.hpp>
25#include <boost/bimap/bimap.hpp>
26#include <boost/bimap/set_of.hpp>
39 bool operator()(
const boost::string_view lhs,
40 const boost::string_view rhs)
const {
43 for (
int i = 0; i < 3; ++i) {
44 lhsUpper[i] = std::toupper(lhs[i]);
45 rhsUpper[i] = std::toupper(rhs[i]);
47 return boost::string_view(lhsUpper, 3) <
48 boost::string_view(rhsUpper, 3);
52 using MonthBimap_t = boost::bimaps::bimap<
53 boost::bimaps::set_of<boost::string_view, is_iless>,
Month>;
56 const MonthBimap_t MONTHS = []() {
76 std::set<Date> ecbKnownDateSet = {
78 Date(38371), Date(38391), Date(38420), Date(38455), Date(38483), Date(38511),
79 Date(38546), Date(38574), Date(38602), Date(38637), Date(38665), Date(38692),
82 Date(38735), Date(38756), Date(38784), Date(38819), Date(38847), Date(38883),
83 Date(38910), Date(38938), Date(38966), Date(39001), Date(39029), Date(39064),
86 Date(39099), Date(39127), Date(39155), Date(39190), Date(39217), Date(39246),
87 Date(39274), Date(39302), Date(39337), Date(39365), Date(39400), Date(39428),
90 Date(39463), Date(39491), Date(39519), Date(39554), Date(39582), Date(39610),
91 Date(39638), Date(39673), Date(39701), Date(39729), Date(39764), Date(39792),
94 Date(39834), Date(39855), Date(39883), Date(39911), Date(39946), Date(39974),
95 Date(40002), Date(40037), Date(40065), Date(40100), Date(40128), Date(40155),
98 Date(40198), Date(40219), Date(40247), Date(40282), Date(40310), Date(40345),
99 Date(40373), Date(40401), Date(40429), Date(40464), Date(40492), Date(40520),
102 Date(40562), Date(40583), Date(40611), Date(40646), Date(40674), Date(40709),
103 Date(40737), Date(40765), Date(40800), Date(40828), Date(40856), Date(40891),
106 Date(40926), Date(40954), Date(40982), Date(41010), Date(41038), Date(41073),
107 Date(41101), Date(41129), Date(41164), Date(41192), Date(41227), Date(41255),
110 Date(41290), Date(41318), Date(41346), Date(41374), Date(41402), Date(41437),
111 Date(41465), Date(41493), Date(41528), Date(41556), Date(41591), Date(41619),
114 Date(41654), Date(41682), Date(41710), Date(41738), Date(41773), Date(41801),
115 Date(41829), Date(41864), Date(41892), Date(41920), Date(41955), Date(41983),
118 Date(42032), Date(42074), Date(42116), Date(42165), Date(42207), Date(42256),
119 Date(42305), Date(42347),
122 Date(42396), Date(42445), Date(42487), Date(42529), Date(42578), Date(42627),
123 Date(42669), Date(42718),
126 Date(42760), Date(42809), Date(42858), Date(42900), Date(42942), Date(42991),
127 Date(43040), Date(43089),
130 Date(43131), Date(43167), Date(43216), Date(43265), Date(43307), Date(43356),
131 Date(43398), Date(43447),
134 Date(43495), Date(43537), Date(43572), Date(43628), Date(43677), Date(43726),
135 Date(43768), Date(43817),
138 Date(43859), Date(43908), Date(43957), Date(43992), Date(44034), Date(44090),
139 Date(44139), Date(44181),
142 Date(44223), Date(44272), Date(44314), Date(44363), Date(44405), Date(44454),
143 Date(44503), Date(44552),
146 Date(44601), Date(44636), Date(44671), Date(44727), Date(44769), Date(44818),
147 Date(44867), Date(44916),
150 Date(44965), Date(45007), Date(45056), Date(45098), Date(45140), Date(45189),
151 Date(45231), Date(45280),
154 Date(45322), Date(45364), Date(45399), Date(45455), Date(45497), Date(45553),
155 Date(45588), Date(45644)
161 return ecbKnownDateSet;
165 ecbKnownDateSet.insert(
d);
169 ecbKnownDateSet.erase(
d);
173 int ToInteger(
const char c) {
174 const int i =
static_cast<int>(c) -
static_cast<int>(
'0');
175 QL_ASSERT((i >= 0) && (i <= 9),
"Character does not represent a digit. char: " << c);
181 const Date& refDate) {
184 ecbCode <<
" is not a valid ECB code");
187 const boost::string_view monthCode(ecbCode.data(), 3);
188 const Month m = MONTHS.left.at(monthCode);
191 Year y = ToInteger(ecbCode[3])*10 + ToInteger(ecbCode[4]);
192 Date referenceDate = (refDate !=
Date() ?
195 Year referenceYear = (referenceDate.
year() % 100);
196 y += referenceDate.
year() - referenceYear;
206 ecbDate <<
" is not a valid ECB date");
209 const boost::string_view month = MONTHS.right.at(ecbDate.
month());
212 const unsigned int y = ecbDate.
year() % 100;
216 std::snprintf(ECBcode, 6,
"%3s%02u", month.data(),
y);
218 #if defined(QL_EXTRA_SAFETY_CHECKS)
220 "the result " << ECBcode <<
221 " is an invalid ECB code");
234 "ECB dates after " << *
knownDates().rbegin() <<
" are unknown");
246 "ECB dates after " << *
knownDates().rbegin() <<
" are unknown");
247 return std::vector<Date>(i,
knownDates().end());
253 if (ecbCode.length() != 5)
258 const boost::string_view month(ecbCode.data(), 3);
259 if (MONTHS.left.find(month) == MONTHS.left.end())
264 return (std::isdigit(
static_cast<unsigned char>(ecbCode[3])) != 0)
265 && (std::isdigit(
static_cast<unsigned char>(ecbCode[4])) != 0);
270 ecbCode <<
" is not a valid ECB code");
272 const boost::string_view month(ecbCode.data(), 3);
273 const Month monthEnum = MONTHS.left.at(month);
276 nextCodeStr.reserve(5);
279 const auto nextMonthEnum =
static_cast<Month>(monthEnum + 1);
280 const boost::string_view nextMonth = MONTHS.right.at(nextMonthEnum);
281 nextCodeStr.append(nextMonth.data(), 3);
284 nextCodeStr += {ecbCode[3], ecbCode[4]};
287 nextCodeStr.append(
"JAN");
290 nextCodeStr += { ecbCode[3], ecbCode[4] };
294 const auto incrementAndCheckForOverlow = [](
char& dig) ->
bool {
303 if (incrementAndCheckForOverlow(nextCodeStr[4]))
304 incrementAndCheckForOverlow(nextCodeStr[3]);
308 #if defined(QL_EXTRA_SAFETY_CHECKS)
310 "the result " << nextCodeStr <<
311 " is an invalid ECB code");
static Date minDate()
earliest allowed date
DateProxy & evaluationDate()
the date at which pricing is to be performed.
static Settings & instance()
access to the unique instance
Classes used to parse data for input.
European Central Bank reserve maintenance date functions.
#define QL_ENSURE(condition, message)
throw an error if the given post-condition is not verified
#define QL_REQUIRE(condition, message)
throw an error if the given pre-condition is not verified
#define QL_ASSERT(condition, message)
throw an error if the given condition is not verified
Real months(const Period &p)
global repository for run-time library settings
static void removeDate(const Date &d)
static std::vector< Date > nextDates(const Date &d=Date())
next maintenance period start dates following the given date
static void addDate(const Date &d)
static std::string nextCode(const Date &d=Date())
next ECB code following the given date
static const std::set< Date > & knownDates()
static bool isECBcode(const std::string &in)
returns whether or not the given string is an ECB code
static Date date(Month m, Year y)
maintenance period start date in the given month/year
static std::string code(const Date &ecbDate)
static Date nextDate(const Date &d=Date())
next maintenance period start date following the given date
static bool isECBdate(const Date &d)