Skip to content

Commit

Permalink
Merge pull request #422 from itbw/xsduration
Browse files Browse the repository at this point in the history
Fix: XSDuration in EWSUtilities (#357, #398, #343)
  • Loading branch information
serious6 committed Aug 30, 2015
2 parents 51990e8 + d3215be commit e43d06a
Show file tree
Hide file tree
Showing 3 changed files with 83 additions and 157 deletions.
167 changes: 11 additions & 156 deletions src/main/java/microsoft/exchange/webservices/data/core/EwsUtilities.java
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,11 @@
import microsoft.exchange.webservices.data.core.exception.service.local.ServiceVersionException;
import microsoft.exchange.webservices.data.misc.TimeSpan;
import microsoft.exchange.webservices.data.property.complex.ItemAttachment;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.joda.time.Period;
import org.joda.time.format.ISOPeriodFormat;

import javax.xml.stream.XMLOutputFactory;
import javax.xml.stream.XMLStreamException;
Expand Down Expand Up @@ -875,170 +878,22 @@ public static TimeSpan getXSDurationToTimeSpan(String xsDuration) {
negative = true;
}

// Year
m = PATTERN_YEAR.matcher(xsDuration);
int year = 0;
if (m.find()) {
year = Integer.parseInt(m.group().substring(0,
m.group().indexOf("Y")));
}

// Month
m = PATTERN_MONTH.matcher(xsDuration);
int month = 0;
if (m.find()) {
month = Integer.parseInt(m.group().substring(0,
m.group().indexOf("M")));
}

// Day
m = PATTERN_DAY.matcher(xsDuration);
int day = 0;
if (m.find()) {
day = Integer.parseInt(m.group().substring(0,
m.group().indexOf("D")));
}

// Hour
m = PATTERN_HOUR.matcher(xsDuration);
int hour = 0;
if (m.find()) {
hour = Integer.parseInt(m.group().substring(0,
m.group().indexOf("H")));
}

// Minute
m = PATTERN_MINUTES.matcher(xsDuration);
int minute = 0;
if (m.find()) {
minute = Integer.parseInt(m.group().substring(0,
m.group().indexOf("M")));
}

// Seconds
m = PATTERN_SECONDS.matcher(xsDuration);
int seconds = 0;
if (m.find()) {
seconds = Integer.parseInt(m.group().substring(0,
m.group().indexOf(".")));
}

int milliseconds = 0;
m = PATTERN_MILLISECONDS.matcher(xsDuration);
if (m.find()) {
// Only allowed 4 digits of precision
if (m.group().length() > 5) {
milliseconds = Integer.parseInt(m.group().substring(0, 4));
} else {
seconds = Integer.parseInt(m.group().substring(0,
m.group().indexOf("S")));
}
}

// Apply conversions of year and months to days.
// Year = 365 days
// Month = 30 days
day = day + (year * 365) + (month * 30);
// TimeSpan retval = new TimeSpan(day, hour, minute, seconds,
// milliseconds);
long retval = (((((((day * 24) + hour) * 60) + minute) * 60) +
seconds) * 1000) + milliseconds;
// Removing leading '-'
if (negative) {
retval = -retval;
}
return new TimeSpan(retval);

}

/**
* Takes an xs:duration string as defined by the W3 Consortiums
* Recommendation "XML Schema Part 2: Datatypes Second Edition",
* http://www.w3.org/TR/xmlschema-2/#duration, and converts it into a
* System.TimeSpan structure This method uses the following approximations:
* 1 year = 365 days 1 month = 30 days Additionally, it only allows for four
* decimal points of seconds precision.
*
* @param xsDuration xs:duration string to convert
* @return System.TimeSpan structure
*/
public static TimeSpan getXSDurationToTimeSpanValue(String xsDuration) {
// TODO: Need to check whether this should be the equivalent or not
Matcher m = PATTERN_TIME_SPAN.matcher(xsDuration);
boolean negative = false;
if (m.find()) {
negative = true;
}

// Year
// m = Pattern.compile("(\\d+)Y").matcher(xsDuration);
// int year = 0;
// if (m.find()) {
// year = Integer.parseInt(m.group().substring(0,
// m.group().indexOf("Y")));
// }

// Month
// m = Pattern.compile("(\\d+)M").matcher(xsDuration);
// int month = 0;
// if (m.find()) {
// month = Integer.parseInt(m.group().substring(0,
// m.group().indexOf("M")));
// }

// Day
m = PATTERN_DAY.matcher(xsDuration);
long day = 0;
if (m.find()) {
day = Integer.parseInt(m.group().substring(0,
m.group().indexOf("D")));
}

// Hour
m = PATTERN_HOUR.matcher(xsDuration);
int hour = 0;
if (m.find()) {
hour = Integer.parseInt(m.group().substring(0,
m.group().indexOf("H")));
}

// Minute
m = PATTERN_MINUTES.matcher(xsDuration);
int minute = 0;
if (m.find()) {
minute = Integer.parseInt(m.group().substring(0,
m.group().indexOf("M")));
}

// Seconds
m = PATTERN_SECONDS.matcher(xsDuration);
int seconds = 0;
int milliseconds = 0;
m = PATTERN_MILLISECONDS.matcher(xsDuration);
if (m.find()) {
// Only allowed 4 digits of precision
if (m.group().length() > 5) {
milliseconds = Integer.parseInt(m.group().substring(0, 4));
} else {
seconds = Integer.parseInt(m.group().substring(0, m.group().indexOf("S")));
}
xsDuration = xsDuration.replace("-P", "P");
}

// Apply conversions of year and months to days.
// Year = 365 days
// Month = 30 days
// day = day + (year * 365) + (month * 30);
//TimeSpan retval = new TimeSpan(day, hour, minute, seconds,
// milliseconds);

long retval =
day * TimeSpan.DAYS + hour * TimeSpan.HOURS + minute * TimeSpan.MINUTES + seconds * TimeSpan.SECONDS
+ milliseconds * TimeSpan.MILLISECONDS;
Period period = Period.parse(xsDuration, ISOPeriodFormat.standard());

long retval = period.toStandardDuration().getMillis();

if (negative) {
retval = -retval;
}

return new TimeSpan(retval);
}

}

/**
* Time span to xs time.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ public TimeSpanPropertyDefinition(String xmlElementName, String uri, EnumSet<Pro
*/
@Override
protected TimeSpan parse(String value) {
return EwsUtilities.getXSDurationToTimeSpanValue(value);
return EwsUtilities.getXSDurationToTimeSpan(value);
}

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
/*
* The MIT License Copyright (c) 2012 Microsoft Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
* associated documentation files (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge, publish, distribute,
* sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or
* substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
* NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/

package microsoft.exchange.webservices.data.core;

import microsoft.exchange.webservices.data.core.EwsUtilities;
import microsoft.exchange.webservices.data.misc.TimeSpan;

import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;

@RunWith(JUnit4.class)
public class XSDurationTest {

// Tests for EwsUtilities.getXSDurationToTimeSpan()

@Test
public void testPeriodHours() {
TimeSpan timeSpan = EwsUtilities.getXSDurationToTimeSpan("-PT13H");
Assert.assertEquals("-P0DT13H0M0.0S", EwsUtilities.getTimeSpanToXSDuration(timeSpan));
}

@Test
public void testPeriodHoursMinutes() {
TimeSpan timeSpan = EwsUtilities.getXSDurationToTimeSpan("-PT5H30M");
Assert.assertEquals("-P0DT5H30M0.0S", EwsUtilities.getTimeSpanToXSDuration(timeSpan));
}

@Test
public void testPeriodFull() {
TimeSpan timeSpan = EwsUtilities.getXSDurationToTimeSpan("PT2H30M59.0S");
Assert.assertEquals("P0DT2H30M59.0S", EwsUtilities.getTimeSpanToXSDuration(timeSpan));
}

@Test
public void testPeriodFullNegative() {
TimeSpan timeSpan = EwsUtilities.getXSDurationToTimeSpan("-PT2H30M59.0S");
Assert.assertEquals("-P0DT2H30M59.0S", EwsUtilities.getTimeSpanToXSDuration(timeSpan));
}

@Test
public void testPeriodFail2() {
TimeSpan timeSpan = EwsUtilities.getXSDurationToTimeSpan("PT2H100M59.0S");
Assert.assertEquals("P0DT3H40M59.0S", EwsUtilities.getTimeSpanToXSDuration(timeSpan));
}

@Test(expected = IllegalArgumentException.class)
public void testPeriodFail() {
TimeSpan timeSpan = EwsUtilities.getXSDurationToTimeSpan("P2H30M59.0S");
Assert.assertEquals("-P0DT2H30M59.0S", EwsUtilities.getTimeSpanToXSDuration(timeSpan));
}

}

0 comments on commit e43d06a

Please sign in to comment.