Skip to content

Commit e43d06a

Browse files
committed
Merge pull request OfficeDev#422 from itbw/xsduration
Fix: XSDuration in EWSUtilities (OfficeDev#357, OfficeDev#398, OfficeDev#343)
2 parents 51990e8 + d3215be commit e43d06a

3 files changed

Lines changed: 83 additions & 157 deletions

File tree

src/main/java/microsoft/exchange/webservices/data/core/EwsUtilities.java

Lines changed: 11 additions & 156 deletions
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,11 @@
5050
import microsoft.exchange.webservices.data.core.exception.service.local.ServiceVersionException;
5151
import microsoft.exchange.webservices.data.misc.TimeSpan;
5252
import microsoft.exchange.webservices.data.property.complex.ItemAttachment;
53+
5354
import org.apache.commons.logging.Log;
5455
import org.apache.commons.logging.LogFactory;
56+
import org.joda.time.Period;
57+
import org.joda.time.format.ISOPeriodFormat;
5558

5659
import javax.xml.stream.XMLOutputFactory;
5760
import javax.xml.stream.XMLStreamException;
@@ -875,170 +878,22 @@ public static TimeSpan getXSDurationToTimeSpan(String xsDuration) {
875878
negative = true;
876879
}
877880

878-
// Year
879-
m = PATTERN_YEAR.matcher(xsDuration);
880-
int year = 0;
881-
if (m.find()) {
882-
year = Integer.parseInt(m.group().substring(0,
883-
m.group().indexOf("Y")));
884-
}
885-
886-
// Month
887-
m = PATTERN_MONTH.matcher(xsDuration);
888-
int month = 0;
889-
if (m.find()) {
890-
month = Integer.parseInt(m.group().substring(0,
891-
m.group().indexOf("M")));
892-
}
893-
894-
// Day
895-
m = PATTERN_DAY.matcher(xsDuration);
896-
int day = 0;
897-
if (m.find()) {
898-
day = Integer.parseInt(m.group().substring(0,
899-
m.group().indexOf("D")));
900-
}
901-
902-
// Hour
903-
m = PATTERN_HOUR.matcher(xsDuration);
904-
int hour = 0;
905-
if (m.find()) {
906-
hour = Integer.parseInt(m.group().substring(0,
907-
m.group().indexOf("H")));
908-
}
909-
910-
// Minute
911-
m = PATTERN_MINUTES.matcher(xsDuration);
912-
int minute = 0;
913-
if (m.find()) {
914-
minute = Integer.parseInt(m.group().substring(0,
915-
m.group().indexOf("M")));
916-
}
917-
918-
// Seconds
919-
m = PATTERN_SECONDS.matcher(xsDuration);
920-
int seconds = 0;
921-
if (m.find()) {
922-
seconds = Integer.parseInt(m.group().substring(0,
923-
m.group().indexOf(".")));
924-
}
925-
926-
int milliseconds = 0;
927-
m = PATTERN_MILLISECONDS.matcher(xsDuration);
928-
if (m.find()) {
929-
// Only allowed 4 digits of precision
930-
if (m.group().length() > 5) {
931-
milliseconds = Integer.parseInt(m.group().substring(0, 4));
932-
} else {
933-
seconds = Integer.parseInt(m.group().substring(0,
934-
m.group().indexOf("S")));
935-
}
936-
}
937-
938-
// Apply conversions of year and months to days.
939-
// Year = 365 days
940-
// Month = 30 days
941-
day = day + (year * 365) + (month * 30);
942-
// TimeSpan retval = new TimeSpan(day, hour, minute, seconds,
943-
// milliseconds);
944-
long retval = (((((((day * 24) + hour) * 60) + minute) * 60) +
945-
seconds) * 1000) + milliseconds;
881+
// Removing leading '-'
946882
if (negative) {
947-
retval = -retval;
948-
}
949-
return new TimeSpan(retval);
950-
951-
}
952-
953-
/**
954-
* Takes an xs:duration string as defined by the W3 Consortiums
955-
* Recommendation "XML Schema Part 2: Datatypes Second Edition",
956-
* http://www.w3.org/TR/xmlschema-2/#duration, and converts it into a
957-
* System.TimeSpan structure This method uses the following approximations:
958-
* 1 year = 365 days 1 month = 30 days Additionally, it only allows for four
959-
* decimal points of seconds precision.
960-
*
961-
* @param xsDuration xs:duration string to convert
962-
* @return System.TimeSpan structure
963-
*/
964-
public static TimeSpan getXSDurationToTimeSpanValue(String xsDuration) {
965-
// TODO: Need to check whether this should be the equivalent or not
966-
Matcher m = PATTERN_TIME_SPAN.matcher(xsDuration);
967-
boolean negative = false;
968-
if (m.find()) {
969-
negative = true;
970-
}
971-
972-
// Year
973-
// m = Pattern.compile("(\\d+)Y").matcher(xsDuration);
974-
// int year = 0;
975-
// if (m.find()) {
976-
// year = Integer.parseInt(m.group().substring(0,
977-
// m.group().indexOf("Y")));
978-
// }
979-
980-
// Month
981-
// m = Pattern.compile("(\\d+)M").matcher(xsDuration);
982-
// int month = 0;
983-
// if (m.find()) {
984-
// month = Integer.parseInt(m.group().substring(0,
985-
// m.group().indexOf("M")));
986-
// }
987-
988-
// Day
989-
m = PATTERN_DAY.matcher(xsDuration);
990-
long day = 0;
991-
if (m.find()) {
992-
day = Integer.parseInt(m.group().substring(0,
993-
m.group().indexOf("D")));
994-
}
995-
996-
// Hour
997-
m = PATTERN_HOUR.matcher(xsDuration);
998-
int hour = 0;
999-
if (m.find()) {
1000-
hour = Integer.parseInt(m.group().substring(0,
1001-
m.group().indexOf("H")));
1002-
}
1003-
1004-
// Minute
1005-
m = PATTERN_MINUTES.matcher(xsDuration);
1006-
int minute = 0;
1007-
if (m.find()) {
1008-
minute = Integer.parseInt(m.group().substring(0,
1009-
m.group().indexOf("M")));
1010-
}
1011-
1012-
// Seconds
1013-
m = PATTERN_SECONDS.matcher(xsDuration);
1014-
int seconds = 0;
1015-
int milliseconds = 0;
1016-
m = PATTERN_MILLISECONDS.matcher(xsDuration);
1017-
if (m.find()) {
1018-
// Only allowed 4 digits of precision
1019-
if (m.group().length() > 5) {
1020-
milliseconds = Integer.parseInt(m.group().substring(0, 4));
1021-
} else {
1022-
seconds = Integer.parseInt(m.group().substring(0, m.group().indexOf("S")));
1023-
}
883+
xsDuration = xsDuration.replace("-P", "P");
1024884
}
1025885

1026-
// Apply conversions of year and months to days.
1027-
// Year = 365 days
1028-
// Month = 30 days
1029-
// day = day + (year * 365) + (month * 30);
1030-
//TimeSpan retval = new TimeSpan(day, hour, minute, seconds,
1031-
// milliseconds);
1032-
1033-
long retval =
1034-
day * TimeSpan.DAYS + hour * TimeSpan.HOURS + minute * TimeSpan.MINUTES + seconds * TimeSpan.SECONDS
1035-
+ milliseconds * TimeSpan.MILLISECONDS;
886+
Period period = Period.parse(xsDuration, ISOPeriodFormat.standard());
887+
888+
long retval = period.toStandardDuration().getMillis();
889+
1036890
if (negative) {
1037891
retval = -retval;
1038892
}
893+
1039894
return new TimeSpan(retval);
1040-
}
1041895

896+
}
1042897

1043898
/**
1044899
* Time span to xs time.

src/main/java/microsoft/exchange/webservices/data/property/definition/TimeSpanPropertyDefinition.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ public TimeSpanPropertyDefinition(String xmlElementName, String uri, EnumSet<Pro
5757
*/
5858
@Override
5959
protected TimeSpan parse(String value) {
60-
return EwsUtilities.getXSDurationToTimeSpanValue(value);
60+
return EwsUtilities.getXSDurationToTimeSpan(value);
6161
}
6262

6363
/**
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
/*
2+
* The MIT License Copyright (c) 2012 Microsoft Corporation
3+
*
4+
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
5+
* associated documentation files (the "Software"), to deal in the Software without restriction,
6+
* including without limitation the rights to use, copy, modify, merge, publish, distribute,
7+
* sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
8+
* furnished to do so, subject to the following conditions:
9+
*
10+
* The above copyright notice and this permission notice shall be included in all copies or
11+
* substantial portions of the Software.
12+
*
13+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
14+
* NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
15+
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
16+
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
17+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
18+
*/
19+
20+
package microsoft.exchange.webservices.data.core;
21+
22+
import microsoft.exchange.webservices.data.core.EwsUtilities;
23+
import microsoft.exchange.webservices.data.misc.TimeSpan;
24+
25+
import org.junit.Assert;
26+
import org.junit.Test;
27+
import org.junit.runner.RunWith;
28+
import org.junit.runners.JUnit4;
29+
30+
@RunWith(JUnit4.class)
31+
public class XSDurationTest {
32+
33+
// Tests for EwsUtilities.getXSDurationToTimeSpan()
34+
35+
@Test
36+
public void testPeriodHours() {
37+
TimeSpan timeSpan = EwsUtilities.getXSDurationToTimeSpan("-PT13H");
38+
Assert.assertEquals("-P0DT13H0M0.0S", EwsUtilities.getTimeSpanToXSDuration(timeSpan));
39+
}
40+
41+
@Test
42+
public void testPeriodHoursMinutes() {
43+
TimeSpan timeSpan = EwsUtilities.getXSDurationToTimeSpan("-PT5H30M");
44+
Assert.assertEquals("-P0DT5H30M0.0S", EwsUtilities.getTimeSpanToXSDuration(timeSpan));
45+
}
46+
47+
@Test
48+
public void testPeriodFull() {
49+
TimeSpan timeSpan = EwsUtilities.getXSDurationToTimeSpan("PT2H30M59.0S");
50+
Assert.assertEquals("P0DT2H30M59.0S", EwsUtilities.getTimeSpanToXSDuration(timeSpan));
51+
}
52+
53+
@Test
54+
public void testPeriodFullNegative() {
55+
TimeSpan timeSpan = EwsUtilities.getXSDurationToTimeSpan("-PT2H30M59.0S");
56+
Assert.assertEquals("-P0DT2H30M59.0S", EwsUtilities.getTimeSpanToXSDuration(timeSpan));
57+
}
58+
59+
@Test
60+
public void testPeriodFail2() {
61+
TimeSpan timeSpan = EwsUtilities.getXSDurationToTimeSpan("PT2H100M59.0S");
62+
Assert.assertEquals("P0DT3H40M59.0S", EwsUtilities.getTimeSpanToXSDuration(timeSpan));
63+
}
64+
65+
@Test(expected = IllegalArgumentException.class)
66+
public void testPeriodFail() {
67+
TimeSpan timeSpan = EwsUtilities.getXSDurationToTimeSpan("P2H30M59.0S");
68+
Assert.assertEquals("-P0DT2H30M59.0S", EwsUtilities.getTimeSpanToXSDuration(timeSpan));
69+
}
70+
71+
}

0 commit comments

Comments
 (0)