blob: fe76963887fc52024a987f97f86657d9cf2e3c7d [file] [log] [blame]
/**********************************************************************
* Copyright (c) 2017 Ericsson
*
* All rights reserved. This program and the accompanying materials are
* made available under the terms of the Eclipse Public License 2.0 which
* accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
**********************************************************************/
package org.eclipse.tracecompass.tmf.ui.views;
import java.text.NumberFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.TimeZone;
import java.util.concurrent.TimeUnit;
import org.eclipse.tracecompass.common.core.format.DecimalUnitFormat;
import org.eclipse.tracecompass.common.core.format.LongToPercentFormat;
import org.eclipse.tracecompass.internal.tmf.ui.Messages;
import org.eclipse.tracecompass.tmf.core.timestamp.TmfTimePreferences;
/**
* Format time to be used in different views.
*
* @author Simon Delisle
* @since 3.3
*/
public final class FormatTimeUtils {
private FormatTimeUtils() {
// do nothing
}
/** Time format for dates and timestamp */
public enum TimeFormat {
/** Relative to the start of the trace */
RELATIVE,
/**
* Absolute timestamp (ie, relative to the Unix epoch)
*/
CALENDAR,
/**
* Timestamp displayed as a simple number
*/
NUMBER,
/**
* Timestamp displayed as cycles
*/
CYCLES,
/**
* Value displayed as percentage
* @since 4.0
*/
PERCENTAGE
}
/**
* Timestamp resolution
*/
public enum Resolution {
/** seconds */
SECONDS,
/** milliseconds */
MILLISEC,
/** microseconds */
MICROSEC,
/** nanoseconds */
NANOSEC
}
private static final SimpleDateFormat TIME_FORMAT = new SimpleDateFormat("HH:mm:ss"); //$NON-NLS-1$
private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd"); //$NON-NLS-1$
private static final long HOURS_PER_DAY = 24;
private static final long MIN_PER_HOUR = 60;
private static final long SEC_PER_MIN = 60;
private static final long SEC_IN_NS = 1000000000;
private static final long MILLISEC_IN_NS = 1000000;
/**
* Update the time and date formats to use the current time zone
*/
public static void updateTimeZone() {
TimeZone timeZone = TmfTimePreferences.getTimeZone();
TIME_FORMAT.setTimeZone(timeZone);
DATE_FORMAT.setTimeZone(timeZone);
}
/**
* Formats time in format: MM:SS:NNN
*
* @param time
* time
* @param format
* 0: MMMM:ss:nnnnnnnnn, 1: HH:MM:ss MMM.mmmm.nnn
* @param resolution
* the resolution
* @return the formatted time
*/
public static String formatTime(long time, TimeFormat format, Resolution resolution) {
switch (format) {
case CALENDAR:
return formatTimeAbs(time, resolution);
case NUMBER:
return NumberFormat.getInstance().format(time);
case CYCLES:
return NumberFormat.getInstance().format(time) + Messages.Utils_ClockCyclesUnit;
case RELATIVE:
return formatTimeRelative(time, resolution);
case PERCENTAGE:
return LongToPercentFormat.getInstance().format(time);
default:
}
StringBuilder str = new StringBuilder();
long t = time;
boolean neg = t < 0;
if (neg) {
t = -t;
str.append('-');
}
long sec = t / SEC_IN_NS;
str.append(sec);
String ns = formatNs(t, resolution);
if (!ns.isEmpty()) {
str.append('.');
str.append(ns);
}
return str.toString();
}
/**
* From input time in nanoseconds, convert to Date format YYYY-MM-dd
*
* @param absTime
* The source time, in ns
* @return the formatted date
*/
public static String formatDate(long absTime) {
return DATE_FORMAT.format(new Date(absTime / MILLISEC_IN_NS));
}
/**
* Formats time in ns to Calendar format: HH:MM:SS MMM.mmm.nnn
*
* @param time
* The source time, in ns
* @param res
* The resolution to use
* @return the formatted time
*/
public static String formatTimeAbs(long time, Resolution res) {
// format time from nanoseconds to calendar time HH:MM:SS
String stime = TIME_FORMAT.format(new Date(time / MILLISEC_IN_NS));
StringBuilder str = new StringBuilder(stime);
String ns = formatNs(time, res);
if (!ns.isEmpty()) {
str.append('.');
/*
* append the Milliseconds, MicroSeconds and NanoSeconds as specified in the
* Resolution
*/
str.append(ns);
}
return str.toString();
}
/**
* Formats time delta
*
* @param delta
* The time delta, in ns
* @param format
* The time format to use
* @param resolution
* The resolution to use
* @return the formatted time delta
*/
public static String formatDelta(long delta, TimeFormat format, Resolution resolution) {
if (format == TimeFormat.CALENDAR) {
return formatDeltaAbs(delta, resolution);
}
return formatTime(delta, format, resolution);
}
/**
* Formats relative time to second
*
* @param time
* The relative time in ns
* @param resolution
* The resolution to use
* @return The formatted time in second
*/
private static String formatTimeRelative(long time, Resolution resolution) {
StringBuilder str = new StringBuilder();
if (time < 0) {
str.append('-');
}
long ns = Math.abs(time);
long seconds = TimeUnit.NANOSECONDS.toSeconds(ns);
str.append(seconds);
str.append('.');
// append the ms, us and ns as specified in the resolution
str.append(formatNs(time, resolution));
str.append('s');
if (seconds == 0) {
str.append(" ("); //$NON-NLS-1$
str.append(new DecimalUnitFormat(1.0 / SEC_IN_NS).format(time));
str.append("s)"); //$NON-NLS-1$
}
return str.toString();
}
/**
* Formats time delta in ns to Calendar format, only formatting the years, days,
* hours or minutes if necessary.
*
* @param delta
* The time delta, in ns
* @param resolution
* The resolution to use
* @return the formatted time delta
*/
public static String formatDeltaAbs(long delta, Resolution resolution) {
StringBuilder str = new StringBuilder();
if (delta < 0) {
str.append('-');
}
long ns = Math.abs(delta);
long seconds = TimeUnit.NANOSECONDS.toSeconds(ns);
long minutes = TimeUnit.NANOSECONDS.toMinutes(ns);
long hours = TimeUnit.NANOSECONDS.toHours(ns);
long days = TimeUnit.NANOSECONDS.toDays(ns);
if (days > 0) {
str.append(days);
str.append("d "); //$NON-NLS-1$
}
if (hours > 0) {
str.append(hours % HOURS_PER_DAY);
str.append("h "); //$NON-NLS-1$
}
if (minutes > 0) {
str.append(minutes % MIN_PER_HOUR);
str.append("m "); //$NON-NLS-1$
}
str.append(seconds % SEC_PER_MIN);
str.append('.');
// append the ms, us and ns as specified in the resolution
str.append(formatNs(delta, resolution));
str.append("s"); //$NON-NLS-1$
if (seconds == 0) {
str.append(" ("); //$NON-NLS-1$
str.append(new DecimalUnitFormat(1.0 / SEC_IN_NS).format(delta));
str.append("s)"); //$NON-NLS-1$
}
return str.toString();
}
/**
* Obtains the remainder fraction on unit Seconds of the entered value in
* nanoseconds. e.g. input: 1241207054171080214 ns The number of fraction
* seconds can be obtained by removing the last 9 digits: 1241207054 the
* fractional portion of seconds, expressed in ns is: 171080214
*
* @param srcTime
* The source time in ns
* @param res
* The Resolution to use
* @return the formatted nanosec
*/
public static String formatNs(long srcTime, Resolution res) {
StringBuilder str = new StringBuilder();
long ns = Math.abs(srcTime % SEC_IN_NS);
String nanos = Long.toString(ns);
str.append("000000000".substring(nanos.length())); //$NON-NLS-1$
str.append(nanos);
if (res == Resolution.MILLISEC) {
return str.substring(0, 3);
} else if (res == Resolution.MICROSEC) {
return str.substring(0, 6);
} else if (res == Resolution.NANOSEC) {
return str.substring(0, 9);
}
return ""; //$NON-NLS-1$
}
}