1 /*
2 * *************************************************************************************************************************************************************
3 *
4 * TheseFoolishThings: Miscellaneous utilities
5 * http://tidalwave.it/projects/thesefoolishthings
6 *
7 * Copyright (C) 2009 - 2025 by Tidalwave s.a.s. (http://tidalwave.it)
8 *
9 * *************************************************************************************************************************************************************
10 *
11 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License.
12 * You may obtain a copy of the License at
13 *
14 * http://www.apache.org/licenses/LICENSE-2.0
15 *
16 * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
17 * CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
18 *
19 * *************************************************************************************************************************************************************
20 *
21 * git clone https://bitbucket.org/tidalwave/thesefoolishthings-src
22 * git clone https://github.com/tidalwave-it/thesefoolishthings-src
23 *
24 * *************************************************************************************************************************************************************
25 */
26 package it.tidalwave.util;
27
28 import jakarta.annotation.Nonnull;
29 import java.time.Instant;
30 import java.time.LocalDateTime;
31 import java.time.ZoneId;
32 import java.time.ZonedDateTime;
33 import java.util.concurrent.atomic.AtomicReference;
34 import java.util.function.Supplier;
35
36 /***************************************************************************************************************************************************************
37 *
38 * A provider of current time. It should be used by code requiring a timestamp, so it can be mocked during tests.
39 * {@code MockTimeProvider} in module "Test Utilities" is a suitable mock for performing tests.
40 *
41 * @author Fabrizio Giudici
42 * @since 3.2-ALPHA-1 (was previously InstantProvider since 1.39)
43 *
44 **************************************************************************************************************************************************************/
45 @FunctionalInterface
46 public interface TimeProvider extends Supplier<Instant>
47 {
48 // FIXME: should be private
49 public static AtomicReference<TimeProvider> __INSTANCE = new AtomicReference<>();
50
51 /***********************************************************************************************************************************************************
52 * Returns the current time.
53 *
54 * @return the current time as an {@link Instant}
55 * @since 3.2-ALPHA-2
56 **********************************************************************************************************************************************************/
57 @Nonnull
58 public Instant currentInstant();
59
60 /***********************************************************************************************************************************************************
61 * Returns the current time. This method is provided to implement {@link Supplier}{@code <Instant>}.
62 *
63 * @return the current time as an {@link Instant}
64 * @since 3.2-ALPHA-2
65 **********************************************************************************************************************************************************/
66 @Override @Nonnull
67 public default Instant get()
68 {
69 return currentInstant();
70 }
71
72 /***********************************************************************************************************************************************************
73 * Returns the current time.
74 *
75 * @return the current time as a {@link ZonedDateTime} in the default zone.
76 * @since 3.2-ALPHA-2
77 **********************************************************************************************************************************************************/
78 @Nonnull
79 public default ZonedDateTime currentZonedDateTime()
80 {
81 return ZonedDateTime.ofInstant(currentInstant(), ZoneId.systemDefault());
82 }
83
84 /***********************************************************************************************************************************************************
85 * Returns the current time.
86 *
87 * @return the current time as a {@link LocalDateTime} in the default zone.
88 * @since 3.2-ALPHA-2
89 **********************************************************************************************************************************************************/
90 @Nonnull
91 public default LocalDateTime currentLocalDateTime()
92 {
93 return LocalDateTime.ofInstant(currentInstant(), ZoneId.systemDefault());
94 }
95
96 /***********************************************************************************************************************************************************
97 * Returns the default instance.
98 *
99 * @return the default instance
100 * @since 3.2-ALPHA-2
101 **********************************************************************************************************************************************************/
102 @Nonnull
103 public static TimeProvider getInstance()
104 {
105 synchronized (TimeProvider.class)
106 {
107 if (__INSTANCE.get() == null)
108 {
109 __INSTANCE.set(new DefaultTimeProvider());
110 }
111
112 return __INSTANCE.get();
113 }
114 }
115
116 /***********************************************************************************************************************************************************
117 *
118 **********************************************************************************************************************************************************/
119 static class DefaultTimeProvider implements TimeProvider
120 {
121 @Override @Nonnull
122 public Instant currentInstant()
123 {
124 return Instant.now();
125 }
126 }
127 }