Bug-1771: Private constuctors in utility static classes throws UnsupportedOperationEx...
[bgpcep.git] / programming / api / src / main / java / org / opendaylight / bgpcep / programming / NanotimeUtil.java
1 /*
2  * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8 package org.opendaylight.bgpcep.programming;
9
10 import java.math.BigInteger;
11 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.programming.rev130930.Nanotime;
12 import org.slf4j.Logger;
13 import org.slf4j.LoggerFactory;
14
15 /**
16  * Util methods for {@link Nanotime}.
17  */
18 public final class NanotimeUtil {
19     private static final Logger LOG = LoggerFactory.getLogger(NanotimeUtil.class);
20     private static final BigInteger MILLION = BigInteger.valueOf(1000000);
21     private static volatile BigInteger nanoTimeOffset = null;
22
23     private NanotimeUtil() {
24         throw new UnsupportedOperationException();
25     }
26
27     /**
28      * Returns current time in nanoseconds.
29      *
30      * @return Nanotime object filled with current time in nanoseconds.
31      */
32     public static Nanotime currentTime() {
33         return new Nanotime(BigInteger.valueOf(System.currentTimeMillis()).multiply(MILLION));
34     }
35
36     /**
37      * Returns calibrated current JVM nano time.
38      *
39      * @return Nanotime object filled with current JVM nano time.
40      */
41     public static Nanotime currentNanoTime() {
42         if (nanoTimeOffset == null) {
43             calibrate();
44         }
45         return new Nanotime(BigInteger.valueOf(System.nanoTime()).add(nanoTimeOffset));
46     }
47
48     /**
49      * Calibrates the offset between the real-time clock providing System.currentTimeMillis() and the monotonic clock
50      * providing System.nanoTime(). This method should be called whenever there is a hint of the two diverging: either
51      * when time shifts or periodically.
52      */
53     public static void calibrate() {
54         final long tm1 = System.currentTimeMillis();
55         final long nt1 = System.nanoTime();
56         final long tm2 = System.currentTimeMillis();
57         final long nt2 = System.nanoTime();
58
59         LOG.debug("Calibrated currentTime and nanoTime to {}m <= {}n <= {}m <= {}n", tm1, nt1, tm2, nt2);
60
61         final BigInteger tm = BigInteger.valueOf(tm1).add(BigInteger.valueOf(tm2)).divide(BigInteger.valueOf(2));
62         final BigInteger nt = BigInteger.valueOf(nt1).add(BigInteger.valueOf(nt2)).divide(BigInteger.valueOf(2));
63
64         nanoTimeOffset = tm.multiply(MILLION).subtract(nt);
65     }
66 }