1 package org.opendaylight.mwtn.base.netconf;
3 import java.text.ParseException;
4 import java.text.SimpleDateFormat;
6 import java.util.TimeZone;
7 import java.util.regex.Matcher;
8 import java.util.regex.Pattern;
10 import org.opendaylight.yang.gen.v1.uri.onf.coremodel.corefoundationmodule.typedefinitions.rev160701.DateAndTime;
11 import org.slf4j.Logger;
12 import org.slf4j.LoggerFactory;
14 public class NetconfTimeStamp {
15 private static final Logger LOG = LoggerFactory.getLogger(NetconfTimeStamp.class);
17 private static final TimeZone TIMEZONEUTC = TimeZone.getTimeZone("GMT");
18 private static final SimpleDateFormat dateFormatResult = init("yyyy-MM-dd'T'HH:mm:ss.S'Z'",TIMEZONEUTC);
19 private static final SimpleDateFormat dateFormatConvert = init("yyyy-MM-dd HH:mm:ss.S", TIMEZONEUTC);
20 private static int MILLISECONDSDIGITS = 3; //Digits of milliseconds in dateFormatResult
21 private static String MILLISECONDZEROS = "000"; //String with zeros for milliseconds in dateFormatResult
23 private static final Pattern dateNetconfPatter[] = {
24 // 10 Groups, 1-7,9+10, ISO8601
25 Pattern.compile("(\\d{4})-(\\d{2})-(\\d{2})T(\\d{2}):(\\d{2}):(\\d{2})\\.(\\d+)?(Z|([+-]\\d{2}):(\\d{2}))"),
26 // 10 Groups, 1-7,9+10, Microwave ONF
27 Pattern.compile("(\\d{4})(\\d{2})(\\d{2})(\\d{2})(\\d{2})(\\d{2}).(\\d+)?(Z|([+-]\\d{2})(\\d{2}))"),
28 // 9 Groups, 1-6, 8+9Ericson. Example: 2017-01-23T13:32:38-05:00
29 Pattern.compile("(\\d{4})-(\\d{2})-(\\d{2})T(\\d{2}):(\\d{2}):(\\d{2})?(Z|([+-]\\d{2}):(\\d{2}))")
32 private static final Pattern dateNetconfPatter = Pattern
34 // 1) ISO8601. Example 2017-01-18T11:44:49.482-05:00
35 // 2) Microwave ONF. Examples 20170118114449.1Z, 20170118114449.1-0500
36 // 3.1) Ericson. Example: 2017-01-23T13:32:38-05:00
37 // 3.2) Ericson. Example: 2017-01-23T13:32-05:00
39 // 1:Year 2:Month 3:day 4:Hour 5:minute 6:optional sec 7:optional ms 8:optioal Z or 9:offset signedhour 10:min
40 .compile("(\\d{4})-?(\\d{2})-?(\\d{2})T?(\\d{2}):?(\\d{2})(?:(?::?)(\\d{2}))?(?:.(\\d+))?(?:(Z)|([+-]\\d{2}):?(\\d{2}))");
43 /* ------------------------------------
48 * Do not provide public constructor for this static module
51 private NetconfTimeStamp() {
55 * Static initialization
57 private static void doInit() {
58 LOG.debug("Init begin");
59 //dateFormatResult =new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
60 dateFormatResult =new SimpleDateFormat("yyyyMMddHHmmss.S'Z'"); //Netconf 1.0 format
61 dateFormatResult.setTimeZone(TIMEZONEUTC);
62 dateFormatConvert =new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.S");
63 dateFormatConvert.setTimeZone(TIMEZONEUTC);
64 LOG.debug("Init end");
67 public static SimpleDateFormat init(String format, TimeZone zone ) {
68 SimpleDateFormat dateFormat;
69 dateFormat = new SimpleDateFormat(format);
70 dateFormat.setTimeZone(zone);
74 /* ------------------------------------
79 * Get actual timestamp as NETCONF specific type NETCONF/YANG 1.0 Format
80 * @return String with Date in NETCONF/YANG Format Version 1.0.
82 public static String getTimeStampAsNetconfString() {
83 /*if (dateFormatResult == null) {
86 return getRightFormattedDate(new Date().getTime());
90 * Get actual timestamp as NETCONF specific type NETCONF/YANG 1.0 Format
91 * @return DateAndTime Type 1.0. Date in NETCONF/YANG Format Version 1.0.
93 public static DateAndTime getTimeStamp() {
94 /*if (dateFormatResult == null) {
98 return DateAndTime.getDefaultInstance(getTimeStampAsNetconfString());
102 * Input ist in folgenden Formaten, die über Netconf empfangen wurden möglich:
106 * 2017-01-18T11:44:49.482-05:00
109 * Netconf - pattern aus ietf-yang-types "2013-07-15"
110 * Pattern: "\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d+)?(Z|[\+\-](\d{2}):(\d{2}))"
113 * (Netconf) DateAndTime CoreModel-CoreFoundationModule-TypeDefinitions vom 2016-07-01
114 * Example1: 20170118114449.1Z
115 * Example2: 20170118114449.1-0500
116 * Pattern: "\d{4}\d{2}\d{2}\d{2}\d{2}\d{2}.\d+?(Z|[\+\-](\d{2})(\d{2}))"
117 * typedef DateAndTime {
118 * description "This primitive type defines the date and time according to the following structure:
119 * 'yyyyMMddhhmmss.s[Z|{+|-}HHMm]' where:
120 * yyyy '0000'..'9999' year
121 * MM '01'..'12' month
124 * mm '00'..'59' minute
125 * ss '00'..'59' second
126 * s '.0'..'.9' tenth of second (set to '.0' if EMS or NE cannot support this granularity)
127 * Z 'Z' indicates UTC (rather than local time)
128 * {+|-} '+' or '-' delta from UTC
129 * HH '00'..'23' time zone difference in hours
130 * Mm '00'..'59' time zone difference in minutes.";
133 * Format4 E/// specific
134 * Example1: 2017-01-23T13:32:38-05:00
135 * Example2: 2017-01-23T13:32-05:00
137 * @param netconfTime as String according the formats given above
138 * @return String in ISO8601 Format for database and presentation.
142 * Return the String with a NETCONF time converted to long
143 * @param netconfTime as String according the formats given above
144 * @return Epoch milliseconds
145 * @throws IllegalArgumentException In case of no compliant time format definition for the string
146 * @throws ParseException Time parsing failed
148 public static long getTimeStampFromNetconfAsMilliseconds( String netconfTime ) throws IllegalArgumentException, ParseException {
149 /*if (dateFormatResult == null) {
154 m = dateNetconfPatter.matcher(netconfTime);
155 //According to spezified matches there have to be 10 parameter
156 if (m.matches() && m.groupCount() == 10) {
158 long utcMillis = dateFormatConvert.parse(getTimeAsNormalizedString(m, m.group(6), m.group(7))).getTime()
159 - getTimezoneOffsetMilliseconds(m.group(9), m.group(10));
162 throw new IllegalArgumentException("No pattern for NETCONF data string: "+netconfTime);
168 * Deliver String result.
169 * @param netconfTime as String according the formats given above
170 * @return If successful: String in ISO8601 Format for database and presentation.
171 * If "wrong formed input" the Input string with the prefix "Mailformed date" is delivered back.
173 public static String getTimeStampFromNetconf( String netconfTime ) {
174 /*if (dateFormatResult == null) {
179 m = dateNetconfPatter.matcher(netconfTime);
180 //According to spezified matches there have to be 10 parameter
181 if (m.matches() && m.groupCount() == 10) {
184 long utcMillis = dateFormatConvert.parse(getTimeAsNormalizedString(m, m.group(6), m.group(7))).getTime()
185 - getTimezoneOffsetMilliseconds(m.group(9), m.group(10));
186 return getRightFormattedDate(utcMillis);
187 } catch (ParseException e) {
188 LOG.info(e.getMessage());
189 } catch (IllegalArgumentException e) {
190 LOG.info(e.getMessage());
194 LOG.debug("No pattern for NETCONF data string: {}",netconfTime);
195 return "Malformed date: "+netconfTime; //Error handling
197 /*-------------------------------------------
198 * Private and static functions
201 * Convert timeZone parameter in format [+-]/d/d:/d/d into milliseconds
202 * @param m Index 9 with "+/-" and hour string or null for UTZ, Index 10 with minutes
203 * @return long milliseconds of TimeZoneOffset
204 * @throws IllegalArgumentException If parameters are wrong
206 private static long getTimezoneOffsetMilliseconds(String timeZoneHour, String timeZoneMinute) throws IllegalArgumentException {
207 //-- Calculate timezone specific offset
208 long timeZoneOffsetMilliseconds = 0;
209 if (timeZoneHour != null) {
210 //Time zone offset in hours and minutes
213 tzHour = Integer.valueOf(timeZoneHour);
214 if (timeZoneMinute != null) {
215 tzMinutes = Integer.valueOf(timeZoneMinute);
217 throw new IllegalArgumentException("Problem in Netconf Time format timeZone minutes parameter.");
219 timeZoneOffsetMilliseconds = (tzHour * 60 + (tzHour > 0 ? tzMinutes : -tzMinutes))*60000;
221 return timeZoneOffsetMilliseconds;
224 * Convert parameters to String with year .. minutes and optional Seconds and .. milliseconds
225 * @param m Matcher with parsed date
226 * @param secString Seconds as String or null
227 * @param msString Milliseconds as String or null
228 * @return Normalized time string
230 private static String getTimeAsNormalizedString(Matcher m, String secString, String msString) {
231 //-- Create time as normalized string
232 StringBuffer sb = new StringBuffer();
233 sb.append(m.group(1)); //year
235 sb.append(m.group(2)); //Month
237 sb.append(m.group(3)); //Day
239 sb.append(m.group(4)); //Hour 0-23
241 sb.append(m.group(5)); //Minute
243 sb.append(secString != null ? secString : "00"); //Seconds (optional)
245 if (msString == null) { //Milliseconds optional
246 sb.append(MILLISECONDZEROS);
247 } else if (msString.length() <= MILLISECONDSDIGITS) {
248 sb.append(msString); //Millisecond
249 sb.append(MILLISECONDZEROS.substring(0, MILLISECONDSDIGITS-msString.length()));
251 sb.append(msString.substring(0, MILLISECONDSDIGITS )); //Only first Three
253 return sb.toString();
256 * Deliver format in a way that milliseconds are correct.
257 * @param dateMillis Date as milliseconds in Java definition
260 private static String getRightFormattedDate( long dateMillis ) {
261 /*if (dateFormatResult == null) {
264 long tenthOfSeconds = dateMillis % 1000/100L; //Extract 100 milliseconds
265 long base = dateMillis / 1000L * 1000L; //Cut milliseconds to 000
266 Date newDate = new Date( base + tenthOfSeconds);
267 return dateFormatResult.format(newDate);