Prepare Oracle Database 19c,26ai for new time zones of British Columbia , Alberta and Manitoba

Photo by Luis Cortes on Unsplash
Problem Statement
British Columbia , Alberta and Manitoba are Canadian provinces which are adopting permanent daylight saving time starting November 1, 2026, ending seasonal clock changes. For an Oracle DBA this means applying a new time zone patch to the database be it 19c or 26ai . Its very rare to find resources on how to apply a timezone patch hence writing this blog for readers to get an idea around it.
1st thing to remember is the timezone patch that covers all these provinces is DSTv47 , read this article for accurate details KB933005 . This article highlights the need to apply RDBMS DSTv47 PATCH 40063528 and OJVM DSTv47 PATCH 40063583 to all supported versions of oracle.
Solution in a nutshell
If you are patching a 19c oracle home , you can apply below 3 patches in the same sequence , else for 26ai homes you can skip the 1st patch
Patch 27605010: DST UPGRADE SLOW (BEGIN_UPGRADE AND UPGRADE_DATABASE) EVEN WITH PATCH 19704999 (Only for 19c Homes)
Patch 40063528: RDBMS - DSTV47 UPDATE - TZDATA2026D & TZDATA2026E
Patch 40063583: DSTV47 UPDATE - TZDATA2026D & TZDATA2026E - NEED OJVM FIX
Implementation Steps
Simple glance at the Read Me files for the above would give you the basic steps for each
#Pro Tip: Backup your oracle home and database prior to the activity
$ORACLE_HOME/OPatch/opatch prereq CheckConflictAgainstOHWithDetail -ph ./
$ORACLE_HOME/OPatch/opatch apply
Note : There are some additional steps while applying the ojvm patch 40063583
cd 40063583
opatch apply
* connect as SYS for non-CDB and for CDB connect to root container CDB$ROOT
SQL>startup
SQL>@?/javavm/admin/fixTZa.sql
...
...
########################################################
Bug is in fact present, so this patch is needed
Proceed by restarting the database and running script
fixTZb
########################################################
# Only if you see above message follow below steps #
SQL>shut immediate
SQL>startup upgrade
SQL>@?/javavm/admin/fixTZb.sql
...
...
########################################################
Bug is no longer present. Patch succeeded.
########################################################
SQL>shut immediate
SQL>startup
Once all the 3 patches have been applied you need to upgrade the timezone files as well as timezone data based on new time zone file . To achieve this we will be using the DBMS_DST package.
If you are at 19c Home the below steps needs to be run as SYS user . If you are at 26ai home , run the below steps for each container .
Step1:
-- Check the current timezone version
SQL> SELECT * FROM v$timezone_file;
FILENAME VERSION CON_ID
-------------------- -------------------- --------------------
timezlrg_32.dat 32 0
SELECT tz_version FROM registry$database;
TZ_VERSION
--------------------
32
COLUMN property_name FORMAT A30
COLUMN property_value FORMAT A20
SELECT property_name, property_value
FROM database_properties
WHERE property_name LIKE 'DST_%'
ORDER BY property_name;
PROPERTY_NAME PROPERTY_VALUE
------------------------------ --------------------
DST_PRIMARY_TT_VERSION 32
DST_SECONDARY_TT_VERSION 0
DST_UPGRADE_STATE NONE
-- Check the latest timezone version available from the patch , this must show as 47
SQL>SELECT DBMS_DST.get_latest_timezone_version FROM dual;
GET_LATEST_TIMEZONE_VERSION
---------------------------
47
-- Start a prepare window
SQL>set timing on;
DECLARE
l_tz_version PLS_INTEGER;
BEGIN
l_tz_version := DBMS_DST.get_latest_timezone_version;
DBMS_OUTPUT.put_line('l_tz_version=' || l_tz_version);
DBMS_DST.begin_prepare(l_tz_version);
END;
/
PL/SQL procedure successfully completed.
-- This must show the secondary timezone version as 47 , primary should be lesser than this
COLUMN property_name FORMAT A30
COLUMN property_value FORMAT A20
SELECT property_name, property_value
FROM database_properties
WHERE property_name LIKE 'DST_%'
ORDER BY property_name;
PROPERTY_NAME PROPERTY_VALUE
------------------------------ --------------------
DST_PRIMARY_TT_VERSION 32
DST_SECONDARY_TT_VERSION 47
DST_UPGRADE_STATE PREPARE
-- Count(*) for both the tables should be '0' if not truncate them both
select count(*) from sys.dst$affected_tables;
select count(*) from sys.dst$error_table;
-- Find the tables which will be affected by the new timezone date
SQL>EXEC DBMS_DST.find_affected_tables;
-- Check which tables are affected , if there is any data in sys.dst$error_table check with oracle support
SQL>select * from sys.dst$affected_tables;
SQL>select * from sys.dst$error_table;
--End the prepare window
SQL>EXEC DBMS_DST.end_prepare;
-- After ending the upgrade state should reflect back to none
SELECT property_name, property_value
FROM database_properties
WHERE property_name LIKE 'DST_%'
ORDER BY property_name;
PROPERTY_NAME PROPERTY_VALUE
------------------------------ --------------------
DST_PRIMARY_TT_VERSION 32
DST_SECONDARY_TT_VERSION 0
DST_UPGRADE_STATE NONE
If you are on a 19c home run Step2 ,skip Step3 and proceed next to Step4
Step2:
SQL>shut immediate
SQL>startup upgrade
If you are on a 26ai home skip Step2 , proceed to Step3 and Step4 onwards
Step3:
-- For homes above 21c
SQL> ALTER SYSTEM SET TIMEZONE_VERSION_UPGRADE_ONLINE = TRUE containers=ALL;
-- This means you donot have to restart database in upgrade mode
Step4:
SQL> set timing on
SET SERVEROUTPUT ON
DECLARE
l_failures PLS_INTEGER;
BEGIN
DBMS_DST.upgrade_database(l_failures);
DBMS_OUTPUT.put_line('DBMS_DST.upgrade_database : l_failures=' || l_failures);
SQL> DBMS_DST.end_upgrade(l_failures);
DBMS_OUTPUT.put_line('DBMS_DST.end_upgrade : l_failures=' || l_failures);
END;
/
...
...
DBMS_DST.upgrade_database : l_failures=0
An upgrade window has been successfully ended.
DBMS_DST.end_upgrade : l_failures=0
-- It should show the new timezone version
SQL> COLUMN property_name FORMAT A30
COLUMN property_value FORMAT A20
SELECT property_name, property_value
FROM database_properties
WHERE property_name LIKE 'DST_%'
ORDER BY property_name;
PROPERTY_NAME PROPERTY_VALUE
------------------------------ --------------------
DST_PRIMARY_TT_VERSION 47
DST_SECONDARY_TT_VERSION 0
DST_UPGRADE_STATE NONE
-- This should show the upgrade_in_progress column as "No" for all the tables , if any table is still in upgrade state contact oracle support
SQL> COLUMN owner FORMAT A30
COLUMN table_name FORMAT A30
SELECT con_id,
owner,
table_name,
upgrade_in_progress
FROM cdb_tstz_tables
ORDER BY 1,2,3;
SQL> SELECT * FROM v$timezone_file;
-- compile all the packages
SQL> @?/rdbms/admin/utlrp.sql
-- Check if all the registry components are valid
SQL> SET LINES 1000
COLUMN COMPONENT FORMAT A40
SELECT comp_name AS component, version, status
FROM dba_registry;
For a 19c Home this is it and your database timezone has been upgraded
For a 26ai Home , this step is complete for the root container CDB$ROOT , now switch to your pdb ( SQL> ALTER SESSION SET CONTAINER = MYPRODPDB; ) and rerun all the steps (Step1-> Step3 -> Step4 ) skipping Step2 .
Note :- There are multiple bugs in 19c home for using the DBMS_DST package in various versions , consider checking the oracle knowledge article KB86566 before prcoeeding.
References
Updating the RDBMS DST version in 12c Release 1 (12.1.0.1 and up) using DBMS_DST (KB86566)
Applying the DSTv47 update for the Oracle Database
Upgrade the Database Time Zone File Using the DBMS_DST Package