1
2
3
4
5
6
7
8
9
10
11
12
13
14 package ch.qos.logback.core.util;
15
16 import java.time.Instant;
17 import java.time.OffsetDateTime;
18 import java.time.ZoneId;
19 import java.time.format.DateTimeFormatter;
20 import java.util.Locale;
21 import java.util.concurrent.atomic.AtomicReference;
22
23
24
25
26
27
28
29
30 public class CachingDateFormatter {
31
32 final DateTimeFormatter dtf;
33 final ZoneId zoneId;
34 final AtomicReference<CacheTuple> atomicReference;
35
36 static class CacheTuple {
37 final long lastTimestamp;
38 final String cachedStr;
39
40 public CacheTuple(long lastTimestamp, String cachedStr) {
41 super();
42 this.lastTimestamp = lastTimestamp;
43 this.cachedStr = cachedStr;
44 }
45 }
46
47 public CachingDateFormatter(String pattern) {
48 this(pattern, null);
49 }
50
51 public CachingDateFormatter(String pattern, ZoneId aZoneId) {
52 this(pattern, aZoneId, null);
53 }
54
55 public CachingDateFormatter(String pattern, ZoneId aZoneId, Locale aLocale) {
56 if (aZoneId == null) {
57 this.zoneId = ZoneId.systemDefault();
58 } else {
59 this.zoneId = aZoneId;
60 }
61 Locale locale = aLocale != null ? aLocale : Locale.getDefault();
62
63 dtf = DateTimeFormatter.ofPattern(pattern).withZone(this.zoneId).withLocale(locale);
64 CacheTuple cacheTuple = new CacheTuple(-1, null);
65 this.atomicReference = new AtomicReference<>(cacheTuple);
66 }
67
68 public final String format(long now) {
69 CacheTuple localCacheTuple = atomicReference.get();
70 CacheTuple oldCacheTuple = localCacheTuple;
71
72 if (now != localCacheTuple.lastTimestamp) {
73 Instant instant = Instant.ofEpochMilli(now);
74 String result = dtf.format(instant);
75 localCacheTuple = new CacheTuple(now, result);
76
77 atomicReference.compareAndSet(oldCacheTuple, localCacheTuple);
78 }
79 return localCacheTuple.cachedStr;
80 }
81
82 }