anchor.diff:    inc(result.year);
   end;
   
  +function vsv(value : String; start, len, min, max : Integer; name : String):Integer;
  +var
  +  v : String;
  +begin
  +  v := copy(value, start, len);
  +  if not StringIsInteger16(v) then
  +    exit(-1);
  +  result := StrToInt(v);
  +  if (result < min) or (result > max) then
  +    exit(-1);
  +end;
  +
  +class function TDateTimeEx.isValidXmlDate(value: String): Boolean;
  +var
  +  s : String;
  +  neg : boolean;
  +  res : TDateTimeEx;
  +begin
  +  if value = '' then
  +    exit(false);
  +
  +  res.Source := Value;
  +  if pos('Z', value) = length(value) then
  +  begin
  +    res.TimezoneType := dttzUTC;
  +    Delete(value, length(value), 1);
  +  end
  +  else if (pos('T', value) > 0) and StringContainsAny(copy(Value, pos('T', value)+1, $FF), ['-', '+']) then
  +  begin
  +    neg := Pos('-', copy(Value, pos('T', value)+1, $FF)) > 0;
  +    StringSplitRight(value, ['-', '+'], value, s);
  +    if length(s) <> 5 then
  +      raise Exception.create('Unable to parse date/time "'+value+'": timezone is illegal length - must be 5');
  +    res.TimezoneHours := vsv(s, 1, 2, 0, 14, 'timezone hours');
  +    res.TimezoneMins := vsv(s, 4, 2, 0, 59, 'timezone minutes');
  +    res.TimezoneType := dttzSpecified;
  +    if neg then
  +      res.TimezoneHours := -res.TimezoneHours;
  +  end;
  +
  +  res.FractionPrecision := 0;
  +
  +  if Length(value) >=4 then
  +    res.Year := vsv(Value, 1, 4, 1800, 2100, 'years');
  +  if Length(value) < 7 then
  +    res.FPrecision := dtpYear
  +  else
  +  begin
  +    res.Month := vsv(Value, 6, 2, 1, 12, 'months');
  +    if length(Value) < 10 then
  +      res.FPrecision := dtpMonth
  +    else
  +    begin
  +      res.Day := vsv(Value, 9, 2, 1, 31, 'days');
  +      if length(Value) < 13 then
  +        res.FPrecision := dtpDay
  +      else
  +      begin
  +        res.Hour := vsv(Value, 12, 2, 0, 23, 'hours');
  +        if length(Value) < 15 then
  +          res.FPrecision := dtpHour
  +        else
  +        begin
  +          res.Minute := vsv(Value, 15, 2, 0, 59, 'minutes');
  +          if length(Value) < 18 then
  +            res.FPrecision := dtpMin
  +          else
  +          begin
  +            res.Second := vsv(Value, 18, 2, 0, 59, 'seconds');
  +            if length(Value) <= 20 then
  +              res.FPrecision := dtpSec
  +            else
  +            begin
  +              s := copy(Value, 21, 6);
  +              res.FractionPrecision := length(s);
  +              res.fraction := trunc(vsv(Value, 21, 4, 0, 999999, 'fractions') * power(10, 9 - res.FractionPrecision));
  +              res.FPrecision := dtpNanoSeconds;
  +            end;
  +          end;
  +        end;
  +      end;
  +    end;
  +  end;
  +  result := res.checkNoException;
  +end;
  +
  +function TDateTimeEx.lessPrecision: TDateTimeEx;
  +begin
  +  result := self;
  +  if result.FPrecision > dtpYear then
  +    result.FPrecision := pred(result.FPrecision);
  +  result.RollUp;
  +end;
  +
   function TDateTimeEx.IncrementWeek : TDateTimeEx;
   var
     i: Integer;
  
positive.code:   result := StrToInt(v);
    if (result < min) or (result > max) then
      raise exception.create('Value for '+name+' in date/time "'+value+'" is not allowed');
  
  end;
  
  
  
negative.code:   result.Fraction := fraction;
  end;
  
  function TDateTimeEx.after(other : TDateTimeEx; inclusive : boolean) : boolean;
  var
    uSelf, uOther : TDateTimeEx;
  begin
    uSelf := UTC;
    uOther := other.UTC;
    if uSelf.equal(uOther) then
      exit(inclusive);
    result := (uSelf.year >= uOther.year) and (uSelf.month >= uOther.month) and (uSelf.day >= uOther.day) and
              (uSelf.hour >= uOther.hour) and (uSelf.minute >= uOther.minute) and (uSelf.second >= uOther.second) and (uSelf.fraction >= uOther.fraction);
  end;
  
  function TDateTimeEx.before(other : TDateTimeEx; inclusive : boolean):boolean;
  var
    uSelf, uOther : TDateTimeEx;
  begin
    uSelf := UTC;
    uOther := other.UTC;
    if uSelf.equal(uOther) then
      exit(inclusive);
    result := (uSelf.year <= uOther.year) and (uSelf.month <= uOther.month) and (uSelf.day <= uOther.day) and
              (uSelf.hour <= uOther.hour) and (uSelf.minute <= uOther.minute) and (uSelf.second <= uOther.second) and (uSelf.fraction <= uOther.fraction);
  end;
  
  function TDateTimeEx.between(min, max : TDateTimeEx; inclusive : boolean):boolean;
  begin
    result := after(min, inclusive) and before(max, inclusive);
  end;
  
  const
    DATETIME_FORMAT_XML = 'yyyy-mm-dd"T"hh:nn:ss';
  
  