whole_func_string: function addDuration(startDate, duration) {
    var end = getObjFromDate(startDate, false),
        endString = '';
  
    // Initialize all the values we need in end based on the duration
    zipDuration(end, duration);
  
    // Add Timezone offset to endString
    if(startDate.getTZHours() != undefined) {
      if(startDate.getTZHours() < 0) {
        endString += '-';
      } else {
        endString += '+';
      }
      endString += ('00'+Math.abs(startDate.getTZHours())).substr(-2,2);
      endString += ':'+('00'+Math.abs(startDate.getTZMinutes())).substr(-2,2);
    }
  
    if(duration.getSeconds()) {
      end.seconds += duration.getSeconds();
    }
    while(end.seconds && end.seconds >= 60) {
      end.seconds -= 60;
      end.minutes += 1;
    }
    if(end.seconds != undefined) {
      endString = ':'+('00'+end.seconds).substr(-2,2)+endString;
    }
  
    if(duration.getMinutes()) {
      end.minutes += duration.getMinutes();
    }
    while(end.minutes && end.minutes >= 60) {
      end.minutes -= 60;
      end.hours += 1;
    }
    if(end.minutes != undefined) {
      endString = ':'+('00'+end.minutes).substr(-2,2)+endString;
    }
  
    if(duration.getHours()) {
      end.hours += duration.getHours();
    }
    while(end.hours && end.hours >= 24) {
      end.hours -= 24;
      end.day += 1;
    }
    if(end.hours != undefined) {
      endString = 'T'+('00'+end.hours).substr(-2,2)+endString;
    }
  
    if(duration.getDays()) {
      end.day += duration.getDays();
    }
    while(end.day && end.day > GlobalUtil.daysInMonth(end.month, end.year)) {
      end.month += 1;
      if(end.month > 12) {
        end.month -= 12;
        end.year += 1;
      }
      end.day -= GlobalUtil.daysInMonth(end.month, end.year);
    }
    if(end.day != undefined) {
      endString = '-'+('00'+end.day).substr(-2,2)+endString;
    }
  
    if(duration.getMonths()) {
      end.month += duration.getMonths();
    }
    while(end.month && end.month > 12) {
      end.month -= 12;
      end.year += 1;
    }
    if(end.month != undefined) {
      endString = '-'+('00'+end.month).substr(-2,2)+endString;
    }
  
    if(duration.getYears()) {
      end.year += duration.getYears();
    }
    if(end.year != undefined) {
      endString = ('0000'+Math.abs(end.year)).substr(-4,4)+endString;
      if(end.year < 0) {
        endString = '-'+endString;
      } else {
        endString = '+'+endString;
      }
    }
  
    // After adding year we could have bumped into a non leap year
    // TODO fix this
  
    if(end.year > 9999) {
      throw new Error('New date out of range');
    }
  
    // TODO return actual simple or approximate dates
    if(startDate.isApproximate()) {
      endString = 'A'+endString;
      return new Approximate(endString);
    } else {
      return new Simple(endString);
    }
  
  }
func_code_string: function addDuration(startDate, duration) {
    var end = getObjFromDate(startDate, false),
        endString = '';
  
    // Initialize all the values we need in end based on the duration
    zipDuration(end, duration);
  
    // Add Timezone offset to endString
    if(startDate.getTZHours() != undefined) {
      if(startDate.getTZHours() < 0) {
        endString += '-';
      } else {
        endString += '+';
      }
      endString += ('00'+Math.abs(startDate.getTZHours())).substr(-2,2);
      endString += ':'+('00'+Math.abs(startDate.getTZMinutes())).substr(-2,2);
    }
  
    if(duration.getSeconds()) {
      end.seconds += duration.getSeconds();
    }
    while(end.seconds && end.seconds >= 60) {
      end.seconds -= 60;
      end.minutes += 1;
    }
    if(end.seconds != undefined) {
      endString = ':'+('00'+end.seconds).substr(-2,2)+endString;
    }
  
    if(duration.getMinutes()) {
      end.minutes += duration.getMinutes();
    }
    while(end.minutes && end.minutes >= 60) {
      end.minutes -= 60;
      end.hours += 1;
    }
    if(end.minutes != undefined) {
      endString = ':'+('00'+end.minutes).substr(-2,2)+endString;
    }
  
    if(duration.getHours()) {
      end.hours += duration.getHours();
    }
    while(end.hours && end.hours >= 24) {
      end.hours -= 24;
      end.day += 1;
    }
    if(end.hours != undefined) {
      endString = 'T'+('00'+end.hours).substr(-2,2)+endString;
    }
  
    if(duration.getDays()) {
      end.day += duration.getDays();
    }
    while(end.day && end.day > GlobalUtil.daysInMonth(end.month, end.year)) {
      end.month += 1;
      if(end.month > 12) {
        end.month -= 12;
        end.year += 1;
      }
      end.day -= GlobalUtil.daysInMonth(end.month, end.year);
    }
    if(end.day != undefined) {
      endString = '-'+('00'+end.day).substr(-2,2)+endString;
    }
  
    if(duration.getMonths()) {
      end.month += duration.getMonths();
    }
    while(end.month && end.month > 12) {
      end.month -= 12;
      end.year += 1;
    }
    if(end.month != undefined) {
      endString = '-'+('00'+end.month).substr(-2,2)+endString;
    }
  
    if(duration.getYears()) {
      end.year += duration.getYears();
    }
    if(end.year != undefined) {
      endString = ('0000'+Math.abs(end.year)).substr(-4,4)+endString;
      if(end.year < 0) {
        endString = '-'+endString;
      } else {
        endString = '+'+endString;
      }
    }
  
    // After adding year we could have bumped into a non leap year
    // TODO fix this
  
    if(end.year > 9999) {
      throw new Error('New date out of range');
    }
  
    // TODO return actual simple or approximate dates
    if(startDate.isApproximate()) {
      endString = 'A'+endString;
      return new Approximate(endString);
    } else {
      return new Simple(endString);
    }
  
  }
func_documentation_string: Adds a duration to a date, returning the new date.