//
-// System.Runtime.Remoting.Metadata.W3cXsd2001.SoapDuration
+// System.Runtime.Remoting.Metadata.W3cXsd2001.SoapDuration.cs
//
// Authors:
// Martin Willemoes Hansen (mwh@sysrq.dk)
using System;
using System.Text;
+using System.Globalization;
namespace System.Runtime.Remoting.Metadata.W3cXsd2001
{
+ [System.Runtime.InteropServices.ComVisible (true)]
public sealed class SoapDuration
{
public SoapDuration()
get { return "duration"; }
}
- public static TimeSpan Parse (string s)
+ public static TimeSpan Parse (string value)
{
- if (s.Length == 0)
+ if (value.Length == 0)
throw new ArgumentException ("Invalid format string for duration schema datatype.");
int start = 0;
- if (s [0] == '-')
+ if (value [0] == '-')
start = 1;
bool minusValue = (start == 1);
- if (s [start] != 'P')
+ if (value [start] != 'P')
throw new ArgumentException ("Invalid format string for duration schema datatype.");
start++;
bool isTime = false;
int hours = 0;
int minutes = 0;
- int seconds = 0;
+ double seconds = 0;
bool error = false;
int i = start;
- while (i < s.Length) {
- if (s [i] == 'T') {
+ while (i < value.Length) {
+ if (value [i] == 'T') {
isTime = true;
parseStep = 4;
i++;
start = i;
continue;
}
- for (; i < s.Length; i++) {
- if (!Char.IsDigit (s [i]))
- break;
+ bool isIntegerValue = true;
+ int dotOccurence = 0;
+ for (; i < value.Length; i++)
+ {
+ if (!Char.IsDigit (value [i]))
+ {
+ //check if it is a non integer value.
+ if (value[i] == '.')
+ {
+ isIntegerValue = false;
+ dotOccurence++;
+ //if there is more than one dot in the number
+ //than its an error
+ if (dotOccurence > 1 )
+ {
+ error = true;
+ break;
+ }
+ }
+ else
+ break;
+ }
}
- int value = int.Parse (s.Substring (start, i - start));
- switch (s [i]) {
+
+ int intValue = -1;
+ double doubleValue = -1;
+ if (isIntegerValue)
+ intValue = int.Parse (value.Substring (start, i - start));
+ else
+ doubleValue = double.Parse (value.Substring (start, i - start), CultureInfo.InvariantCulture);
+ switch (value [i]) {
case 'Y':
- days += value * 365;
- if (parseStep > 0)
+ days += intValue * 365;
+ if (parseStep > 0 || !isIntegerValue)
error = true;
else
parseStep = 1;
break;
case 'M':
- if (parseStep < 2) {
- days += 365 * (value / 12) + 30 * (value % 12);
+ if (parseStep < 2 && isIntegerValue) {
+ days += 365 * (intValue / 12) + 30 * (intValue % 12);
parseStep = 2;
- } else if (isTime && parseStep < 6) {
- minutes = value;
+ } else if (isTime && parseStep < 6 && isIntegerValue) {
+ minutes = intValue;
parseStep = 6;
}
else
error = true;
break;
case 'D':
- days += value;
- if (parseStep > 2)
+ days += intValue;
+ if (parseStep > 2 || !isIntegerValue)
error = true;
else
parseStep = 3;
break;
case 'H':
- hours = value;
- if (!isTime || parseStep > 4)
+ hours = intValue;
+ if (!isTime || parseStep > 4 || !isIntegerValue)
error = true;
else
parseStep = 5;
break;
case 'S':
- seconds = value;
+ if (isIntegerValue)
+ seconds = intValue;
+ else
+ seconds = doubleValue;
if (!isTime || parseStep > 6)
error = true;
else
}
if (error)
throw new ArgumentException ("Invalid format string for duration schema datatype.");
- TimeSpan ts = new TimeSpan (days, hours, minutes, seconds);
+ TimeSpan ts = new TimeSpan (days, hours, minutes, 0) + TimeSpan.FromSeconds (seconds);
return minusValue ? -ts : ts;
}
- public static string ToString (TimeSpan value)
+ public static string ToString (TimeSpan timeSpan)
{
StringBuilder builder = new StringBuilder();
- if (value.Ticks < 0) {
+ if (timeSpan.Ticks < 0) {
builder.Append('-');
- value = value.Negate();
+ timeSpan = timeSpan.Negate();
}
builder.Append('P');
- if (value.Days > 0) builder.Append(value.Days).Append('D');
- if (value.Days > 0 || value.Minutes > 0 || value.Seconds > 0 || value.Milliseconds > 0) {
+ if (timeSpan.Days > 0) builder.Append(timeSpan.Days).Append('D');
+ if (timeSpan.Days > 0 || timeSpan.Minutes > 0 || timeSpan.Seconds > 0 || timeSpan.Milliseconds > 0) {
builder.Append('T');
- if (value.Hours > 0) builder.Append(value.Hours).Append('D');
- if (value.Minutes > 0) builder.Append(value.Minutes).Append('M');
- if (value.Seconds > 0 || value.Milliseconds > 0) {
- builder.Append(value.Seconds);
- if (value.Milliseconds > 0) builder.Append('.').Append(String.Format("{0:000}", value.Milliseconds));
+ if (timeSpan.Hours > 0) builder.Append(timeSpan.Hours).Append('H');
+ if (timeSpan.Minutes > 0) builder.Append(timeSpan.Minutes).Append('M');
+ if (timeSpan.Seconds > 0 || timeSpan.Milliseconds > 0) {
+ double secs = (double) timeSpan.Seconds;
+ if (timeSpan.Milliseconds > 0)
+ secs += ((double)timeSpan.Milliseconds) / 1000.0;
+ builder.Append(String.Format(CultureInfo.InvariantCulture, "{0:0.0000000}", secs));
builder.Append('S');
}
}