From d8c6c105d6d60be11288d9d3ae303dde31f4f9a0 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Adjemian=20=28Charybdis=29?=
 <stepan@adjemian.eu>
Date: Thu, 11 Feb 2021 19:00:07 +0100
Subject: [PATCH] Fixed bug in conversion of dates to lower frequency.

Bug introduced in 7bb6a68 when changing the implementation of the
@dates class.

Also:

 - added unit tests,
 - added conversion to bi annual dates.
---
 src/utilities/convert/dates2M.m | 49 ++++++++++++++++++++++--
 src/utilities/convert/dates2Q.m | 66 ++++++++++++++++++++++++++++++--
 src/utilities/convert/dates2S.m | 47 +++++++++++++++++++++++
 src/utilities/convert/dates2Y.m | 68 +++++++++++++++++++++++++++++++--
 4 files changed, 221 insertions(+), 9 deletions(-)
 create mode 100644 src/utilities/convert/dates2S.m

diff --git a/src/utilities/convert/dates2M.m b/src/utilities/convert/dates2M.m
index 91ce7f3..15bf188 100644
--- a/src/utilities/convert/dates2M.m
+++ b/src/utilities/convert/dates2M.m
@@ -1,4 +1,4 @@
-function m = dates2M(d)
+function m = dates2M(d) % --*-- Unitary tests --*--
 
 % INPUTS
 % - d   [dates]    daily frequency object with n elements.
@@ -6,7 +6,7 @@ function m = dates2M(d)
 % OUTPUTS
 % - m   [dates]    monthly frequency object with n elements (with repetitions).
 
-% Copyright © 2020 Dynare Team
+% Copyright © 2021 Dynare Team
 %
 % This code is free software: you can redistribute it and/or modify
 % it under the terms of the GNU General Public License as published by
@@ -30,4 +30,47 @@ else
     error('Cannot convert to higher frequency.')
 end
 
-m = dates(12, time(:,1:2));
\ No newline at end of file
+m = dates(12, time(:,1:2));
+
+return
+
+%@test:1
+try
+    m = dates2M(dates('1938-11-22'));
+    t(1) = true;
+catch
+    t(1) = false;
+end
+
+if t(1)
+    t(2) = isequal(m, dates('1938M11'));
+end
+
+T = all(t);
+%@eof:1
+
+%@test:2
+try
+    m = dates2M(dates('1938M11'));
+    t(1) = true;
+catch
+    t(1) = false;
+end
+
+if t(1)
+    t(2) = isequal(m, dates('1938M11'));
+end
+
+T = all(t);
+%@eof:2
+
+%@test:3
+try
+    m = dates2M(dates('1938Q4'));
+    t(1) = false;
+catch
+    t(1) = true;
+end
+
+T = all(t);
+%@eof:3
\ No newline at end of file
diff --git a/src/utilities/convert/dates2Q.m b/src/utilities/convert/dates2Q.m
index 7414ccc..bab7b0e 100644
--- a/src/utilities/convert/dates2Q.m
+++ b/src/utilities/convert/dates2Q.m
@@ -1,4 +1,4 @@
-function m = dates2Q(d)
+function m = dates2Q(d)  % --*-- Unitary tests --*--
 
 % INPUTS
 % - d   [dates]    daily frequency object with n elements.
@@ -24,7 +24,9 @@ function m = dates2Q(d)
 if d.freq==365
     time = datevec(d.time(:,1));
 elseif d.freq==12
-    time = d.time;
+    y = floor((d.time-1)/d.freq);
+    s = d.time-y*d.freq;
+    time = [y, s];
 elseif d.freq==4
     m = d;
     return
@@ -42,4 +44,62 @@ time(isq2,2) = 2;
 time(isq3,2) = 3;
 time(isq4,2) = 4;
 
-m = dates(4, time(:,1:2));
\ No newline at end of file
+m = dates(4, time(:,1:2));
+
+return
+
+%@test:1
+try
+    m = dates2Q(dates('1938-11-22'));
+    t(1) = true;
+catch
+    t(1) = false;
+end
+
+if t(1)
+    t(2) = isequal(m, dates('1938Q4'));
+end
+
+T = all(t);
+%@eof:1
+
+%@test:2
+try
+    m = dates2Q(dates('1938M11'));
+    t(1) = true;
+catch
+    t(1) = false;
+end
+
+if t(1)
+    t(2) = isequal(m, dates('1938Q4'));
+end
+
+T = all(t);
+%@eof:2
+
+%@test:3
+try
+    m = dates2Q(dates('1938Q4'));
+    t(1) = true;
+catch
+    t(1) = false;
+end
+
+if t(1)
+    t(2) = isequal(m, dates('1938Q4'));
+end
+
+T = all(t);
+%@eof:3
+
+%@test:4
+try
+    m = dates2Q(dates('1938S2'));
+    t(1) = false;
+catch
+    t(1) = true;
+end
+
+T = all(t);
+%@eof:4
\ No newline at end of file
diff --git a/src/utilities/convert/dates2S.m b/src/utilities/convert/dates2S.m
new file mode 100644
index 0000000..c91a6bb
--- /dev/null
+++ b/src/utilities/convert/dates2S.m
@@ -0,0 +1,47 @@
+function m = dates2S(d)
+
+% INPUTS
+% - d   [dates]    daily frequency object with n elements.
+%
+% OUTPUTS
+% - q   [dates]    bi-annual frequency object with n elements (with repetitions).
+
+% Copyright © 2021 Dynare Team
+%
+% This code is free software: you can redistribute it and/or modify
+% it under the terms of the GNU General Public License as published by
+% the Free Software Foundation, either version 3 of the License, or
+% (at your option) any later version.
+%
+% Dynare dates submodule is distributed in the hope that it will be useful,
+% but WITHOUT ANY WARRANTY; without even the implied warranty of
+% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+% GNU General Public License for more details.
+%
+% You should have received a copy of the GNU General Public License
+% along with Dynare.  If not, see <http://www.gnu.org/licenses/>.
+
+if d.freq==365
+    time = datevec(d.time(:,1));
+elseif d.freq==12
+    time = d.time;
+elseif d.freq==4
+    time = d.time;
+elseif d.freq==2
+    m = d;
+    return
+else
+    error('Cannot convert to higher frequency.')
+end
+
+isq1 = arrayfun( @(m) ismember(m, [1, 2, 3]), time(:,2));
+isq2 = arrayfun( @(m) ismember(m, [4, 5, 6]), time(:,2));
+isq3 = arrayfun( @(m) ismember(m, [7, 8, 9]), time(:,2));
+isq4 = arrayfun( @(m) ismember(m, [10, 11, 12]), time(:,2));
+
+time(isq1,2) = 1;
+time(isq2,2) = 2;
+time(isq3,2) = 3;
+time(isq4,2) = 4;
+
+m = dates(4, time(:,1:2));
\ No newline at end of file
diff --git a/src/utilities/convert/dates2Y.m b/src/utilities/convert/dates2Y.m
index 848b111..0f9ac68 100644
--- a/src/utilities/convert/dates2Y.m
+++ b/src/utilities/convert/dates2Y.m
@@ -23,8 +23,8 @@ function y = dates2Y(d)
 
 if d.freq==365
     time = datevec(d.time(:,1));
-elseif d.freq==12 || d.freq==4
-    time = d.time;
+elseif ismember(d.freq, [2,4,12])
+    time = floor((d.time-1)/d.freq);
 elseif d.freq==1
     y = d;
     return
@@ -32,4 +32,66 @@ else
     error('Unknown frequency.')
 end
 
-y = dates(1, time(:,1));
\ No newline at end of file
+y = dates(1, time(:,1));
+
+return
+
+%@test:1
+try
+    m = dates2Y(dates('1938-11-22'));
+    t(1) = true;
+catch
+    t(1) = false;
+end
+
+if t(1)
+    t(2) = isequal(m, dates('1938Y'));
+end
+
+T = all(t);
+%@eof:1
+
+%@test:2
+try
+    m = dates2Y(dates('1938M11'));
+    t(1) = true;
+catch
+    t(1) = false;
+end
+
+if t(1)
+    t(2) = isequal(m, dates('1938Y'));
+end
+
+T = all(t);
+%@eof:2
+
+%@test:3
+try
+    m = dates2Y(dates('1938S2'));
+    t(1) = true;
+catch
+    t(1) = false;
+end
+
+if t(1)
+    t(2) = isequal(m, dates('1938Y'));
+end
+
+T = all(t);
+%@eof:3
+
+%@test:4
+try
+    m = dates2Q(dates('1938Y'));
+    t(1) = true;
+catch
+    t(1) = false;
+end
+
+if t(1)
+    t(2) = isequal(m, dates('1938Y'));
+end
+
+T = all(t);
+%@eof:4
\ No newline at end of file
-- 
GitLab