Skip to content

[RFC] :LEGACY typezones with deprecation warnings.#504

Open
rofinn wants to merge 3 commits intomasterfrom
rf/469
Open

[RFC] :LEGACY typezones with deprecation warnings.#504
rofinn wants to merge 3 commits intomasterfrom
rf/469

Conversation

@rofinn
Copy link
Copy Markdown
Member

@rofinn rofinn commented Jan 7, 2026

Related to #469 and #419.

Background

We already have access to links when compiling tzjfiles, but we currently don't retain that information for TimeZones.jl to use. The proposed solution is to:

  1. Optionally include timezone link targets in our TZJFile tuples
  2. Update the TimeZone constructor to auto-redirect legacy timezones with the link info and throw a depwarn, so errors are limited to running with --depwarn=error.

Usage

On Julia v1.12.3

Basic:

> julia --project=.

julia> using TimeZones

julia> tz"Europe/Amsterdam"
Europe/Brussels (UTC+1/UTC+2)

Error:

> julia --depwarn=error --project=.

julia> using TimeZones

julia> tz"Europe/Amsterdam"
ERROR: LoadError: The time zone "Europe/Amsterdam" is deprecated, using "Europe/Brussels" instead.
Stacktrace:
 [1] _depwarn(msg::Any, funcsym::Any, force::Bool)
   @ Base ./deprecated.jl:262
 [2] #invokelatest_gr#232
   @ ./reflection.jl:1295 [inlined]
 [3] invokelatest_gr
   @ ./reflection.jl:1289 [inlined]
 [4] #depwarn#953
   @ ./deprecated.jl:256 [inlined]
 [5] depwarn
   @ ./deprecated.jl:251 [inlined]
 [6] TimeZone(str::String, mask::TimeZones.Class)
   @ TimeZones ~/repos/invenia/TimeZones.jl/src/types/timezone.jl:56
 [7] TimeZone(str::String)
   @ TimeZones ~/repos/invenia/TimeZones.jl/src/types/timezone.jl:42
 [8] var"@tz_str"(__source__::LineNumberNode, __module__::Module, str::Any)
   @ TimeZones ~/repos/invenia/TimeZones.jl/src/types/timezone.jl:85
in expression starting at REPL[2]:1

V1 (same behaviour):

> JULIA_TZJ_VERSION=1 julia --project=.

julia> using TimeZones, Dates

julia> tz"Europe/Amsterdam"
ERROR: LoadError: ArgumentError: The time zone "Europe/Amsterdam" is of class `TimeZones.Class(:LEGACY)` which is currently not allowed by the mask: `TimeZones.Class(:FIXED) | TimeZones.Class(:STANDARD)`
Stacktrace:
 [1] TimeZone(str::String, mask::TimeZones.Class)
   @ TimeZones ~/repos/invenia/TimeZones.jl/src/types/timezone.jl:64
 [2] TimeZone(str::String)
   @ TimeZones ~/repos/invenia/TimeZones.jl/src/types/timezone.jl:42
 [3] var"@tz_str"(__source__::LineNumberNode, __module__::Module, str::Any)
   @ TimeZones ~/repos/invenia/TimeZones.jl/src/types/timezone.jl:85
in expression starting at REPL[2]:1

Decisions Summary

  • Union{String, Nothing} in the compiled files for simplicity.
  • We are not handling the recursive case for links (a -> b -> c) and assuming (a -> c, b -> c) as stated in the backward file header.
  • To keep the cache tuples isbits, I'm reusing InlineStrings.jl with an empty string instead of nothing. Looks like InlineString31 should fit all the names, but it does increase memory usage per cache entry.
  • The JULIA_TZJ_VERSION feature flag and compiled path changes are just some hacks to support switching between formats for testing the behaviour. It has been handy for testing, but could be reverted. Also, maybe there's an easier way I'm unfamiliar with?

rofinn added 3 commits January 5, 2026 10:23
- We're using InlineStrings and a sentinel empty string to retain the
  isbits property where possible. Unfortunately, we needed to update a
  bunch of helpers for this.
- Since some names in the backward file exceed the InlineString15 size
  we're using InlineString31.
- It seemed a bit verbose so I renamed link_target to just link
  where appropriate.
- We also added "backward" to the test regions and added a compile.jl
  test that ensure only :LEGACY timezones have links saved (reducing
  memory usage).
NOTES:
- Wrapped `DEFAULT_VERSION` in `tzjfile_version()` which supports a JULIA_TZJ_VERSION feature flag.
- Setup expected compiled dir to include the version format (`~/.julia/scratchspaces/f269a46b-ccf7-5d73-abea-4c690281aa53/build/compiled/tzjf/v2/2025b`)
- Needed some hacks in __init__ and timezonecache._build to handle the path changes temporarily.
Comment thread src/TimeZones.jl
function __init__()
# Set at runtime to ensure relocatability
_COMPILED_DIR[] = @static if isdefined(TZJData, :artifact_dir)
# Prefer scratch-compiled directory with matching versions, fall back to artifact
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Part of the version feature flag and path hacks for testing both v1 and v2 behaviour.

Comment thread src/types/timezone.jl
tz, class, link = get(_TZ_CACHE, str) do
if occursin(FIXED_TIME_ZONE_REGEX, str)
FixedTimeZone(str), Class(:FIXED)
FixedTimeZone(str), Class(:FIXED), InlineString31("")
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unfortunately, a Union with nothing is not isbits, hence the empty InlineString31.

Comment thread src/types/timezone.jl
"The time zone \"$str\" is deprecated, using \"$link\" instead.",
:TimeZone
)
return TimeZone(String(link), mask)
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NOTE: If the backward file had a recursive case of a -> b -> c, then this would still error. The header comments say that's been avoided due to other parsers not handling it.

if desired_version != TZJData.TZDATA_VERSION
_COMPILED_DIR[] = TZData.build(desired_version, _scratch_dir())
# Also rebuilds if the TZJFile format version doesn't match the expected version
function _build(tzjf_version::Integer=TZJFile.tzjfile_version())
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Another main hack is for switching compiled file formats.

Comment thread src/tzjfile/TZJFile.jl
1
```
"""
function tzjfile_version()
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Again, a handy feature for switching compiled file versions, but it could be removed.

@rofinn
Copy link
Copy Markdown
Member Author

rofinn commented Jan 7, 2026

I'm not surprised about the TZJData system image errors, but the allocation test differences on 1.6 and nightly seem odd.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant