// This file is already in the mpxj distrib. it was copied here for easier debugging as its hard to debug the packaged code package com.projity.server.data.mspdi; import java.text.DecimalFormat; import java.text.DecimalFormatSymbols; /** * This class parses and represents an xsd:duration value. */ public final class XsdDuration { /** * Constructor. Parses the xsd:duration value and extracts the duration data * from it. * * @param duration * value formatted as an xsd:duration */ XsdDuration(String duration) { if (duration != null) { int length = duration.length(); if (length > 0) { if (duration.charAt(0) != 'P') { if (length < 2 || (duration.charAt(0) != '-' && duration.charAt(1) != 'P')) { throw new IllegalArgumentException(duration); } } int index; boolean negative; if (duration.charAt(0) == '-') { index = 2; negative = true; } else { index = 1; negative = false; } while (index < length) { index = readComponent(duration, index, length); } if (negative == true) { m_years = -m_years; m_months = -m_months; m_days = -m_days; m_hours = -m_hours; m_minutes = -m_minutes; m_seconds = -m_seconds; } } } } /** * This constructor allows an xsd:duration to be created from an MPX * duration. * * @param duration * An MPX duration. */ public XsdDuration(net.sf.mpxj.Duration duration) { if (duration != null) { double amount = duration.getDuration(); if (amount != 0) { switch (duration.getUnits()) { //claur mpxj now using enum case MINUTES: case ELAPSED_MINUTES: { m_minutes = (int) amount; m_seconds = (amount * 60) - (m_minutes * 60); break; } case HOURS: case ELAPSED_HOURS: { m_hours = (int) amount; amount = (amount * 60) - (m_hours * 60); m_minutes = (int) amount; m_seconds = (amount * 60) - (m_minutes * 60); break; } case DAYS: case ELAPSED_DAYS: { m_days = (int) amount; amount = (amount * 24) - (m_days * 24); m_hours = (int) amount; amount = (amount * 60) - (m_hours * 60); m_minutes = (int) amount; m_seconds = (amount * 60) - (m_minutes * 60); break; } case WEEKS: case ELAPSED_WEEKS: { amount *= 7; m_days = (int) amount; amount = (amount * 24) - (m_days * 24); m_hours = (int) amount; amount = (amount * 60) - (m_hours * 60); m_minutes = (int) amount; m_seconds = (amount * 60) - (m_minutes * 60); break; } case MONTHS: case ELAPSED_MONTHS: { m_months = (int) amount; amount = (amount * 28) - (m_months * 28); m_days = (int) amount; amount = (amount * 24) - (m_days * 24); m_hours = (int) amount; amount = (amount * 60) - (m_hours * 60); m_minutes = (int) amount; m_seconds = (amount * 60) - (m_minutes * 60); break; } case YEARS: case ELAPSED_YEARS: { m_years = (int) amount; amount = (amount * 12) - (m_years * 12); m_months = (int) amount; amount = (amount * 28) - (m_months * 28); m_days = (int) amount; amount = (amount * 24) - (m_days * 24); m_hours = (int) amount; amount = (amount * 60) - (m_hours * 60); m_minutes = (int) amount; m_seconds = (amount * 60) - (m_minutes * 60); break; } } } } } /** * Convert from a string xsd duration value to a number of milliseconds * @param s * @return */ public static long millis(String s) { // most of the time, the value is either 8 hours or 0 hours, so treat these specially for speed if (s == null || s.equals("0") || s.equals("PT0H0M0S")) return 0L; if (s.equals("PT8H0M0S")) return 8*60*60*1000L; return new XsdDuration(s).getMillis(); } /** * This method is called repeatedly to parse each duration component from * srting data in xsd:duration format. Each component consists of a number, * followed by a letter representing the type. * * @param duration * xsd:duration formatted string * @param index * current position in the string * @param length * length of string * @return current position in the string */ private int readComponent2(String duration, int index, int length) { char c = 0; StringBuffer number = new StringBuffer(); while (index < length) { c = duration.charAt(index); if (Character.isDigit(c) == true || c == '.') { number.append(c); } else { break; } ++index; } switch (c) { case 'Y': { m_years = Integer.parseInt(number.toString()); break; } case 'M': { if (m_hasTime == false) { m_months = Integer.parseInt(number.toString()); } else { m_minutes = Integer.parseInt(number.toString()); } break; } case 'D': { m_days = Integer.parseInt(number.toString()); break; } case 'T': { m_hasTime = true; break; } case 'H': { m_hours = Integer.parseInt(number.toString()); break; } case 'S': { m_seconds = Double.parseDouble(number.toString()); break; } default: { throw new IllegalArgumentException(duration); } } ++index; return (index); } /** * Retrieves the number of days. * * @return int */ public int getDays() { return (m_days); } /** * Retrieves the number of hours. * * @return int */ public int getHours() { return (m_hours); } /** * Retrieves the number of minutes. * * @return int */ public int getMinutes() { return (m_minutes); } /** * Retrieves the number of months. * * @return int */ public int getMonths() { return (m_months); } /** * Retrieves the number of seconds. * * @return double */ public double getSeconds() { return (m_seconds); } /** * Retrieves the number of years. * * @return int */ public int getYears() { return (m_years); } /** * This method generates the string representation of an xsd:duration value. * * @return xsd:duration value */ public String toString() { StringBuffer buffer = new StringBuffer("P"); boolean negative = false; if (m_years != 0 || m_months != 0 || m_days != 0) { if (m_years < 0) { negative = true; buffer.append(-m_years); } else { buffer.append(m_years); } buffer.append("Y"); if (m_months < 0) { negative = true; buffer.append(-m_months); } else { buffer.append(m_months); } buffer.append("M"); if (m_days < 0) { negative = true; buffer.append(-m_days); } else { buffer.append(m_days); } buffer.append("D"); } buffer.append("T"); if (m_hours < 0) { negative = true; buffer.append(-m_hours); } else { buffer.append(m_hours); } buffer.append("H"); if (m_minutes < 0) { negative = true; buffer.append(-m_minutes); } else { buffer.append(m_minutes); } buffer.append("M"); if (m_seconds < 0) { negative = true; buffer.append(FORMAT.format(-m_seconds)); } else { buffer.append(FORMAT.format(m_seconds)); } buffer.append("S"); if (negative == true) { buffer.insert(0, '-'); } return (buffer.toString()); } private boolean m_hasTime; private int m_years; private int m_months; private int m_days; private int m_hours; private int m_minutes; private double m_seconds; public long getMillis() { return 1000L * ((long) m_seconds + 60L * (m_minutes + 60L * (m_hours + 24L * (m_days + (28L * m_months + 365L * m_years) )))); } /** * Configure the decimal separator to be independent of the one used by the * default locale. */ private static final DecimalFormatSymbols SYMBOLS = new DecimalFormatSymbols(); static { SYMBOLS.setDecimalSeparator('.'); } private static final DecimalFormat FORMAT = new DecimalFormat("#", SYMBOLS); private int readComponent (String duration, int index, int length) { char c = 0; StringBuffer number = new StringBuffer (); // System.out.println("read componenent " + duration); // if (duration.contains(".")) // System.out.println("dot"); while (index < length) { c = duration.charAt(index); if (Character.isDigit(c) == true || c == '.') { number.append (c); } else { break; } ++index; } switch (c) { case 'Y': { // projity m_years = (int) Math.floor(Double.parseDouble(number.toString())); // projity commented m_years = Integer.parseInt(number.toString()); break; } case 'M': { if (m_hasTime == false) { // projity m_months = (int) Math.floor(Double.parseDouble(number.toString())); // projity commented m_months = Integer.parseInt(number.toString()); } else { // projity m_minutes += Math.floor(Double.parseDouble(number.toString())); // projity commented m_minutes = Integer.parseInt(number.toString()); } break; } case 'D': { // projity m_days = (int) Math.floor(Double.parseDouble(number.toString())); // projity commented m_days = Integer.parseInt(number.toString()); break; } case 'T': { m_hasTime = true; break; } case 'H': { // Projity double h = Double.parseDouble(number.toString()); if (Math.round(h) != h) { m_hours = (int) Math.floor(h); double min = (h - m_hours) * 60; m_minutes += (int) Math.floor(min); double sec = (min - m_minutes) * 60; m_seconds += Math.round(sec); } else { m_hours = (int) h; } // projity commented m_hours = Integer.parseInt(number.toString()); break; } case 'S': { //projity m_seconds += Double.parseDouble(number.toString()); // projity commented m_seconds = Double.parseDouble(number.toString()); break; } default: { throw new IllegalArgumentException (duration); } } ++index; return (index); } }