001/* 002 * SPDX-License-Identifier: Apache-2.0 003 * 004 * Copyright 2025-2026 The Enola <https://enola.dev> Authors 005 * 006 * Licensed under the Apache License, Version 2.0 (the "License"); 007 * you may not use this file except in compliance with the License. 008 * You may obtain a copy of the License at 009 * 010 * https://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018package dev.enola.common.time; 019 020import dev.enola.common.context.Singleton; 021import dev.enola.common.context.TLC; 022 023import java.time.ZoneId; 024import java.time.ZoneOffset; 025 026/** 027 * ZoneIdSupplierTLC is a {@link ZoneIdSupplier} implementation that looks up the current TZ from 028 * the {@link TLC}. If it's not found there, then it checks the (static) {@link #SINGLETON}. 029 * Otherwise, it falls back to one passed to the constructor. 030 */ 031public final class ZoneIdSupplierTLC implements ZoneIdSupplier { 032 033 public static final Singleton<ZoneId> SINGLETON = new Singleton<>() {}; 034 035 /** 036 * Falls back to (variable) {@link ZoneId#systemDefault()} if no TZ has been pushed to the 037 * {@link TLC} nor set on the {@link #SINGLETON}. 038 * 039 * <p>Using this in tests could lead to flaky tests which depend on the local OS default. 040 */ 041 public static final ZoneIdSupplierTLC JVM_DEFAULT = 042 new ZoneIdSupplierTLC(ZoneId.systemDefault()); 043 044 /** 045 * Falls back to (constant) {@link ZoneOffset#UTC} if no Locale has been pushed to the {@link 046 * TLC} nor set on the {@link #SINGLETON}. 047 */ 048 public static final ZoneIdSupplierTLC UTC = new ZoneIdSupplierTLC(ZoneOffset.UTC); 049 050 private final ZoneId falbackZoneId; 051 052 /** Creates a new instance which falls back to the TZ passed to this constructor. */ 053 public ZoneIdSupplierTLC(ZoneId fallback) { 054 this.falbackZoneId = fallback; 055 } 056 057 @Override 058 public ZoneId get() { 059 return TLC.optional(ZoneId.class).or(SINGLETON::getOptional).orElse(falbackZoneId); 060 } 061}