diff --git a/lib/SimpleSAML/Utilities.php b/lib/SimpleSAML/Utilities.php
index daf57e59ff6ac27cc2d05134a36817b3f243ea2c..033f0f691acb5d0bdbda4ce28a97a5003d57ba21 100644
--- a/lib/SimpleSAML/Utilities.php
+++ b/lib/SimpleSAML/Utilities.php
@@ -392,6 +392,89 @@ class SimpleSAML_Utilities {
 	}
 
 
+	/**
+	 * Interpret a ISO8601 duration value relative to a given timestamp.
+	 *
+	 * @param string $duration  The duration, as a string.
+	 * @param int $timestamp  The unix timestamp we should apply the duration to. Optional, default
+	 *                        to the current time.
+	 * @return int  The new timestamp, after the duration is applied.
+	 */
+	public static function parseDuration($duration, $timestamp = NULL) {
+		assert('is_string($duration)');
+		assert('is_null($timestamp) || is_int($timestamp)');
+
+		/* Parse the duration. We use a very strict pattern. */
+		$durationRegEx = '#^(-?)P(?:(?:(?:(\\d+)Y)?(?:(\\d+)M)?(?:(\\d+)D)?(?:T(?:(\\d+)H)?(?:(\\d+)M)?(?:(\\d+)S)?)?)|(?:(\\d+)W))$#';
+		if (!preg_match($durationRegEx, $duration, $matches)) {
+			throw new Exception('Invalid ISO 8601 duration: ' . $duration);
+		}
+
+		$durYears = (empty($matches[2]) ? 0 : (int)$matches[2]);
+		$durMonths = (empty($matches[3]) ? 0 : (int)$matches[3]);
+		$durDays = (empty($matches[4]) ? 0 : (int)$matches[4]);
+		$durHours = (empty($matches[5]) ? 0 : (int)$matches[5]);
+		$durMinutes = (empty($matches[6]) ? 0 : (int)$matches[6]);
+		$durSeconds = (empty($matches[7]) ? 0 : (int)$matches[7]);
+		$durWeeks = (empty($matches[8]) ? 0 : (int)$matches[8]);
+
+		if (!empty($matches[1])) {
+			/* Negative */
+			$durYears = -$durYears;
+			$durMonths = -$durMonths;
+			$durDays = -$durDays;
+			$durHours = -$durHours;
+			$durMinutes = -$durMinutes;
+			$durSeconds = -$durSeconds;
+			$durWeeks = -$durWeeks;
+		}
+
+		if ($timestamp === NULL) {
+			$timestamp = time();
+		}
+
+		if ($durYears !== 0 || $durMonths !== 0) {
+			/* Special handling of months and years, since they aren't a specific interval, but
+			 * instead depend on the current time.
+			 */
+
+			/* We need the year and month from the timestamp. Unfortunately, PHP doesn't have the
+			 * gmtime function. Instead we use the gmdate function, and split the result.
+			 */
+			$yearmonth = explode(':', gmdate('Y:n', $timestamp));
+			$year = (int)($yearmonth[0]);
+			$month = (int)($yearmonth[1]);
+
+			/* Remove the year and month from the timestamp. */
+			$timestamp -= gmmktime(0, 0, 0, $month, 1, $year);
+
+			/* Add years and months, and normalize the numbers afterwards. */
+			$year += $durYears;
+			$month += $durMonths;
+			while ($month > 12) {
+				$year += 1;
+				$month -= 12;
+			}
+			while ($month < 1) {
+				$year -= 1;
+				$month += 12;
+			}
+
+			/* Add year and month back into timestamp. */
+			$timestamp += gmmktime(0, 0, 0, $month, 1, $year);
+		}
+
+		/* Add the other elements. */
+		$timestamp += $durWeeks * 7 * 24 * 60 * 60;
+		$timestamp += $durDays * 24 * 60 * 60;
+		$timestamp += $durHours * 60 * 60;
+		$timestamp += $durMinutes * 60;
+		$timestamp += $durSecods;
+
+		return $timestamp;
+	}
+
+
 	/** 
 	 * Show and log fatal error message.
 	 *