diff --git a/matlab/perfect-foresight-models/make_ex_.m b/matlab/perfect-foresight-models/make_ex_.m
index e98f4c4b5dffb48d5644c97a66e1256ef0ebe20a..0d796d89e26376ebf23aabab6b1dc75051aebae6 100644
--- a/matlab/perfect-foresight-models/make_ex_.m
+++ b/matlab/perfect-foresight-models/make_ex_.m
@@ -28,11 +28,12 @@ function oo_ = make_ex_(M_, options_, oo_)
 % along with Dynare.  If not, see <https://www.gnu.org/licenses/>.
 
 try
-    periods = get_simulation_periods(options_);
+    [periods, first_simulation_period] = get_simulation_periods(options_);
 catch ME
     if strcmp(ME.identifier, 'Dynare:periodsNotSet')
         % This function is called from dyn_forecast in some contexts where periods is not set
         periods = 0;
+        first_simulation_period = options_.simul.first_simulation_period;
     else
         rethrow(ME);
     end
@@ -91,11 +92,20 @@ end
 
 % Add temporary shocks
 if isfield(M_, 'det_shocks')
-    if ~isempty(M_.det_shocks) && any([M_.det_shocks.periods]==0) && ~M_.maximum_lag
-        error('make_ex_: The model does not have lags, so you cannot set values for period 0'); %leads are taken care of by preprocessor
-    end
     for i = 1:length(M_.det_shocks)
-        k = M_.det_shocks(i).periods + M_.maximum_lag;
+        if isa(M_.det_shocks(i).periods, 'numeric')
+            k = M_.det_shocks(i).periods + M_.maximum_lag;
+            if any(k == 0)
+                error('make_ex_: The model does not have lags, so you cannot set values for period 0');
+            end
+        else % dates
+            k = M_.det_shocks(i).periods - first_simulation_period + 1 + M_.maximum_lag;
+            if any(k <= 1)
+                %% Contrary to the numeric case, we don’t allow k=0 for the dates case, because it
+                %% was a design mistake to allow them here (histval should rather be used)
+                error('make_ex_: some shocks are set at a date before the first simulation period');
+            end
+        end
         ivar = M_.det_shocks(i).exo_id;
         v = M_.det_shocks(i).value;
         if ~M_.det_shocks(i).exo_det
diff --git a/matlab/perfect-foresight-models/perfect_foresight_setup.m b/matlab/perfect-foresight-models/perfect_foresight_setup.m
index bcbc17d9e90af24ad49c3f15aa3a50ea5ffcb79e..ff65afb797ee3395c9b8816d6cc228ce662e48e2 100644
--- a/matlab/perfect-foresight-models/perfect_foresight_setup.m
+++ b/matlab/perfect-foresight-models/perfect_foresight_setup.m
@@ -47,19 +47,25 @@ if size(M_.lead_lag_incidence,2)-nnz(M_.lead_lag_incidence(M_.maximum_endo_lag+1
     error(mess)
 end
 
-periods = get_simulation_periods(options_);
+[periods, ~, last_simulation_period] = get_simulation_periods(options_);
 
-if ~isempty(M_.det_shocks) && periods < max([M_.det_shocks.periods])
-    % Some expected shocks happen after the terminal period.
-    mess = sprintf('\nPERFECT_FORESIGHT_SETUP: Problem with the declaration of the expected shocks:\n');
+if ~isempty(M_.det_shocks)
+    % Check whether some expected shocks happen after the terminal period.
+    mess = '';
     for i=1:length(M_.det_shocks)
-        if any(M_.det_shocks(i).periods > periods)
+        if isa(M_.det_shocks(i).periods, 'dates') && isempty(last_simulation_period)
+            error('PERFECT_FORESIGHT_SETUP: temporary shocks are specified using dates but neither first_simulation_period nor last_simulation_period option was passed')
+        end
+        if (isa(M_.det_shocks(i).periods, 'numeric') && any(M_.det_shocks(i).periods > periods)) ...
+               || (isa(M_.det_shocks(i).periods, 'dates') && any(M_.det_shocks(i).periods > last_simulation_period))
             mess = sprintf('%s\n   At least one expected value for %s has been declared after the terminal period.', mess, M_.exo_names{M_.det_shocks(i).exo_id});
         end
     end
-    disp(mess)
-    skipline()
-    error('PERFECT_FORESIGHT_SETUP: Please check the declaration of the shocks or increase the number of periods in the simulation.')
+    if ~isempty(mess)
+        disp(sprintf('\nPERFECT_FORESIGHT_SETUP: Problem with the declaration of the expected shocks:\n%s', mess));
+        skipline()
+        error('PERFECT_FORESIGHT_SETUP: Please check the declaration of the shocks or increase the number of periods in the simulation.')
+    end
 end
 
 if options_.simul.endval_steady && M_.maximum_lead == 0
diff --git a/matlab/perfect-foresight-models/perfect_foresight_with_expectation_errors_setup.m b/matlab/perfect-foresight-models/perfect_foresight_with_expectation_errors_setup.m
index 545f566c5089cca9ca182a9d29c81f34c33d5734..7c938f9432acbd2899b638a71e5e2344c972e3c3 100644
--- a/matlab/perfect-foresight-models/perfect_foresight_with_expectation_errors_setup.m
+++ b/matlab/perfect-foresight-models/perfect_foresight_with_expectation_errors_setup.m
@@ -31,7 +31,7 @@ if ~isempty(oo_.initval_series)
     error('perfect_foresight_with_expectation_errors_setup: cannot be used in conjunction with histval_file/initval_file')
 end
 
-periods = get_simulation_periods(options_);
+[periods, first_simulation_period] = get_simulation_periods(options_);
 
 %% Initialize informational structures
 oo_.pfwee.terminal_info = NaN(M_.exo_nbr, periods); % 2nd dimension is informational time
@@ -72,11 +72,27 @@ else
         warning('perfect_foresight_with_expectation_errors_setup: there is no shocks(learnt_in=...) or endval(learnt_in=...) block, and you did not pass the datafile option, so there is no point in using this command')
     end
 
+    %% Check that dates can be processed, if any
+    allperiods = {};
+    if ~isempty(M_.det_shocks)
+        allperiods = [allperiods, {M_.det_shocks.periods}];
+    end
+    if ~isempty(M_.learnt_shocks)
+        allperiods = [allperiods, {M_.learnt_shocks.periods}];
+    end
+    if any(cellfun(@(x) isa(x, 'dates'), allperiods)) && isempty(first_simulation_period)
+        error('perfect_foresight_with_expectations_error_setup: at least one periods statement is specified using a date but neither first_simulation_period nor last_simulation_period option was passed')
+    end
+
     %% Initialize information set at period 1 using “bare” shocks and endval blocks (or initval if there is no endval)
     oo_.pfwee.terminal_info(:, 1) = oo_.exo_steady_state;
     oo_.pfwee.shocks_info(:, :, 1) = repmat(oo_.exo_steady_state, 1, periods);
     for i = 1:length(M_.det_shocks)
-        prds = M_.det_shocks(i).periods;
+        if isa(M_.det_shocks(i).periods, 'numeric')
+            prds = M_.det_shocks(i).periods;
+        else % dates
+            prds = M_.det_shocks(i).periods - first_simulation_period + 1;
+        end
         exo_id = M_.det_shocks(i).exo_id;
         v = M_.det_shocks(i).value;
         if ~M_.det_shocks(i).exo_det
@@ -121,7 +137,11 @@ else
             for i = 1:length(idx)
                 j = idx(i);
                 exo_id = M_.learnt_shocks(j).exo_id;
-                prds = M_.learnt_shocks(j).periods;
+                if isa(M_.learnt_shocks(j).periods, 'numeric')
+                    prds = M_.learnt_shocks(j).periods;
+                else % dates
+                    prds = M_.learnt_shocks(j).periods - first_simulation_period + 1;
+                end
                 switch M_.learnt_shocks(j).type
                     case 'level'
                         oo_.pfwee.shocks_info(exo_id, prds, p) = M_.learnt_shocks(j).value;
diff --git a/preprocessor b/preprocessor
index 35b68b1411ae18c1403882ab784897983c3193fd..8e3cdd94643b32e885a19ae4c79441ed952a5e2f 160000
--- a/preprocessor
+++ b/preprocessor
@@ -1 +1 @@
-Subproject commit 35b68b1411ae18c1403882ab784897983c3193fd
+Subproject commit 8e3cdd94643b32e885a19ae4c79441ed952a5e2f