Coverage Report

Created: 2025-08-11 06:28

/src/quantlib/ql/time/calendar.hpp
Line
Count
Source (jump to first uncovered line)
1
/* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
3
/*
4
 Copyright (C) 2000, 2001, 2002, 2003 RiskMap srl
5
 Copyright (C) 2003, 2004, 2005, 2006, 2007 StatPro Italia srl
6
 Copyright (C) 2006 Piter Dias
7
 Copyright (C) 2020 Leonardo Arcari
8
 Copyright (C) 2020 Kline s.r.l.
9
10
 This file is part of QuantLib, a free-software/open-source library
11
 for financial quantitative analysts and developers - http://quantlib.org/
12
13
 QuantLib is free software: you can redistribute it and/or modify it
14
 under the terms of the QuantLib license.  You should have received a
15
 copy of the license along with this program; if not, please email
16
 <quantlib-dev@lists.sf.net>. The license is also available online at
17
 <http://quantlib.org/license.shtml>.
18
19
 This program is distributed in the hope that it will be useful, but WITHOUT
20
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
21
 FOR A PARTICULAR PURPOSE.  See the license for more details.
22
*/
23
24
/*! \file calendar.hpp
25
    \brief %calendar class
26
*/
27
28
#ifndef quantlib_calendar_hpp
29
#define quantlib_calendar_hpp
30
31
#include <ql/errors.hpp>
32
#include <ql/time/date.hpp>
33
#include <ql/time/businessdayconvention.hpp>
34
#include <ql/shared_ptr.hpp>
35
#include <set>
36
#include <vector>
37
#include <string>
38
39
namespace QuantLib {
40
41
    class Period;
42
43
    //! %calendar class
44
    /*! This class provides methods for determining whether a date is a
45
        business day or a holiday for a given market, and for
46
        incrementing/decrementing a date of a given number of business days.
47
48
        The Bridge pattern is used to provide the base behavior of the
49
        calendar, namely, to determine whether a date is a business day.
50
51
        A calendar should be defined for specific exchange holiday schedule
52
        or for general country holiday schedule. Legacy city holiday schedule
53
        calendars will be moved to the exchange/country convention.
54
55
        \ingroup datetime
56
57
        \test the methods for adding and removing holidays are tested
58
              by inspecting the calendar before and after their
59
              invocation.
60
    */
61
    class Calendar {
62
      protected:
63
        //! abstract base class for calendar implementations
64
        class Impl {
65
          public:
66
161k
            virtual ~Impl() = default;
67
            virtual std::string name() const = 0;
68
            virtual bool isBusinessDay(const Date&) const = 0;
69
            virtual bool isWeekend(Weekday) const = 0;
70
            std::set<Date> addedHolidays, removedHolidays;
71
        };
72
        ext::shared_ptr<Impl> impl_;
73
      public:
74
        /*! The default constructor returns a calendar with a null
75
            implementation, which is therefore unusable except as a
76
            placeholder.
77
        */
78
402k
        Calendar() = default;
79
        //! \name Calendar interface
80
        //@{
81
        //!  Returns whether or not the calendar is initialized
82
        bool empty() const;
83
        //! Returns the name of the calendar.
84
        /*! \warning This method is used for output and comparison between
85
                calendars. It is <b>not</b> meant to be used for writing
86
                switch-on-type code.
87
        */
88
        std::string name() const;
89
        /*! Returns <tt>true</tt> iff the date is a business day for the
90
            given market.
91
        */
92
93
        /*! Returns the set of added holidays for the given calendar */
94
        const std::set<Date>& addedHolidays() const;
95
        
96
        /*! Returns the set of removed holidays for the given calendar */
97
        const std::set<Date>& removedHolidays() const;
98
99
        /*! Clear the set of added and removed holidays */
100
        void resetAddedAndRemovedHolidays();
101
102
        bool isBusinessDay(const Date& d) const;
103
        /*! Returns <tt>true</tt> iff the date is a holiday for the given
104
            market.
105
        */
106
        bool isHoliday(const Date& d) const;
107
        /*! Returns <tt>true</tt> iff the weekday is part of the
108
            weekend for the given market.
109
        */
110
        bool isWeekend(Weekday w) const;
111
        /*! Returns <tt>true</tt> iff in the given market, the date is on
112
            or before the first business day for that month.
113
        */
114
        bool isStartOfMonth(const Date& d) const;
115
        //! first business day of the month to which the given date belongs
116
        Date startOfMonth(const Date& d) const;
117
        /*! Returns <tt>true</tt> iff in the given market, the date is on
118
            or after the last business day for that month.
119
        */
120
        bool isEndOfMonth(const Date& d) const;
121
        //! last business day of the month to which the given date belongs
122
        Date endOfMonth(const Date& d) const;
123
124
        /*! Adds a date to the set of holidays for the given calendar. */
125
        void addHoliday(const Date&);
126
        /*! Removes a date from the set of holidays for the given calendar. */
127
        void removeHoliday(const Date&);
128
129
        /*! Returns the holidays between two dates. */
130
        std::vector<Date> holidayList(const Date& from,
131
                                      const Date& to,
132
                                      bool includeWeekEnds = false) const;
133
        /*! Returns the business days between two dates. */
134
        std::vector<Date> businessDayList(const Date& from,
135
                                          const Date& to) const;
136
137
        /*! Adjusts a non-business day to the appropriate near business day
138
            with respect to the given convention.
139
        */
140
        Date adjust(const Date&,
141
                    BusinessDayConvention convention = Following) const;
142
        /*! Advances the given date of the given number of business days and
143
            returns the result.
144
            \note The input date is not modified.
145
        */
146
        Date advance(const Date&,
147
                     Integer n,
148
                     TimeUnit unit,
149
                     BusinessDayConvention convention = Following,
150
                     bool endOfMonth = false) const;
151
        /*! Advances the given date as specified by the given period and
152
            returns the result.
153
            \note The input date is not modified.
154
        */
155
        Date advance(const Date& date,
156
                     const Period& period,
157
                     BusinessDayConvention convention = Following,
158
                     bool endOfMonth = false) const;
159
        /*! Calculates the number of business days between two given
160
            dates and returns the result.
161
        */
162
        Date::serial_type businessDaysBetween(const Date& from,
163
                                              const Date& to,
164
                                              bool includeFirst = true,
165
                                              bool includeLast = false) const;
166
        //@}
167
168
      protected:
169
        //! partial calendar implementation
170
        /*! This class provides the means of determining the Easter
171
            Monday for a given year, as well as specifying Saturdays
172
            and Sundays as weekend days.
173
        */
174
        class WesternImpl : public Impl {
175
          public:
176
            bool isWeekend(Weekday) const override;
177
            //! expressed relative to first day of year
178
            static Day easterMonday(Year);
179
        };
180
        //! partial calendar implementation
181
        /*! This class provides the means of determining the Orthodox
182
            Easter Monday for a given year, as well as specifying
183
            Saturdays and Sundays as weekend days.
184
        */
185
        class OrthodoxImpl : public Impl {
186
          public:
187
            bool isWeekend(Weekday) const override;
188
            //! expressed relative to first day of year
189
            static Day easterMonday(Year);
190
        };
191
    };
192
193
    /*! Returns <tt>true</tt> iff the two calendars belong to the same
194
        derived class.
195
        \relates Calendar
196
    */
197
    bool operator==(const Calendar&, const Calendar&);
198
199
    /*! \relates Calendar */
200
    bool operator!=(const Calendar&, const Calendar&);
201
202
    /*! \relates Calendar */
203
    std::ostream& operator<<(std::ostream&, const Calendar&);
204
205
206
    // inline definitions
207
208
0
    inline bool Calendar::empty() const {
209
0
        return !impl_;
210
0
    }
211
212
0
    inline std::string Calendar::name() const {
213
0
        QL_REQUIRE(impl_, "no calendar implementation provided");
214
0
        return impl_->name();
215
0
    }
Unexecuted instantiation: QuantLib::Calendar::name() const
Unexecuted instantiation: QuantLib::Calendar::name() const
216
217
0
    inline const std::set<Date>& Calendar::addedHolidays() const {
218
0
        QL_REQUIRE(impl_, "no calendar implementation provided");
219
0
220
0
        return impl_->addedHolidays;
221
0
    }
222
223
0
    inline const std::set<Date>& Calendar::removedHolidays() const {
224
0
        QL_REQUIRE(impl_, "no calendar implementation provided");
225
0
226
0
        return impl_->removedHolidays;
227
0
    }
228
229
28.8M
    inline bool Calendar::isBusinessDay(const Date& d) const {
230
28.8M
        QL_REQUIRE(impl_, "no calendar implementation provided");
231
232
#ifdef QL_HIGH_RESOLUTION_DATE
233
        const Date _d(d.dayOfMonth(), d.month(), d.year());
234
#else
235
28.8M
        const Date& _d = d;
236
28.8M
#endif
237
238
28.8M
        if (!impl_->addedHolidays.empty() &&
239
28.8M
            impl_->addedHolidays.find(_d) != impl_->addedHolidays.end())
240
0
            return false;
241
242
28.8M
        if (!impl_->removedHolidays.empty() &&
243
28.8M
            impl_->removedHolidays.find(_d) != impl_->removedHolidays.end())
244
0
            return true;
245
246
28.8M
        return impl_->isBusinessDay(_d);
247
28.8M
    }
Unexecuted instantiation: QuantLib::Calendar::isBusinessDay(QuantLib::Date const&) const
QuantLib::Calendar::isBusinessDay(QuantLib::Date const&) const
Line
Count
Source
229
28.8M
    inline bool Calendar::isBusinessDay(const Date& d) const {
230
28.8M
        QL_REQUIRE(impl_, "no calendar implementation provided");
231
232
#ifdef QL_HIGH_RESOLUTION_DATE
233
        const Date _d(d.dayOfMonth(), d.month(), d.year());
234
#else
235
28.8M
        const Date& _d = d;
236
28.8M
#endif
237
238
28.8M
        if (!impl_->addedHolidays.empty() &&
239
28.8M
            impl_->addedHolidays.find(_d) != impl_->addedHolidays.end())
240
0
            return false;
241
242
28.8M
        if (!impl_->removedHolidays.empty() &&
243
28.8M
            impl_->removedHolidays.find(_d) != impl_->removedHolidays.end())
244
0
            return true;
245
246
28.8M
        return impl_->isBusinessDay(_d);
247
28.8M
    }
248
249
0
    inline bool Calendar::isStartOfMonth(const Date& d) const {
250
0
        return d <= startOfMonth(d);
251
0
    }
252
253
0
    inline Date Calendar::startOfMonth(const Date& d) const {
254
0
        return adjust(Date::startOfMonth(d), Following);
255
0
    }
256
257
0
    inline bool Calendar::isEndOfMonth(const Date& d) const {
258
0
        return d >= endOfMonth(d);
259
0
    }
260
261
0
    inline Date Calendar::endOfMonth(const Date& d) const {
262
0
        return adjust(Date::endOfMonth(d), Preceding);
263
0
    }
264
265
28.8M
    inline bool Calendar::isHoliday(const Date& d) const {
266
28.8M
        return !isBusinessDay(d);
267
28.8M
    }
268
269
0
    inline bool Calendar::isWeekend(Weekday w) const {
270
0
        QL_REQUIRE(impl_, "no calendar implementation provided");
271
0
        return impl_->isWeekend(w);
272
0
    }
Unexecuted instantiation: QuantLib::Calendar::isWeekend(QuantLib::Weekday) const
Unexecuted instantiation: QuantLib::Calendar::isWeekend(QuantLib::Weekday) const
273
274
0
    inline bool operator==(const Calendar& c1, const Calendar& c2) {
275
0
        return (c1.empty() && c2.empty())
276
0
            || (!c1.empty() && !c2.empty() && c1.name() == c2.name());
277
0
    }
278
279
0
    inline bool operator!=(const Calendar& c1, const Calendar& c2) {
280
0
        return !(c1 == c2);
281
0
    }
282
283
0
    inline std::ostream& operator<<(std::ostream& out, const Calendar &c) {
284
0
        return out << c.name();
285
0
    }
286
287
}
288
289
#endif