
New patches:

[Added a function which returns adjusted time, taking care of overflows.
Denys Rtveliashvili <rtvd@mail.ru>**20071001121830] {
hunk ./local-time.lisp 54
+	   #:adjusted-local-time
hunk ./local-time.lisp 495
+(defun adjusted-local-time (location offset time)
+  "Returns a time adjusted by the specified offset. Takes care about different kinds of overflows."
+
+  (labels ((direct-adjust (location offset usec sec day timezone)
+	     (if (zerop offset)
+		 ;; The offset is zero, so just assemble the local-time object
+		 (make-local-time :usec usec
+				  :sec sec
+				  :day day
+				  :timezone timezone)
+		 
+		 ;; The offset is not zero
+		 (case location
+		   (:usec
+		    (multiple-value-bind (sec-offset new-usec)
+			(floor (+ offset usec) 1000000)
+		    
+		      ;; the time might need to be adjusted a bit more if q != 0
+		      (direct-adjust :sec sec-offset
+				     new-usec sec day timezone)))
+		   (:day
+		    (make-local-time :usec usec
+				     :sec sec
+				     :day (+ day offset)
+				     :timezone timezone))
+		   (otherwise
+		    (multiple-value-bind (days-offset new-sec)
+			(floor (+ sec (* offset (ecase location
+						  (:sec 1)
+						  (:minute 60)
+						  (:hour 3600))))
+			       86400)
+		      (direct-adjust :day days-offset
+				     usec new-sec day timezone))))))
+
+	   (normalize-month-year-pair (month year)
+	     "Normalizes the month/year pair: in case month is < 1 or > 12
+the month and year are corrected to handle the overflow."
+
+	     (multiple-value-bind (year-offset month-minus-one)
+		 (floor (1- month) 12)
+	       (values (1+ month-minus-one)
+		       (+ year year-offset))))
+
+	   (days-in-month (month year)
+	     "Returns the number of days in the given month of the specified year"
+
+	     (multiple-value-bind (month1 year1)
+		 (normalize-month-year-pair month year)
+	       (multiple-value-bind (month2 year2)
+		   (normalize-month-year-pair (1+ month) year)
+		 ;; month1-year1 pair represents the current month
+		 ;; month2-year2 pair represents the sequential month
+		 ;; now we get timestamps for the first days of these months
+		 ;; and find out what the difference in days is
+		 (let ((timestamp1 (encode-local-time 0 0 0 0 1 month1 year1))
+		       (timestamp2 (encode-local-time 0 0 0 0 1 month2 year2)))
+		   (- (day-of timestamp2) (day-of timestamp1))))))
+
+	   (safe-adjust (location offset time)
+	     (multiple-value-bind (usec ss mm hh day month year d-o-w d-s-t-p timezone)
+		 (decode-local-time time)
+	       (declare (ignore d-o-w d-s-t-p))
+	       (multiple-value-bind (month-new year-new)
+		   (normalize-month-year-pair
+		    (+ (ecase location
+			 (:month offset)
+			 (:year (* 12 offset)))
+		       month)
+		    year)
+		 ;; Almost there. However, it is necessary to check for
+		 ;; overflows first
+		 (let* ((days (days-in-month month-new year-new))
+			(day-new (if (> day days)
+				     days
+				     day)))
+		   (encode-local-time usec ss mm hh day-new month-new year-new :timezone timezone))))))
+    
+    (ecase location
+      ((:usec :sec :minute :hour :day)
+       (direct-adjust location offset
+		      (usec-of time)
+		      (sec-of time)
+		      (day-of time)
+		      (timezone-of time)))
+      ((:month :year) (safe-adjust location offset time)))))
+
hunk ./local-time.lisp 764
-  "Returns the decoded time as multiple values: ms, ss, mm, hh, day, month, year, day-of-week, daylight-saving-time-p, timezone, and the customary timezone abbreviation."
+  "Returns the decoded time as multiple values: usec, ss, mm, hh, day, month, year, day-of-week, daylight-saving-time-p, timezone, and the customary timezone abbreviation."
}

[Added "modified-local-time" and "days-in-month" functions.
Denys Rtveliashvili <rtvd@mail.ru>**20071011162326] {
hunk ./local-time.lisp 54
-	   #:adjusted-local-time
+           #:days-in-month
+           #:modified-local-time
+           #:adjusted-local-time
hunk ./local-time.lisp 496
+(defun normalize-month-year-pair (month year)
+  "Normalizes the month/year pair: in case month is < 1 or > 12
+the month and year are corrected to handle the overflow."
+  
+  (multiple-value-bind (year-offset month-minus-one)
+      (floor (1- month) 12)
+    (values (1+ month-minus-one)
+	    (+ year year-offset))))
+
+(defun days-in-month (month year)
+  "Returns the number of days in the given month of the specified year
+TODO: optimize it"
+  
+  (multiple-value-bind (month1 year1)
+      (normalize-month-year-pair month year)
+    (multiple-value-bind (month2 year2)
+	(normalize-month-year-pair (1+ month) year)
+      ;; month1-year1 pair represents the current month
+      ;; month2-year2 pair represents the sequential month
+      ;; now we get timestamps for the first days of these months
+      ;; and find out what the difference in days is
+      (let ((timestamp1 (encode-local-time 0 0 0 0 1 month1 year1))
+	    (timestamp2 (encode-local-time 0 0 0 0 1 month2 year2)))
+	(- (day-of timestamp2) (day-of timestamp1))))))
+
+(defun fix-overflow-in-days (day month year)
+  "In case the day number is higher than the maximal possible for the given month/year pair,
+returns the last day of the month."
+  (let ((max-day (days-in-month month year)))
+    (if (> day max-day)
+	max-day
+	day)))
+
+(defun modified-local-time (location new-value time)
+  "Returns a modified timestamp, the original timestamp is left intact"
+  (case location
+    ((:usec :sec-of-day :day)
+     (let ((usec (usec-of time))
+	   (sec (sec-of time))
+	   (day (day-of time))
+	   (timezone (timezone-of time)))
+       (case location
+	 (:usec (setf usec (coerce new-value '(integer 0 999999))))
+	 (:sec-of-day (setf sec (coerce new-value '(integer 0 #.(* 24 60 60)))))
+	 (:day (setf day new-value))
+	 (:timezone (setf timezone new-value)))
+       (make-local-time :usec usec
+			:sec sec
+			:day day
+			:timezone timezone)))
+     (otherwise
+      (multiple-value-bind (usec ss mm hh day month year day-of-week daylight-saving-time-p timezone timezone-abbr)
+	  (decode-local-time time)
+	(declare (ignore daylight-saving-time-p timezone-abbr day-of-week))
+	(ecase location
+	  (:sec (setf ss new-value))
+	  (:minute (setf mm new-value))
+	  (:hour (setf hh new-value))
+	  (:day-of-month (setf day new-value))
+	  (:month (setf month new-value)
+		  (setf day (fix-overflow-in-days day month year)))
+	  (:year (setf year new-value)
+		 (setf day (fix-overflow-in-days day month year)))
+	  (:timezone (setf timezone new-value)))
+	(encode-local-time usec ss mm hh day month year :timezone timezone)))))
hunk ./local-time.lisp 592
-						  (:hour 3600))))
-			       86400)
+						  (:hour #.(* 60 60)))))
+			       #.(* 24 60 60))
hunk ./local-time.lisp 597
-	   (normalize-month-year-pair (month year)
-	     "Normalizes the month/year pair: in case month is < 1 or > 12
-the month and year are corrected to handle the overflow."
-
-	     (multiple-value-bind (year-offset month-minus-one)
-		 (floor (1- month) 12)
-	       (values (1+ month-minus-one)
-		       (+ year year-offset))))
-
-	   (days-in-month (month year)
-	     "Returns the number of days in the given month of the specified year"
-
-	     (multiple-value-bind (month1 year1)
-		 (normalize-month-year-pair month year)
-	       (multiple-value-bind (month2 year2)
-		   (normalize-month-year-pair (1+ month) year)
-		 ;; month1-year1 pair represents the current month
-		 ;; month2-year2 pair represents the sequential month
-		 ;; now we get timestamps for the first days of these months
-		 ;; and find out what the difference in days is
-		 (let ((timestamp1 (encode-local-time 0 0 0 0 1 month1 year1))
-		       (timestamp2 (encode-local-time 0 0 0 0 1 month2 year2)))
-		   (- (day-of timestamp2) (day-of timestamp1))))))
-
hunk ./local-time.lisp 610
-		 (let* ((days (days-in-month month-new year-new))
-			(day-new (if (> day days)
-				     days
-				     day)))
-		   (encode-local-time usec ss mm hh day-new month-new year-new :timezone timezone))))))
+		 (encode-local-time usec ss mm hh
+				    (fix-overflow-in-days day month-new year-new)
+				    month-new year-new
+				    :timezone timezone)))))
hunk ./local-time.lisp 1180
+
}

Context:

[added valid-date-p
attila.lendvai@gmail.com**20070908205216] 
[Optimize some array lookups
attila.lendvai@gmail.com**20070823140940] 
[Added first-day-of-year and last-day-of-year
attila.lendvai@gmail.com**20070823124104] 
[Added some useful constants.
levente.meszaros@gmail.com**20070809194320] 
[fix some tests: (now) may have usec now
attila.lendvai@gmail.com**20070809135232] 
[re-fix usec parsing
attila.lendvai@gmail.com**20070809135224] 
[Use leap-factor wherever applicable.
levente.meszaros@gmail.com**20070809141319] 
[Added format-datestring.
levente.meszaros@gmail.com**20070809135040] 
[Fix parse-timestring to always pass usec to encode-local-time, default is 0.
levente.meszaros@gmail.com**20070809135008] 
[Refactored encode-local-time and local-time-decode-date to correctly work with leap days.
levente.meszaros@gmail.com**20070809134832] 
[Add tests for encode and decode local time.
levente.meszaros@gmail.com**20070809134817] 
[Fix wrong parse-timestring test cases.
levente.meszaros@gmail.com**20070809134720] 
[Fix usec parsing
attila.lendvai@gmail.com**20070809095615] 
[Annotate types on the local-time class for documentation purposes
attila.lendvai@gmail.com**20070809095546] 
[Added failing test
attila.lendvai@gmail.com**20070808211131] 
[Allow missing elements in the reader syntax
attila.lendvai@gmail.com**20070808204235] 
[Implement usec precision (NOW) for sbcl
attila.lendvai@gmail.com**20070731235534] 
[Fix: local-time-adjust was not handling the overflow of sec to day
attila.lendvai@gmail.com**20070731234841] 
[Added PARSE-DATESTRING and TODAY
attila.lendvai@gmail.com**20070626161626] 
[Docstring typo
attila.lendvai@gmail.com**20070424132535] 
[Optimization: Check if target timezone is the same as the timezone of the input in local-time-adjust and return the input if it is
attila.lendvai@gmail.com**20070424131635] 
[Set the default year/month/day in parse-timestring to 2000-03-01 which is the zero point of local-time objects
attila.lendvai@gmail.com**20070421142631] 
[Fix for (parse-timestring "2000-01-01TZ")
attila.lendvai@gmail.com**20070421115621] 
[Indentation
attila.lendvai@gmail.com**20070421115315] 
[Use &rest args for local-time-min/max to behave more like their equivalent CL operator
attila.lendvai@gmail.com**20070417092932] 
[Added missing &allow-other-keys for format-rfc3339-timestring
attila.lendvai@gmail.com**20070416122023] 
[Added local-time-min and local-time-max
attila.lendvai@gmail.com**20070305130540] 
[Convert some &optional's into &key args for more flexibility (WARNING: api change)
attila.lendvai@gmail.com**20061217171826] 
[Added local-time-adjust-days
attila.lendvai@gmail.com**20061217171721] 
[Cleanups in local-time-whole-year-difference
attila.lendvai@gmail.com**20061211175223] 
[Export.
levente.meszaros@gmail.com**20061207164854] 
[Added function to calculate the number of whole years elapsed between two local-times.
levente.meszaros@gmail.com**20061207164002] 
[Introduced a defcomparator macro and support arbitrary number of times in the comparators
attila.lendvai@gmail.com**20061213195041] 
[Change the test expression order to match the expected (is (predicate EXPECTED ACTUAL))
attila.lendvai@gmail.com**20061211173734] 
[Fix parsing of zulu in timestrings like "2006-06-06T00:00:00Z", fix some tests
attila.lendvai@gmail.com**20061206163645] 
[Default fields to their lowest possible values in parse-timestring when a field is not defined in the string
attila.lendvai@gmail.com**20061204115627] 
[Added note to TODO to integrate with cl-l10n
attila.lendvai@gmail.com**20061202133159] 
[Added .boring file
attila.lendvai@gmail.com**20061202132625] 
[FIX: patch missed at last record
attila.lendvai@gmail.com**20061124143408] 
[Added timezone repository, fix parsing of timestrings with random timezone
attila.lendvai@gmail.com**20061122213055] 
[Various small fixes
attila.lendvai@gmail.com**20061122212627] 
[Added zoneinfo files
attila.lendvai@gmail.com**20061122212102] 
[Partially fix parsing the timezon (works for zulu at least)
attila.lendvai@gmail.com**20061117152729] 
[Convert also the timezone in universal-time
attila.lendvai@gmail.com**20061117141346
 
 LOCAL-TIME> (let ((now (now)))
               (local-time-adjust now +utc-zone+ now)
               (local-time= now (local-time :universal (universal-time now))))
 T
] 
[Added &optional timezone for minimize/maximize-time-part
attila.lendvai@gmail.com**20061117133430] 
[Added type annotations to fail early when called with a wrong type, also to help the compiler
attila.lendvai@gmail.com**20061109123602] 
[Dropped unused functions: skip-timestring-junk, read-integer-str, read-millisecond-str
attila.lendvai@gmail.com**20061109113419] 
[Allow to specify hour only in timezone when allow-missing-timezone-part-p is true.
levente.meszaros@gmail.com**20061109144552] 
[Enable running 5am tests by default
dlowe@bitmuse.com**20061101204702] 
[Fix for clisp's rigid loop impl
attila.lendvai@gmail.com**20061031233554] 
[Extend customizability of formatting/parsing timestrings
attila.lendvai@gmail.com**20061009141027] 
[Added maximize- and minimize-time-part
attila.lendvai@gmail.com**20061001200738] 
[Added parse-rfc3339-timestring
attila.lendvai@gmail.com**20061001181820] 
[Follow 5am changes
attila.lendvai@gmail.com**20061001175205] 
[Replaced the timestring parser with an optimized and more configurable version
attila.lendvai@gmail.com**20061001175154] 
[Merge conflicts
attila.lendvai@gmail.com**20060930202401] 
[Added use-zulu-p and made format-timestring call local-time-adjust when a custom timezone is supplied
attila.lendvai@gmail.com**20060930152908] 
[Added format-rfc3339-timestring with small changes to format-timestring
attila.lendvai@gmail.com**20060930152833] 
[Converted the tests to use 5am
attila.lendvai@gmail.com**20060930135233] 
[Removed unnecessary automatic in-package
dlowe@bitmuse.com**20061101153847] 
[Comment out the in-package form by default
attila.lendvai@gmail.com**20061001190055] 
[Only print usec if it's not zero
attila.lendvai@gmail.com**20060930144311] 
[Renamed to date-time-separator and used &optional defaulting in format-timestring
attila.lendvai@gmail.com**20060930144214] 
[Use uninterned symbols in the package definition
attila.lendvai@gmail.com**20060930144135] 
[Added compatibility accessors and fixed documentation strings
dlowe@bitmuse.com**20060930141058] 
[Update documentation files
dlowe@bitmuse.com**20060930141036] 
[A few more resolving fixes
dlowe@bitmuse.com**20060930135319] 
[Resolved conflicts and changed remaining tabs
dlowe@bitmuse.com**20060930134410] 
[Replace tabs with spaces
attila.lendvai@gmail.com**20060930130209] 
[Return (values) from enable-read-macros
attila.lendvai@gmail.com**20060930130116] 
[Fix exports, export +utc-zone+
attila.lendvai@gmail.com**20060930130029] 
[Added several asdf goodies
attila.lendvai@gmail.com**20060930095645
 
 - auto in-package after loaded with asdf
 - (asdf:operate 'asdf:test-op :local-time)
 - single .asd file
] 
[Removed durations and renamed accessors
dlowe@bitmuse.com**20060930132058
 
 Durations, though useful, are too semantically unwieldy to add
 at this time.  The skeleton duration support has been removed
 and the accessors renamed by removing the epoch- designator.
 
] 
[Fixed erroneous rename of local-time-day-of-week
dlowe@bitmuse.com**20060929222702] 
[Better testing, code for tracking durations
dlowe@bitmuse.com**20060815154546
 * local-time/local-time-test.lisp
 * local-time/local-time.lisp
 	- deftest now accepts forms to test against instead of values
 	- local-time class now has code for tracking durations - not finished yet
] 
[TAG 0.9.1
dlowe@bitmuse.com**20060722140000] 
[enable-read-macros is now exported from the package
dlowe@bitmuse.com**20060722132556] 
[Updated copyright and fixed reader macros
dlowe@bitmuse.com**20060718124934
 * local-time/ChangeLog
 	- Added new changes
 
 * local-time/COPYING
 	- Updated copyright year
 
 * local-time/local-time-test.lisp
 	- Added tests for reader macros
 
 * local-time/local-time.lisp
 	- Reader macros now return an actual object instead of the code to
 	  generate it
 
 * local-time/local-time.asd
 	- Bumped up version number
] 
[TAG 0.9.0
dlowe@bitmuse.com**20060429085300] 
[Fixed local-time-adjust
dlowe@bitmuse.com**20060414160507
 * local-time/local-time-test.lisp
 	- local-time-adjust-1 now checks more values
 
 * local-time/local-time.lisp
 	- local-time-adjust now passes all tests
] 
[Fixed problem with negatively adjusting timezones
dlowe@bitmuse.com**20060414153201
 * local-time/ChangeLog
 * local-time/local-time-test.lisp
 	- Test failure now mentions which value didn't match
 	- Added tests for local-time-adjust with negatively adjusting
 	  timezones
 	- Test compilation now results in fewer warnings
 
 * local-time/local-time.lisp
 	- LOCAL-TIME-ADJUST now works better with negatively adjusting
 	  timezones
] 
[Updated changelog, fixed bugs, added minor features
dlowe@bitmuse.com**20060410014640
 * local-time/TODO
 	- Added a bunch of todo items
 
 * local-time/ChangeLog
 	- Added mine and Sekissov's contributions
 
 * local-time/local-time-test.lisp
 	- reset-tests now clears the correct hash variable
 	- tests updated to include Sekissov's changes
 
 * local-time/local-time.lisp
 	- Added month and day names, as well as julian date functions
 
 * local-time/CREDITS
 	- Added Sekissov
 
 * local-time/README
 	- Removed warning about parse-timestring
 	- Added documentation for julian date functions
] 
[TAG 0.8.0
dlowe@bitmuse.com**20060403222300] 
[parse-timestring now works much, much better.
dlowe@bitmuse.com**20060403222253] 
[TAG 0.7.0
dlowe@bitmuse.com**20060207184000] 
[Updated changelog, better parsing and testing
dlowe@bitmuse.com**20060207183925
 * local-time/ChangeLog
 	- Added entries for latest changes
 
 * local-time/local-time.lisp
     - updated copyright date
     - decode-local-time now handles 2001-03-01 correctly
     - parse-timestring now partially honors JUNK-ALLOWED keyword
     - construct-timestring now always prints at least 4 digits for year
     - construct-timestring now puts negative sign in proper location
     
 * local-time/local-time-test.lisp
     - deftest now has many more features
     - added encode-local-time test
     - added two more decode-local-time tests
] 
[TAG 0.6.0
dlowe@bitmuse.com**20051229204400] 
[Added changelog, credits, and bug fixes
dlowe@bitmuse.com**20051229024115
 * local-time/ChangeLog
 * local-time/NEWS
 	- NEWS file removed in favor of a well-formatted ChangeLog
 
 * local-time/CREDITS
 	- Added credits file so I could thank helpers
 
 * local-time/local-time-test.lisp
 	- Added tests for decode-local-time and parse-timestamp
 
 * local-time/local-time.lisp
 	- decode-local-time no longer displays the wrong month and year
 	  when the month is January
 	- parse-timestamp now actually does something useful
] 
[local-time:NOW is now an exported symbol.
dlowe@bitmuse.com**20050512153642] 
[TAG 0.5.0
dlowe@bitmuse.com**20050427143900] 
Patch bundle hash:
891a4905d84cae82ce9e234268ea74d7505ee904
