Vim window logic, slimv
This commit is contained in:
parent
babcc9e44b
commit
515847d07e
791 changed files with 51552 additions and 86 deletions
22
sbcl/.quicklisp/dists/quicklisp/software/local-time-20190710-git/.gitignore
vendored
Normal file
22
sbcl/.quicklisp/dists/quicklisp/software/local-time-20190710-git/.gitignore
vendored
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
*.*fas*
|
||||
*.fasl
|
||||
*.dfsl
|
||||
*.ppcf
|
||||
*.x86f
|
||||
*.fas
|
||||
*.lib
|
||||
doc/manual/
|
||||
doc/*.vr
|
||||
doc/*.tp
|
||||
doc/*.tps
|
||||
doc/*.toc
|
||||
doc/*.pg
|
||||
doc/*.log
|
||||
doc/*.ky
|
||||
doc/*.it
|
||||
doc/*.info
|
||||
doc/*.fn
|
||||
doc/*.fns
|
||||
doc/*.cp
|
||||
doc/*.cps
|
||||
doc/*.aux
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
local-time Copyright (c) 2005-2012 by Daniel Lowe
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
Thanks to those of you who have helped me make LOCAL-TIME an engaging
|
||||
and worthwhile project!
|
||||
|
||||
* Matthew Danish <mdanish@andrew.cmu.edu>
|
||||
* The #lisp crew on irc.freenode.net
|
||||
* Vladimir Sekissov <svg@surnet.ru>
|
||||
* Attila Lendvai <attila.lendvai@gmail.com>
|
||||
* Tomi Borbely <tomi.borbely@gmail.com>
|
||||
* Denys Rtveliashvili <rtvd@mail.ru>
|
||||
* Levente Meszaros <levente.meszaros@gmail.com>
|
||||
* Arjan Wekking <arjan@streamtech.nl>
|
||||
|
||||
------------------------------------------------------------------------
|
||||
Apologies to anyone I didn't mention (please let me know).
|
||||
|
||||
Daniel Lowe
|
||||
<dlowe@dlowe.net>
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
# Installation
|
||||
|
||||
## Using Quicklisp
|
||||
|
||||
1. Install quicklisp
|
||||
2. Use quicklisp to install local-time
|
||||
|
||||
(ql:quickload :local-time)
|
||||
|
||||
## Manual Installation
|
||||
|
||||
1. Make sure the ASDF library is loaded. In SBCL, this involves:
|
||||
|
||||
(require :asdf)
|
||||
|
||||
2. Add the path to the directory containing local-time.asd to
|
||||
asdf:*central-registry*. If you've installed this package using
|
||||
asdf-install, this shouldn't be necessary.
|
||||
|
||||
(push "/my/local-time/directory/" asdf:*central-registry*)
|
||||
|
||||
3. Load local-time using ASDF:
|
||||
|
||||
(asdf:oos 'asdf:load-op 'local-time)
|
||||
|
||||
4. In your own projects, you can direct asdf to automatically load
|
||||
LOCAL-TIME with the :depends-on asdf:defsystem directive.
|
||||
|
||||
(defsystem myproject
|
||||
:depends-on (local-time)
|
||||
...)
|
||||
|
||||
## Testing
|
||||
|
||||
local-time uses Stefil for testing. To run the Stefil test suite, do
|
||||
the following:-
|
||||
|
||||
(ql:quickload :local-time.test)
|
||||
(in-suite test)
|
||||
(test)
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
LOCAL-TIME
|
||||
|
||||
See the "COPYING" file for information about legal issues of copying
|
||||
and using this library.
|
||||
|
||||
See the "INSTALL" file for information about building and installing
|
||||
this library.
|
||||
|
||||
The LOCAL-TIME library is a Common Lisp library for the manipulation
|
||||
of dates and times. It is based almost entirely upon Erik Naggum's
|
||||
paper "The Long Painful History of Time".
|
||||
|
||||
Related projects of interest:
|
||||
* https://github.com/enaeher/local-time-duration
|
||||
* http://common-lisp.net/projects/cl-l10n/
|
||||
|
||||
See the manual/ directory for more information and/or the website at
|
||||
http://common-lisp.net/project/local-time/
|
||||
|
|
@ -0,0 +1,104 @@
|
|||
-*- mode: org; coding: utf-8-unix -*-
|
||||
|
||||
* Basic Outline
|
||||
** A more human friendly parser
|
||||
|
||||
PARSE-TIMESTRING works fine, but we need a more human-friendly parser that
|
||||
can handle stuff like "08/03/2006 1:54pm CST". or maybe not? see
|
||||
http://chaitanyagupta.com/lisp/chronicity/
|
||||
|
||||
** Support for other notational systems than the Gregorian
|
||||
|
||||
** Ideally, local-time should have everything that the ruby Date class does
|
||||
|
||||
Also, the time functions in the venerable and honored clsql library.
|
||||
This may be a tall order.
|
||||
|
||||
** Integrate local-time with http://common-lisp.net/project/cl-l10n/
|
||||
Also drop time/timezone related functionality from cl-l10n.
|
||||
|
||||
** Make local-time work with olson timezone rules
|
||||
http://www.twinsun.com/tz/tz-link.htm
|
||||
Right now, we're using zic compiled files, which have a limited
|
||||
scope. They may also be larger than the corresponding rule files.
|
||||
|
||||
* Attila:
|
||||
Many of the operations currently defined on timestamps should not
|
||||
really be defined on timestamps at all. i think this is due to some
|
||||
heritage from the times when a timestamp value also had a timezone
|
||||
value attached to it.
|
||||
|
||||
Examples of such bogus operations are timestamp+, timestamp-, all
|
||||
adjust-timestamp variants that operate on the components of a date
|
||||
value, etc.
|
||||
|
||||
* Nomenclature
|
||||
** timestamp: a sharp cut on the continuous t axis (as in physics) of time
|
||||
It is mostly unrelated to timezones and different calendar systems
|
||||
(e.g. Julian, Gregorian), which are just ways to denote a timestamp in
|
||||
a way humans can easily deal with.
|
||||
|
||||
** interval: a range on the time axis denoted by two timestamps
|
||||
|
||||
** date-time: contains the fields defined by the calendar system
|
||||
Some date-time fields may be left undefined.
|
||||
|
||||
** calendar: a converter to and from a particular date-time type
|
||||
A method defining how to denote a timestamp using a set of numbers
|
||||
(called year, month, day, etc). there are various such encodings
|
||||
like the Gregorian calendar, or the Julian calendar (which was in
|
||||
effect in Russia until 1922!). wikipedia has loads of info about
|
||||
these. We'll default to a naive Gregorian calendar
|
||||
|
||||
** duration: a value representing a delta between date-times
|
||||
|
||||
|
||||
* Timestamp Operations
|
||||
** basic arithmetic
|
||||
essentially arithmetic on numbers denoting seconds. operations that
|
||||
would expose the epoch chosen by the implementation are not allowed
|
||||
(e.g. adding two timestamps), but things like adding/subbing
|
||||
literals and substracting two timestamps are valid.
|
||||
|
||||
** convert to/from date
|
||||
(only in the mandatory context of a calendar system, which most of
|
||||
the time includes a timezone, too.)
|
||||
|
||||
** create an interval given two timestamps
|
||||
|
||||
** comparison predicates
|
||||
|
||||
* Interval Operations
|
||||
There's a project implementing intervals at:
|
||||
https://github.com/enaeher/local-time-duration
|
||||
|
||||
** Arithmetic with timestamps
|
||||
** Arithmetic with intervals
|
||||
** convert to a duration with a calendar
|
||||
** Intersection with a timestamp
|
||||
** Overlap with another intervals
|
||||
|
||||
* Date-time operations
|
||||
** parse from string representation
|
||||
, e.g. an rfc3339 string. note that such a date-time does not
|
||||
necessarily describe a timestamp completely. it only does so when
|
||||
it contains all the components needed by the calendar system to
|
||||
denote a sharp cut on the t axis.
|
||||
|
||||
** set/offset any component of it,
|
||||
although what those operations mean potentially depend on the
|
||||
calendar system and its parameters (e.g. the optional timezone
|
||||
value in it). also note that some operations are potentially
|
||||
undefined and signal an error with certain illegal values
|
||||
(e.g. instantiating a date using an illegal or contradictory
|
||||
combination of its parameters; setting a field to an illegal value
|
||||
like february 29 in leap years...)
|
||||
|
||||
** convert to/from a timestamp
|
||||
(strictly in the context of a calendar system and a timezone)
|
||||
|
||||
** comparison functions
|
||||
|
||||
* Duration operations
|
||||
** Arithmetic with date-times
|
||||
** Arithmetic with durations
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
(defsystem #:cl-postgres+local-time
|
||||
:name "cl-postgres+local-time"
|
||||
:version "1.0.6"
|
||||
:author "Daniel Lowe <dlowe@dlowe.net>"
|
||||
:description "Integration between cl-postgres and local-time"
|
||||
:depends-on (:cl-postgres :local-time)
|
||||
:components ((:module "src"
|
||||
:components ((:module "integration"
|
||||
:components ((:file "cl-postgres")))))))
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
# -*- Mode: Makefile; tab-width: 4; indent-tabs-mode: t -*-
|
||||
|
||||
all: docs
|
||||
|
||||
docs:
|
||||
sh gendocs.sh -o manual --html "--css-include=style.css" local-time "The local-time Manual"
|
||||
|
||||
clean:
|
||||
find . \( -name "*.info" -o -name "*.it" -o -name "*.aux" -o -name "*.cp" -o -name "*.fn" -o -name "*.fns" -o -name "*.ky" -o -name "*.log" -o -name "*.pg" -o -name "*.toc" -o -name "*.tp" -o -name "*.vr" -o -name "*.dvi" -o -name "*.cps" -o -name "*.vrs" \) -exec rm {} \;
|
||||
rm -rf manual
|
||||
|
||||
upload-docs:
|
||||
rsync -av --delete -e ssh manual common-lisp.net:/project/local-time/public_html/
|
||||
# scp -r manual spec common-lisp.net:/project/local-time/public_html/
|
||||
|
||||
# vim: ft=make ts=4 noet
|
||||
|
|
@ -0,0 +1,285 @@
|
|||
#!/bin/sh
|
||||
# gendocs.sh -- generate a GNU manual in many formats. This script is
|
||||
# mentioned in maintain.texi. See the help message below for usage details.
|
||||
# $Id: gendocs.sh,v 1.17 2006/05/19 00:07:52 karl Exp $
|
||||
#
|
||||
# Copyright (C) 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2, or (at your option)
|
||||
# any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, you can either send email to this
|
||||
# program's maintainer or write to: The Free Software Foundation,
|
||||
# Inc.; 51 Franklin Street, Fifth Floor; Boston, MA 02110-1301, USA.
|
||||
#
|
||||
# Original author: Mohit Agarwal.
|
||||
# Send bug reports and any other correspondence to bug-texinfo@gnu.org.
|
||||
|
||||
prog=`basename "$0"`
|
||||
srcdir=`pwd`
|
||||
|
||||
scripturl="http://savannah.gnu.org/cgi-bin/viewcvs/~checkout~/texinfo/texinfo/util/gendocs.sh"
|
||||
templateurl="http://savannah.gnu.org/cgi-bin/viewcvs/~checkout~/texinfo/texinfo/util/gendocs_template"
|
||||
|
||||
: ${MAKEINFO="makeinfo"}
|
||||
: ${TEXI2DVI="texi2dvi -t @finalout"}
|
||||
: ${DVIPS="dvips"}
|
||||
: ${DOCBOOK2TXT="docbook2txt"}
|
||||
: ${DOCBOOK2HTML="docbook2html"}
|
||||
: ${DOCBOOK2PDF="docbook2pdf"}
|
||||
: ${DOCBOOK2PS="docbook2ps"}
|
||||
: ${GENDOCS_TEMPLATE_DIR="."}
|
||||
unset CDPATH
|
||||
|
||||
rcs_revision='$Revision: 1.17 $'
|
||||
rcs_version=`set - $rcs_revision; echo $2`
|
||||
program=`echo "$0" | sed -e 's!.*/!!'`
|
||||
version="gendocs.sh $rcs_version
|
||||
|
||||
Copyright (C) 2006 Free Software Foundation, Inc.
|
||||
There is NO warranty. You may redistribute this software
|
||||
under the terms of the GNU General Public License.
|
||||
For more information about these matters, see the files named COPYING."
|
||||
|
||||
usage="Usage: $prog [OPTION]... PACKAGE MANUAL-TITLE
|
||||
|
||||
Generate various output formats from PACKAGE.texinfo (or .texi or .txi) source.
|
||||
See the GNU Maintainers document for a more extensive discussion:
|
||||
http://www.gnu.org/prep/maintain_toc.html
|
||||
|
||||
Options:
|
||||
-o OUTDIR write files into OUTDIR, instead of manual/.
|
||||
--docbook convert to DocBook too (xml, txt, html, pdf and ps).
|
||||
--html ARG pass indicated ARG to makeinfo for HTML targets.
|
||||
--help display this help and exit successfully.
|
||||
--version display version information and exit successfully.
|
||||
|
||||
Simple example: $prog emacs \"GNU Emacs Manual\"
|
||||
|
||||
Typical sequence:
|
||||
cd YOURPACKAGESOURCE/doc
|
||||
wget \"$scripturl\"
|
||||
wget \"$templateurl\"
|
||||
$prog YOURMANUAL \"GNU YOURMANUAL - One-line description\"
|
||||
|
||||
Output will be in a new subdirectory \"manual\" (by default, use -o OUTDIR
|
||||
to override). Move all the new files into your web CVS tree, as
|
||||
explained in the Web Pages node of maintain.texi.
|
||||
|
||||
MANUAL-TITLE is included as part of the HTML <title> of the overall
|
||||
manual/index.html file. It should include the name of the package being
|
||||
documented. manual/index.html is created by substitution from the file
|
||||
$GENDOCS_TEMPLATE_DIR/gendocs_template. (Feel free to modify the
|
||||
generic template for your own purposes.)
|
||||
|
||||
If you have several manuals, you'll need to run this script several
|
||||
times with different YOURMANUAL values, specifying a different output
|
||||
directory with -o each time. Then write (by hand) an overall index.html
|
||||
with links to them all.
|
||||
|
||||
You can set the environment variables MAKEINFO, TEXI2DVI, and DVIPS to
|
||||
control the programs that get executed, and GENDOCS_TEMPLATE_DIR to
|
||||
control where the gendocs_template file is looked for.
|
||||
|
||||
Email bug reports or enhancement requests to bug-texinfo@gnu.org.
|
||||
"
|
||||
|
||||
calcsize()
|
||||
{
|
||||
size=`ls -ksl $1 | awk '{print $1}'`
|
||||
echo $size
|
||||
}
|
||||
|
||||
outdir=manual
|
||||
html=
|
||||
PACKAGE=
|
||||
MANUAL_TITLE=
|
||||
|
||||
while test $# -gt 0; do
|
||||
case $1 in
|
||||
--help) echo "$usage"; exit 0;;
|
||||
--version) echo "$version"; exit 0;;
|
||||
-o) shift; outdir=$1;;
|
||||
--docbook) docbook=yes;;
|
||||
--html) shift; html=$1;;
|
||||
-*)
|
||||
echo "$0: Unknown or ambiguous option \`$1'." >&2
|
||||
echo "$0: Try \`--help' for more information." >&2
|
||||
exit 1;;
|
||||
*)
|
||||
if test -z "$PACKAGE"; then
|
||||
PACKAGE=$1
|
||||
elif test -z "$MANUAL_TITLE"; then
|
||||
MANUAL_TITLE=$1
|
||||
else
|
||||
echo "$0: extra non-option argument \`$1'." >&2
|
||||
exit 1
|
||||
fi;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
|
||||
if test -s "$srcdir/$PACKAGE.texinfo"; then
|
||||
srcfile=$srcdir/$PACKAGE.texinfo
|
||||
elif test -s "$srcdir/$PACKAGE.texi"; then
|
||||
srcfile=$srcdir/$PACKAGE.texi
|
||||
elif test -s "$srcdir/$PACKAGE.txi"; then
|
||||
srcfile=$srcdir/$PACKAGE.txi
|
||||
else
|
||||
echo "$0: cannot find .texinfo or .texi or .txi for $PACKAGE in $srcdir." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if test ! -r $GENDOCS_TEMPLATE_DIR/gendocs_template; then
|
||||
echo "$0: cannot read $GENDOCS_TEMPLATE_DIR/gendocs_template." >&2
|
||||
echo "$0: it is available from $templateurl." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo Generating output formats for $srcfile
|
||||
|
||||
cmd="${MAKEINFO} -o $PACKAGE.info \"$srcfile\""
|
||||
echo "Generating info files... ($cmd)"
|
||||
eval "$cmd"
|
||||
mkdir -p $outdir/
|
||||
tar czf $outdir/$PACKAGE.info.tar.gz $PACKAGE.info*
|
||||
info_tgz_size=`calcsize $outdir/$PACKAGE.info.tar.gz`
|
||||
# do not mv the info files, there's no point in having them available
|
||||
# separately on the web.
|
||||
|
||||
cmd="${TEXI2DVI} \"$srcfile\""
|
||||
echo "Generating dvi ... ($cmd)"
|
||||
eval "$cmd"
|
||||
|
||||
# now, before we compress dvi:
|
||||
echo Generating postscript...
|
||||
${DVIPS} $PACKAGE -o
|
||||
gzip -f -9 $PACKAGE.ps
|
||||
ps_gz_size=`calcsize $PACKAGE.ps.gz`
|
||||
mv $PACKAGE.ps.gz $outdir/
|
||||
|
||||
# compress/finish dvi:
|
||||
gzip -f -9 $PACKAGE.dvi
|
||||
dvi_gz_size=`calcsize $PACKAGE.dvi.gz`
|
||||
mv $PACKAGE.dvi.gz $outdir/
|
||||
|
||||
cmd="${TEXI2DVI} --pdf \"$srcfile\""
|
||||
echo "Generating pdf ... ($cmd)"
|
||||
eval "$cmd"
|
||||
pdf_size=`calcsize $PACKAGE.pdf`
|
||||
mv $PACKAGE.pdf $outdir/
|
||||
|
||||
cmd="${MAKEINFO} -o $PACKAGE.txt --no-split --no-headers \"$srcfile\""
|
||||
echo "Generating ASCII... ($cmd)"
|
||||
eval "$cmd"
|
||||
ascii_size=`calcsize $PACKAGE.txt`
|
||||
gzip -f -9 -c $PACKAGE.txt >$outdir/$PACKAGE.txt.gz
|
||||
ascii_gz_size=`calcsize $outdir/$PACKAGE.txt.gz`
|
||||
mv $PACKAGE.txt $outdir/
|
||||
|
||||
cmd="${MAKEINFO} --no-split --html -o $PACKAGE.html $html \"$srcfile\""
|
||||
echo "Generating monolithic html... ($cmd)"
|
||||
rm -rf $PACKAGE.html # in case a directory is left over
|
||||
eval "$cmd"
|
||||
html_mono_size=`calcsize $PACKAGE.html`
|
||||
gzip -f -9 -c $PACKAGE.html >$outdir/$PACKAGE.html.gz
|
||||
html_mono_gz_size=`calcsize $outdir/$PACKAGE.html.gz`
|
||||
mv $PACKAGE.html $outdir/
|
||||
|
||||
cmd="${MAKEINFO} --html -o $PACKAGE.html $html \"$srcfile\""
|
||||
echo "Generating html by node... ($cmd)"
|
||||
eval "$cmd"
|
||||
split_html_dir=$PACKAGE.html
|
||||
(
|
||||
cd ${split_html_dir} || exit 1
|
||||
tar -czf ../$outdir/${PACKAGE}.html_node.tar.gz -- *.html
|
||||
)
|
||||
html_node_tgz_size=`calcsize $outdir/${PACKAGE}.html_node.tar.gz`
|
||||
rm -f $outdir/html_node/*.html
|
||||
mkdir -p $outdir/html_node/
|
||||
mv ${split_html_dir}/*.html $outdir/html_node/
|
||||
rmdir ${split_html_dir}
|
||||
|
||||
echo Making .tar.gz for sources...
|
||||
srcfiles=`ls *.texinfo *.texi *.txi *.eps 2>/dev/null`
|
||||
tar cvzfh $outdir/$PACKAGE.texi.tar.gz $srcfiles
|
||||
texi_tgz_size=`calcsize $outdir/$PACKAGE.texi.tar.gz`
|
||||
|
||||
if test -n "$docbook"; then
|
||||
cmd="${MAKEINFO} -o - --docbook \"$srcfile\" > ${srcdir}/$PACKAGE-db.xml"
|
||||
echo "Generating docbook XML... $(cmd)"
|
||||
eval "$cmd"
|
||||
docbook_xml_size=`calcsize $PACKAGE-db.xml`
|
||||
gzip -f -9 -c $PACKAGE-db.xml >$outdir/$PACKAGE-db.xml.gz
|
||||
docbook_xml_gz_size=`calcsize $outdir/$PACKAGE-db.xml.gz`
|
||||
mv $PACKAGE-db.xml $outdir/
|
||||
|
||||
cmd="${DOCBOOK2HTML} -o $split_html_db_dir ${outdir}/$PACKAGE-db.xml"
|
||||
echo "Generating docbook HTML... ($cmd)"
|
||||
eval "$cmd"
|
||||
split_html_db_dir=html_node_db
|
||||
(
|
||||
cd ${split_html_db_dir} || exit 1
|
||||
tar -czf ../$outdir/${PACKAGE}.html_node_db.tar.gz -- *.html
|
||||
)
|
||||
html_node_db_tgz_size=`calcsize $outdir/${PACKAGE}.html_node_db.tar.gz`
|
||||
rm -f $outdir/html_node_db/*.html
|
||||
mkdir -p $outdir/html_node_db
|
||||
mv ${split_html_db_dir}/*.html $outdir/html_node_db/
|
||||
rmdir ${split_html_db_dir}
|
||||
|
||||
cmd="${DOCBOOK2TXT} ${outdir}/$PACKAGE-db.xml"
|
||||
echo "Generating docbook ASCII... ($cmd)"
|
||||
eval "$cmd"
|
||||
docbook_ascii_size=`calcsize $PACKAGE-db.txt`
|
||||
mv $PACKAGE-db.txt $outdir/
|
||||
|
||||
cmd="${DOCBOOK2PS} ${outdir}/$PACKAGE-db.xml"
|
||||
echo "Generating docbook PS... $(cmd)"
|
||||
eval "$cmd"
|
||||
gzip -f -9 -c $PACKAGE-db.ps >$outdir/$PACKAGE-db.ps.gz
|
||||
docbook_ps_gz_size=`calcsize $outdir/$PACKAGE-db.ps.gz`
|
||||
mv $PACKAGE-db.ps $outdir/
|
||||
|
||||
cmd="${DOCBOOK2PDF} ${outdir}/$PACKAGE-db.xml"
|
||||
echo "Generating docbook PDF... ($cmd)"
|
||||
eval "$cmd"
|
||||
docbook_pdf_size=`calcsize $PACKAGE-db.pdf`
|
||||
mv $PACKAGE-db.pdf $outdir/
|
||||
fi
|
||||
|
||||
echo Writing index file...
|
||||
curdate=`date '+%B %d, %Y'`
|
||||
sed \
|
||||
-e "s!%%TITLE%%!$MANUAL_TITLE!g" \
|
||||
-e "s!%%DATE%%!$curdate!g" \
|
||||
-e "s!%%PACKAGE%%!$PACKAGE!g" \
|
||||
-e "s!%%HTML_MONO_SIZE%%!$html_mono_size!g" \
|
||||
-e "s!%%HTML_MONO_GZ_SIZE%%!$html_mono_gz_size!g" \
|
||||
-e "s!%%HTML_NODE_TGZ_SIZE%%!$html_node_tgz_size!g" \
|
||||
-e "s!%%INFO_TGZ_SIZE%%!$info_tgz_size!g" \
|
||||
-e "s!%%DVI_GZ_SIZE%%!$dvi_gz_size!g" \
|
||||
-e "s!%%PDF_SIZE%%!$pdf_size!g" \
|
||||
-e "s!%%PS_GZ_SIZE%%!$ps_gz_size!g" \
|
||||
-e "s!%%ASCII_SIZE%%!$ascii_size!g" \
|
||||
-e "s!%%ASCII_GZ_SIZE%%!$ascii_gz_size!g" \
|
||||
-e "s!%%TEXI_TGZ_SIZE%%!$texi_tgz_size!g" \
|
||||
-e "s!%%DOCBOOK_HTML_NODE_TGZ_SIZE%%!$html_node_db_tgz_size!g" \
|
||||
-e "s!%%DOCBOOK_ASCII_SIZE%%!$docbook_ascii_size!g" \
|
||||
-e "s!%%DOCBOOK_PS_GZ_SIZE%%!$docbook_ps_gz_size!g" \
|
||||
-e "s!%%DOCBOOK_PDF_SIZE%%!$docbook_pdf_size!g" \
|
||||
-e "s!%%DOCBOOK_XML_SIZE%%!$docbook_xml_size!g" \
|
||||
-e "s!%%DOCBOOK_XML_GZ_SIZE%%!$docbook_xml_gz_size!g" \
|
||||
-e "s,%%SCRIPTURL%%,$scripturl,g" \
|
||||
-e "s!%%SCRIPTNAME%%!$prog!g" \
|
||||
$GENDOCS_TEMPLATE_DIR/gendocs_template >$outdir/index.html
|
||||
|
||||
echo "Done! See $outdir/ subdirectory for new files."
|
||||
|
|
@ -0,0 +1,260 @@
|
|||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
<!-- $Id: gendocs_template,v 1.7 2005/05/15 00:00:08 karl Exp $ -->
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
|
||||
|
||||
<!--
|
||||
|
||||
This template was adapted from Texinfo:
|
||||
http://savannah.gnu.org/cgi-bin/viewcvs/texinfo/texinfo/util/gendocs_template
|
||||
|
||||
-->
|
||||
|
||||
|
||||
<head>
|
||||
<title>%%TITLE%%</title>
|
||||
<meta http-equiv="content-type" content='text/html; charset=utf-8' />
|
||||
<!-- <link rel="stylesheet" type="text/css" href="/gnu.css" /> -->
|
||||
<!-- <link rev="made" href="webmasters@gnu.org" /> -->
|
||||
<style>
|
||||
/* CSS style taken from http://gnu.org/gnu.css */
|
||||
|
||||
html, body {
|
||||
background-color: #FFFFFF;
|
||||
color: #000000;
|
||||
font-family: sans-serif;
|
||||
}
|
||||
|
||||
a:link {
|
||||
color: #1f00ff;
|
||||
background-color: transparent;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
a:visited {
|
||||
color: #9900dd;
|
||||
background-color: transparent;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
color: #9900dd;
|
||||
background-color: transparent;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.center {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.italic {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.bold {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.quote {
|
||||
margin-left: 40px;
|
||||
margin-right: 40px;
|
||||
}
|
||||
|
||||
.hrsmall {
|
||||
width: 80px;
|
||||
height: 1px;
|
||||
margin-left: 20px;
|
||||
}
|
||||
|
||||
.td_title {
|
||||
border-color: #3366cc;
|
||||
border-style: solid;
|
||||
border-width: thin;
|
||||
color: #3366cc;
|
||||
background-color : #f2f2f9;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.td_con {
|
||||
padding-top: 3px;
|
||||
padding-left: 8px;
|
||||
padding-bottom: 3px;
|
||||
color : #303030;
|
||||
background-color : #fefefe;
|
||||
font-size: smaller;
|
||||
}
|
||||
|
||||
.translations {
|
||||
background-color: transparent;
|
||||
color: black;
|
||||
font-family: serif;
|
||||
font-size: smaller;
|
||||
}
|
||||
|
||||
.fsflink {
|
||||
font-size: smaller;
|
||||
font-family: monospace;
|
||||
color : #000000;
|
||||
border-left: #3366cc thin solid;
|
||||
border-bottom: #3366cc thin solid;
|
||||
padding-left: 5px;
|
||||
padding-bottom: 5px;
|
||||
}
|
||||
|
||||
/*
|
||||
* rtl stands for right-to-left layout, as in farsi/persian,
|
||||
* arabic, etc. See also trans_rtl.
|
||||
*/
|
||||
.fsflink_rtl {
|
||||
font-size: smaller;
|
||||
font-family: monospace;
|
||||
color : #000000;
|
||||
border-right: #3366cc thin solid;
|
||||
border-bottom: #3366cc thin solid;
|
||||
padding-right: 5px;
|
||||
padding-bottom: 5px;
|
||||
}
|
||||
|
||||
.trans {
|
||||
font-size: smaller;
|
||||
color : #000000;
|
||||
border-left: #3366cc thin solid;
|
||||
padding-left: 20px;
|
||||
}
|
||||
|
||||
.trans_rtl {
|
||||
font-size: smaller;
|
||||
color : #000000;
|
||||
border-right: #3366cc thin solid;
|
||||
padding-right: 20px;
|
||||
}
|
||||
|
||||
img {
|
||||
border: none 0;
|
||||
}
|
||||
|
||||
td.side {
|
||||
color: #3366cc;
|
||||
/* background: #f2f2f9;
|
||||
border-color: #3366cc;
|
||||
border-style: solid;
|
||||
border-width: thin; */
|
||||
border-color: white;
|
||||
border-style: none;
|
||||
vertical-align: top;
|
||||
width: 150px;
|
||||
}
|
||||
|
||||
div.copyright {
|
||||
font-size: 80%;
|
||||
border: 2px solid #3366cc;
|
||||
padding: 4px;
|
||||
background: #f2f2f9;
|
||||
border-style: solid;
|
||||
border-width: thin;
|
||||
}
|
||||
|
||||
.footnoteref {
|
||||
font-size: smaller;
|
||||
vertical-align: text-top;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<!-- This document is in XML, and xhtml 1.0 -->
|
||||
<!-- Please make sure to properly nest your tags -->
|
||||
<!-- and ensure that your final document validates -->
|
||||
<!-- consistent with W3C xhtml 1.0 and CSS standards -->
|
||||
<!-- See validator.w3.org -->
|
||||
|
||||
<body>
|
||||
|
||||
<h3>%%TITLE%%</h3>
|
||||
|
||||
<!-- <address>Free Software Foundation</address> -->
|
||||
<address>last updated %%DATE%%</address>
|
||||
|
||||
<!--
|
||||
<p>
|
||||
<a href="/graphics/gnu-head.jpg">
|
||||
<img src="/graphics/gnu-head-sm.jpg"
|
||||
alt=" [image of the head of a GNU] "
|
||||
width="129" height="122" />
|
||||
</a>
|
||||
<a href="/philosophy/gif.html">(no gifs due to patent problems)</a>
|
||||
</p>
|
||||
-->
|
||||
|
||||
<hr />
|
||||
|
||||
<p>This document <!--(%%PACKAGE%%)--> is available in the following formats:</p>
|
||||
|
||||
<ul>
|
||||
<li><a href="%%PACKAGE%%.html">HTML
|
||||
(%%HTML_MONO_SIZE%%K characters)</a> - entirely on one web page.</li>
|
||||
<li><a href="html_node/index.html">HTML</a> - with one web page per
|
||||
node.</li>
|
||||
<li><a href="%%PACKAGE%%.html.gz">HTML compressed
|
||||
(%%HTML_MONO_GZ_SIZE%%K gzipped characters)</a> - entirely on
|
||||
one web page.</li>
|
||||
<li><a href="%%PACKAGE%%.html_node.tar.gz">HTML compressed
|
||||
(%%HTML_NODE_TGZ_SIZE%%K gzipped tar file)</a> -
|
||||
with one web page per node.</li>
|
||||
<li><a href="%%PACKAGE%%.info.tar.gz">Info document
|
||||
(%%INFO_TGZ_SIZE%%K characters gzipped tar file)</a>.</li>
|
||||
<li><a href="%%PACKAGE%%.txt">ASCII text
|
||||
(%%ASCII_SIZE%%K characters)</a>.</li>
|
||||
<li><a href="%%PACKAGE%%.txt.gz">ASCII text compressed
|
||||
(%%ASCII_GZ_SIZE%%K gzipped characters)</a>.</li>
|
||||
<li><a href="%%PACKAGE%%.dvi.gz">TeX dvi file
|
||||
(%%DVI_GZ_SIZE%%K characters gzipped)</a>.</li>
|
||||
<li><a href="%%PACKAGE%%.ps.gz">PostScript file
|
||||
(%%PS_GZ_SIZE%%K characters gzipped)</a>.</li>
|
||||
<li><a href="%%PACKAGE%%.pdf">PDF file
|
||||
(%%PDF_SIZE%%K characters)</a>.</li>
|
||||
<li><a href="%%PACKAGE%%.texi.tar.gz">Texinfo source
|
||||
(%%TEXI_TGZ_SIZE%%K characters gzipped tar file)</a></li>
|
||||
</ul>
|
||||
|
||||
<p>(This page was generated by the <a href="%%SCRIPTURL%%">%%SCRIPTNAME%%
|
||||
script</a>.)</p>
|
||||
|
||||
<div class="copyright">
|
||||
<p>
|
||||
Return to <a href="/project/local-time/">local-time's home page</a>.
|
||||
</p>
|
||||
|
||||
<!--
|
||||
<p>
|
||||
Please send FSF & GNU inquiries to
|
||||
<a href="mailto:gnu@gnu.org"><em>gnu@gnu.org</em></a>.
|
||||
There are also <a href="/home.html#ContactInfo">other ways to contact</a>
|
||||
the FSF.
|
||||
<br />
|
||||
Please send broken links and other corrections (or suggestions) to
|
||||
<a href="mailto:webmasters@gnu.org"><em>webmasters@gnu.org</em></a>.
|
||||
</p>
|
||||
-->
|
||||
|
||||
<p>
|
||||
<!--
|
||||
Copyright (C) 2008
|
||||
Daniel Lowe <dlowe dlowe.net>
|
||||
Attila Lendvai <attila.lendvai gmail.com>
|
||||
<br />
|
||||
Verbatim copying and distribution of this entire article is
|
||||
permitted in any medium, provided this notice is preserved.
|
||||
-->
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Updated: %%DATE%%
|
||||
<!-- timestamp start -->
|
||||
<!-- $Date: 2005/05/15 00:00:08 $ $Author: karl $ -->
|
||||
<!-- timestamp end -->
|
||||
</p>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -0,0 +1,774 @@
|
|||
\input texinfo @c -*- Mode: Texinfo; Mode: auto-fill -*-
|
||||
@c %**start of header
|
||||
@setfilename local-time.info
|
||||
@settitle The local-time Manual
|
||||
@exampleindent 2
|
||||
|
||||
@c @documentencoding utf-8
|
||||
|
||||
@macro name {}
|
||||
@code{local-time}
|
||||
@end macro
|
||||
|
||||
@macro mathx {tex, non-tex}
|
||||
@iftex
|
||||
@math{\tex\}
|
||||
@end iftex
|
||||
@ifnottex
|
||||
@emph{\non-tex\}
|
||||
@end ifnottex
|
||||
@end macro
|
||||
|
||||
@macro impnote {text}
|
||||
@quotation Implementor's note
|
||||
@emph{\text\}
|
||||
@end quotation
|
||||
@end macro
|
||||
|
||||
@c Set ROMANCOMMENTS to get comments in roman font.
|
||||
@ifset ROMANCOMMENTS
|
||||
@alias lispcmt = r
|
||||
@end ifset
|
||||
@ifclear ROMANCOMMENTS
|
||||
@alias lispcmt = asis
|
||||
@end ifclear
|
||||
|
||||
@c Index for public api.
|
||||
@defindex it
|
||||
|
||||
@macro pub {name}
|
||||
@itindex \name\
|
||||
@c
|
||||
@end macro
|
||||
|
||||
@macro k {what}
|
||||
@code{\what\}
|
||||
@end macro
|
||||
|
||||
@iftex
|
||||
@alias v = asis
|
||||
@alias cl = code
|
||||
@end iftex
|
||||
|
||||
@ifnottex
|
||||
@alias v = var
|
||||
@alias cl = strong
|
||||
@end ifnottex
|
||||
|
||||
@c Show variables, clauses, and concepts in the same index.
|
||||
@syncodeindex it cp
|
||||
@syncodeindex vr cp
|
||||
|
||||
@copying
|
||||
Copyright @copyright{} 2012 Daniel Lowe <dlowe dlowe.net> @*
|
||||
Copyright @copyright{} 2012 Attila Lendvai <attila.lendvai gmail.com> @*
|
||||
|
||||
@quotation
|
||||
This manual describes the @name{} Common Lisp library which is
|
||||
based on Erik Naggum's @emph{The Long, Painful History of Time}
|
||||
[NaggumPaper] paper.
|
||||
|
||||
@end quotation
|
||||
@end copying
|
||||
@c %**end of header
|
||||
|
||||
@titlepage
|
||||
@title The @name{} Manual
|
||||
@subtitle Version 1.0.0
|
||||
@author Daniel Lowe
|
||||
@author Attila Lendvai
|
||||
|
||||
@page
|
||||
@vskip 0pt plus 1filll
|
||||
@insertcopying
|
||||
@end titlepage
|
||||
|
||||
@contents
|
||||
|
||||
@ifnottex
|
||||
@node Top
|
||||
@top @name{}
|
||||
@insertcopying
|
||||
@end ifnottex
|
||||
|
||||
@menu
|
||||
* Introduction::
|
||||
* Public API::
|
||||
* Other Features::
|
||||
* References::
|
||||
* Comprehensive Index::
|
||||
@end menu
|
||||
|
||||
@c ===================================================================
|
||||
@node Introduction
|
||||
@chapter Introduction
|
||||
|
||||
@menu
|
||||
* Portability::
|
||||
@end menu
|
||||
|
||||
The @name{} library is a Common Lisp library for the manipulation of
|
||||
dates, times and intervals. It was originally based almost entirely
|
||||
upon Erik Naggum's paper @emph{The Long Painful History of Time}
|
||||
[NaggumPaper]. Many of the core concepts originated from this paper,
|
||||
such as the seperation of days and seconds, the choice of 2000-03-01
|
||||
as the standard epoch, and the timestring format.
|
||||
|
||||
@c ===================================================================
|
||||
@node Portability
|
||||
@section Portability
|
||||
|
||||
This implementation assumes that time zone information is stored in
|
||||
the tzfile format. The default timezone is loaded from
|
||||
/etc/localtime. On non-POSIX systems, this will certainly give
|
||||
different results than the system time handling.
|
||||
|
||||
local-time currently supports sub-second precision clocks with ABCL,
|
||||
Allegro, CMUCL, CCL, SBCL, and LispWorks for Linux or Darwin. All
|
||||
others will be able to retrieve the time with second precision using
|
||||
@code{get-universal-time}. You may add support for your own
|
||||
implementation by implementing the clock generic protocol documented
|
||||
here.
|
||||
|
||||
@c ===================================================================
|
||||
@node Public API
|
||||
@chapter Public API
|
||||
|
||||
@menu
|
||||
* Types::
|
||||
* Timezones::
|
||||
* Creating timestamp Objects::
|
||||
* Querying timestamp Objects::
|
||||
* Manipulating Date and Time Values::
|
||||
* Parsing and Formatting::
|
||||
* Clocks::
|
||||
@end menu
|
||||
|
||||
@c ===================================================================
|
||||
@node Types
|
||||
@section Types
|
||||
|
||||
It's a good idea to treat all values as immutable objects. @name{}
|
||||
will not modify any object it was given unless explicitly asked to by
|
||||
the @code{:into} keyword argument.
|
||||
|
||||
@itindex timestamp
|
||||
@deftp Class timestamp day sec nsec
|
||||
|
||||
@code{timestamp} values can represent either a @emph{date},
|
||||
a @emph{daytime} or a @emph{time} value. It has the following slots:
|
||||
|
||||
@lisp
|
||||
(defclass timestamp ()
|
||||
((day :type integer)
|
||||
(sec :type integer)
|
||||
(nsec :type (integer 0 999999999))))
|
||||
@end lisp
|
||||
|
||||
The following constraints apply to the specific types:
|
||||
@itemize
|
||||
|
||||
@item
|
||||
@emph{date}: must have a @var{+utc-zone+} timezone and the @var{sec}
|
||||
slot must be the first second of a day; In other words, the time
|
||||
elements of the @code{timestamp} value must have their least possible
|
||||
values.
|
||||
|
||||
@item
|
||||
@emph{time}: the @var{day} slot must be zero.
|
||||
|
||||
@end itemize
|
||||
@end deftp
|
||||
|
||||
@deftp Struct timezone path name loaded
|
||||
|
||||
@code{timezone} objects represent timezones - local and political
|
||||
modifications to the time representation. Timezones are responsible
|
||||
for storing offsets from GMT, abbreviations for different
|
||||
sub-timezones, and the times each sub-timezone is to be in effect.
|
||||
|
||||
@end deftp
|
||||
|
||||
@c ===================================================================
|
||||
@node Timezones
|
||||
@section Timezones
|
||||
|
||||
@itindex *default-timezone*
|
||||
@defvr Default *default-timezone*
|
||||
|
||||
The variable @var{*default-timezone*} contains the timezone that will
|
||||
be used by default if none is specified. It is loaded from
|
||||
@emph{/etc/localtime} when the library is loaded. If
|
||||
@emph{/etc/localtime} is not present, it will default to UTC.
|
||||
|
||||
@end defvr
|
||||
|
||||
@itindex +utc-zone+
|
||||
@defvr Constant +utc-zone+
|
||||
|
||||
The variable @var{+utc-zone+} contains a timezone corresponding to
|
||||
UTC.
|
||||
|
||||
@end defvr
|
||||
|
||||
|
||||
@itindex define-timezone
|
||||
@defmac define-timezone zone-name zone-file &key (load nil)
|
||||
|
||||
Define @var{zone-name} (a symbol or a string) as a new timezone,
|
||||
lazy-loaded from @var{zone-file} (a pathname designator relative to
|
||||
the zoneinfo directory on this system. If @var{load} is true, load
|
||||
immediately.
|
||||
|
||||
@end defmac
|
||||
|
||||
@itindex find-timezone-by-location-name
|
||||
@defun find-timezone-by-location-name name
|
||||
|
||||
Returns the timezone found at the location name (such as
|
||||
@code{US/Eastern}). @code{reread-timezone-repository} must be called
|
||||
before this function is used.
|
||||
|
||||
@end defun
|
||||
|
||||
@itindex reread-timezone-repository
|
||||
@defun reread-timezone-repository &key (timezone-repository *default-timezone-repository-path*)
|
||||
|
||||
Walks the current repository, reading all tzinfo files updating
|
||||
indexes. The default timezone repository is set to the zoneinfo/
|
||||
directory of the local-time system.
|
||||
|
||||
@end defun
|
||||
|
||||
@c ===================================================================
|
||||
@node Creating timestamp Objects
|
||||
@section Creating @code{timestamp} Objects
|
||||
|
||||
@itindex universal-to-timestamp
|
||||
@defun universal-to-timestamp universal &key (nsec 0)
|
||||
|
||||
Produces a @code{timestamp} instance from the provided universal time
|
||||
@var{universal}. Universal time is defined in the Common Lisp
|
||||
Specification as the number of seconds since 1900-01-01T00:00:00Z.
|
||||
@end defun
|
||||
|
||||
|
||||
@itindex unix-to-timestamp
|
||||
@defun unix-to-timestamp unix &key (nsec 0)
|
||||
|
||||
Produces a @code{timestamp} instance from the provided unix time
|
||||
@var{unix}. Unix time is defined by POSIX as the number of seconds
|
||||
since 1970-01-01T00:00:00Z.
|
||||
@end defun
|
||||
|
||||
|
||||
@itindex now
|
||||
@defun now
|
||||
|
||||
Produces a @code{timestamp} instance with the current time. With
|
||||
Allegro, CMUCL, CCL, SBCL, and LispWorks for Linux or Darwin, the new
|
||||
timestamp will be precise to the microsecond (usec); with ABCL, to the
|
||||
millisecond (ms). Otherwise, the precision is limited to the second.
|
||||
@end defun
|
||||
|
||||
|
||||
@itindex today
|
||||
@defun today
|
||||
|
||||
Produces a @code{timestamp} instance that corresponds to today's
|
||||
date, which is the midnight of the current day in the UTC zone.
|
||||
@end defun
|
||||
|
||||
|
||||
@itindex encode-timestamp
|
||||
@defun encode-timestamp nsec sec minute hour day month year &key timezone offset into
|
||||
|
||||
Returns a new @code{timestamp} instance corresponding to the specified
|
||||
time elements. The @var{offset} is the number of seconds offset from
|
||||
UTC of the locale. If @var{offset} is not specified, the offset will
|
||||
be guessed from the @var{timezone}. If a @code{timestamp} is passed
|
||||
as the @var{into} argument, its value will be set and that
|
||||
@code{timestamp} will be returned. Otherwise, a new @code{timestamp}
|
||||
is created.
|
||||
@end defun
|
||||
|
||||
|
||||
@itindex make-timestamp
|
||||
@defmac make-timestamp &key :day :sec :nsec
|
||||
|
||||
Expands to an expression that creates an instance of a
|
||||
@code{timestamp} exactly as specified.
|
||||
@end defmac
|
||||
|
||||
|
||||
@itindex clone-timestamp
|
||||
@defmac clone-timestamp timestamp
|
||||
|
||||
Expands to an expression that creates another copy of @var{timestamp}
|
||||
that is @code{timestamp=} to it.
|
||||
@end defmac
|
||||
|
||||
|
||||
@c ===================================================================
|
||||
@node Querying timestamp Objects
|
||||
@section Querying @code{timestamp} Objects
|
||||
|
||||
@itindex day-of
|
||||
@defun day-of timestamp
|
||||
|
||||
Returns the day component of @var{timestamp}. Although Naggum's paper
|
||||
specifies that the day should be a signed fixnum, it is left unbounded
|
||||
for flexibility reasons.
|
||||
@end defun
|
||||
|
||||
@itindex sec-of
|
||||
@defun sec-of timestamp
|
||||
|
||||
Returns the 'seconds' component of the time. Valid values for the
|
||||
seconds range from 0 to 86399.
|
||||
@end defun
|
||||
|
||||
@itindex nsec-of
|
||||
@defun nsec-of timestamp
|
||||
|
||||
Returns the 'microseconds' component of the time. Valid values for
|
||||
the nanoseconds range from 0 to 999999999.
|
||||
@end defun
|
||||
|
||||
@itindex timestamp-to-universal
|
||||
@defun timestamp-to-universal timestamp
|
||||
|
||||
This returns the date/time specified in @var{timestamp} encoded as
|
||||
the number of seconds since January 1st, 1900 12:00am UTC.
|
||||
@end defun
|
||||
|
||||
@itindex timestamp-to-unix
|
||||
@defun timestamp-to-unix timestamp
|
||||
|
||||
This returns the date/time specified in @var{timestamp} encoded as
|
||||
the number of seconds since January 1st, 1970 12:00am UTC. It
|
||||
corresponds with the time received from the POSIX call @code{time()}.
|
||||
@end defun
|
||||
|
||||
@itindex timestamp-subtimezone
|
||||
@defun timestamp-subtimezone timestamp timezone
|
||||
|
||||
Returns as multiple values the time zone applicable at the given time
|
||||
as the number of seconds east of UTC, a boolean daylight-saving-p, and
|
||||
the customary abbreviation of the timezone.
|
||||
@end defun
|
||||
|
||||
|
||||
@itindex with-decoded-timestamp
|
||||
@defmac with-decoded-timestamp (&key nsec sec minute hour day month year day-of-week daylight-p timezone) timestamp &body body
|
||||
|
||||
This macro binds variables to the decoded elements of @var{timestamp}.
|
||||
The timezone argument is used for decoding the timestamp, and is not
|
||||
bound by the macro. The value of @var{day-of-week} starts from 0 which
|
||||
means Sunday.
|
||||
@end defmac
|
||||
|
||||
|
||||
@itindex decode-timestamp
|
||||
@defun decode-timestamp timestamp
|
||||
|
||||
Returns the decoded time as @code{(values ns ss mm hh day month
|
||||
year day-of-week daylight-saving-time-p timezone-offset timezone-abbreviation)}.
|
||||
@end defun
|
||||
|
||||
|
||||
@itindex timestamp<
|
||||
@itindex timestamp<=
|
||||
@itindex timestamp>
|
||||
@itindex timestamp>=
|
||||
@itindex timestamp=
|
||||
@itindex timestamp/=
|
||||
@defun timestamp< time-a time-b
|
||||
@defunx timestamp<= time-a time-b
|
||||
@defunx timestamp> time-a time-b
|
||||
@defunx timestamp>= time-a time-b
|
||||
@defunx timestamp= time-a time-b
|
||||
@defunx timestamp/= time-a time-b
|
||||
|
||||
These comparison functions act like their string and char counterparts.
|
||||
@end defun
|
||||
|
||||
|
||||
@itindex timestamp-minimum
|
||||
@defun timestamp-minimum timestamp &rest timestamps
|
||||
|
||||
Returns the earliest timestamp passed to it.
|
||||
@end defun
|
||||
|
||||
|
||||
@itindex timestamp-maximum
|
||||
@defun timestamp-maximum timestamp &rest timestamps
|
||||
|
||||
Returns the latest timestamp passed to it.
|
||||
@end defun
|
||||
|
||||
|
||||
@itindex timestamp-day-of-week
|
||||
@defun timestamp-day-of-week timestamp
|
||||
|
||||
This returns the index of the day of the week,
|
||||
starting at 0 which means Sunday.
|
||||
@quotation Note
|
||||
''Day of the week'' is ambigous and locale dependent.
|
||||
@end quotation
|
||||
@end defun
|
||||
|
||||
|
||||
@itindex universal-to-timestamp
|
||||
@defun universal-to-timestamp timestamp
|
||||
|
||||
Returns the UNIVERSAL-TIME corresponding to @var{timestamp}.
|
||||
@quotation Note
|
||||
Subsecond precision is not preserved.
|
||||
@end quotation
|
||||
@end defun
|
||||
|
||||
|
||||
@itindex timestamp-millennium
|
||||
@itindex timestamp-century
|
||||
@itindex timestamp-decade
|
||||
@defun timestamp-millennium timestamp &key timezone
|
||||
@defunx timestamp-century timestamp &key timezone
|
||||
@defunx timestamp-decade timestamp &key timezone
|
||||
|
||||
Returns the ordinal millennium, century or decade upon which the
|
||||
timestamp falls. Ordinal time values start at 1, so the
|
||||
(timestamp-century (now)) will return 21.
|
||||
|
||||
@end defun
|
||||
|
||||
@itindex timestamp-year
|
||||
@itindex timestamp-month
|
||||
@itindex timestamp-day
|
||||
@itindex timestamp-hour
|
||||
@itindex timestamp-minute
|
||||
@itindex timestamp-second
|
||||
@itindex timestamp-millisecond
|
||||
@itindex timestamp-microsecond
|
||||
@defun timestamp-year timestamp &key timezone
|
||||
@defunx timestamp-month timestamp &key timezone
|
||||
@defunx timestamp-day timestamp &key timezone
|
||||
@defunx timestamp-hour timestamp &key timezone
|
||||
@defunx timestamp-minute timestamp &key timezone
|
||||
@defunx timestamp-second timestamp &key timezone
|
||||
@defunx timestamp-millisecond timestamp &key timezone
|
||||
@defunx timestamp-microsecond timestamp &key timezone
|
||||
@defunx timestamp-microsecond timestamp &key timezone
|
||||
|
||||
Returns the decoded part of the timestamp.
|
||||
@end defun
|
||||
|
||||
|
||||
@c ===================================================================
|
||||
@node Manipulating Date and Time Values
|
||||
@section Manipulating Date and Time Values
|
||||
|
||||
@itindex timestamp+
|
||||
@itindex timestamp-
|
||||
@defun timestamp+ time amount unit
|
||||
@defunx timestamp- time amount unit
|
||||
|
||||
Add or subtract the @var{amount} to the @var{time} using the specified
|
||||
@var{unit}. @var{unit} may be one of ( @code{:nsec} @code{:sec}
|
||||
@code{:minute} @code{:hour} @code{:day} @code{:month} @code{:year}).
|
||||
The value of the parts of the timestamp of higher resolution than the
|
||||
UNIT will never be touched. If you want a precise number of seconds
|
||||
from a time, you should specify the offset in seconds.
|
||||
@end defun
|
||||
|
||||
@itindex timestamp-maximize-part
|
||||
@defun timestamp-maximize-part timestamp part &key offset timezone into
|
||||
|
||||
Returns a timestamp with its parts maximized up to @var{part}. @var{part} can be
|
||||
any of (:nsec :sec :min :hour :day :month). If @var{into} is specified, it
|
||||
will be modified and returned, otherwise a new timestamp will be
|
||||
created.
|
||||
@end defun
|
||||
|
||||
|
||||
@itindex timestamp-minimize-part
|
||||
@defun timestamp-minimize-part timestamp part &key offset timezone into
|
||||
|
||||
Returns a timestamp with its parts minimized up to @var{part}. @var{part} can be
|
||||
any of (:nsec :sec :min :hour :day :month). If @var{into} is specified, it
|
||||
will be modified and returned, otherwise a new timestamp will be
|
||||
created.
|
||||
@end defun
|
||||
|
||||
|
||||
@itindex adjust-timestamp
|
||||
@defmac adjust-timestamp timestamp &body changes
|
||||
|
||||
Alters various parts of @var{timestamp}, given a list of changes. The
|
||||
changes are in the format @code{(offset part value)} and @code{(set
|
||||
part value)}.
|
||||
|
||||
@lisp
|
||||
;; Return a new @code{timestamp} value that points to the Monday in
|
||||
;; the week of @code{(today)}
|
||||
(adjust-timestamp (today) (offset :day-of-week :monday))
|
||||
|
||||
;; Return a new @code{timestamp} value that points three days ahead from now
|
||||
(adjust-timestamp (today) (offset :day 3))
|
||||
@end lisp
|
||||
|
||||
Keep in mind that @code{adjust-timestamp} is not a mere setter for
|
||||
fields but instead it handles overflows and timezone conversions as
|
||||
expected. Also note that it's possible to specify multiple commands.
|
||||
|
||||
The list of possible places to manipulate are: @code{:nsec}
|
||||
@code{:sec} @code{:sec-of-day} @code{:minute} @code{:hour}
|
||||
@code{:day} @code{:day-of-month} @code{:month} @code{:year}.
|
||||
@end defmac
|
||||
|
||||
|
||||
@itindex adjust-timestamp!
|
||||
@defmac adjust-timestamp! timestamp &body changes
|
||||
|
||||
Just like @code{adjust-timestamp}, but instead of returning a freshly
|
||||
constructed value, it alters the provided @var{timestamp} value (and
|
||||
returns it).
|
||||
@end defmac
|
||||
|
||||
|
||||
@itindex timestamp-whole-year-difference
|
||||
@defun timestamp-whole-year-difference time-a time-b
|
||||
|
||||
Returns the number of whole years elapsed between @var{time-a} and @var{time-b}.
|
||||
@quotation Note
|
||||
This is useful for calculating anniversaries and birthdays.
|
||||
@end quotation
|
||||
@end defun
|
||||
|
||||
|
||||
@itindex days-in-month
|
||||
@defun days-in-month month year
|
||||
|
||||
Returns the number of days in a given month of the specified year.
|
||||
@end defun
|
||||
|
||||
|
||||
@c ===================================================================
|
||||
@node Parsing and Formatting
|
||||
@section Parsing and Formatting
|
||||
|
||||
|
||||
@itindex +iso-8601-format+
|
||||
@defvr Constant +iso-8601-format+
|
||||
|
||||
The constant @var{+iso-8601-format+} is bound to a description of the ISO 8601 format. An output with this format will look like this: @samp{2008-03-01T19:42:34.608506+01:00}. This is the default format for the @code{format-timestring} function.
|
||||
|
||||
@end defvr
|
||||
|
||||
@itindex +asctime-format+
|
||||
@defvr Constant +asctime-format+
|
||||
|
||||
The constant @var{+asctime-format+} is bound to a format mirroring the output of the POSIX asctime() function. An output with this format will look like this: @samp{Sat Mar 1 19:42:34 2008}.
|
||||
|
||||
@end defvr
|
||||
|
||||
@itindex +rfc-1123-format+
|
||||
@defvr Constant +rfc-1123-format+
|
||||
|
||||
The constant @var{+rfc-1123-format+} is bound to a description of the format defined in RFC 1123 for Internet timestamps. An output with this format will look like this: @samp{Sat, 01 Mar 2008 19:42:34 -0500}.
|
||||
|
||||
@end defvr
|
||||
|
||||
@itindex +iso-week-date-format+
|
||||
@defvr Constant +iso-week-date-format+
|
||||
|
||||
The constant @var{+iso-week-date-format+} is bound to a description of the ISO 8601 Week Date format. An output with this format will look like this: @samp{2009-W53-5}.
|
||||
|
||||
@end defvr
|
||||
|
||||
@itindex parse-timestring
|
||||
@defun parse-timestring timestring &key (start 0) end (fail-on-error t) (offset 0)
|
||||
|
||||
Parses a timestring and returns the corresponding @code{timestamp}.
|
||||
Parsing begins at @var{start} and stops at the @var{end}
|
||||
position. If there are invalid characters within @code{timestring}
|
||||
and @var{fail-on-error} is @code{T}, then an @code{invalid-timestring}
|
||||
error is signaled, otherwise @code{NIL} is returned.
|
||||
|
||||
If there is no timezone specified in @code{timestring} then
|
||||
@var{offset} is used as the default timezone offset (in seconds).
|
||||
@end defun
|
||||
|
||||
|
||||
@itindex format-timestring
|
||||
@defun format-timestring (destination timestamp &key (format +iso-8601-format+) (timezone *default-timezone*))
|
||||
|
||||
Constructs a string representation of TIMESTAMP according to FORMAT and returns it. If destination is @code{T}, the string is written to @code{*standard-output*}. If destination is a stream, the string is written to the stream.
|
||||
|
||||
FORMAT is a list containing one or more of strings, characters, and keywords. Strings and characters are output literally, while keywords are replaced by the values here:
|
||||
|
||||
@table @code
|
||||
@item :year
|
||||
*year
|
||||
@item :month
|
||||
*numeric month
|
||||
@item :day
|
||||
*day of month
|
||||
@item :weekday
|
||||
*numeric day of week, starting from 0 which means Sunday
|
||||
@item :hour
|
||||
*hour
|
||||
@item :min
|
||||
*minutes
|
||||
@item :sec
|
||||
*seconds
|
||||
@item :msec
|
||||
*milliseconds
|
||||
@item :usec
|
||||
*microseconds
|
||||
@item :nsec
|
||||
*nanoseconds
|
||||
@item :iso-week-year
|
||||
*year for ISO week date (can be different from regular calendar year)
|
||||
@item :iso-week-number
|
||||
*ISO week number (i.e. 1 through 53)
|
||||
@item :iso-week-day
|
||||
*ISO compatible weekday number (i.e. monday=1, sunday=7)
|
||||
@item :ordinal-day
|
||||
day of month as an ordinal (e.g. 1st, 23rd)
|
||||
@item :long-weekday
|
||||
long form of weekday (e.g. Sunday, Monday)
|
||||
@item :short-weekday
|
||||
short form of weekday (e.g. Sun, Mon)
|
||||
@item :minimal-weekday
|
||||
minimal form of weekday (e.g. Su, Mo)
|
||||
@item :short-year
|
||||
short form of year (last 2 digits, e.g. 41, 42 instead of 2041, 2042)
|
||||
@item :long-month
|
||||
long form of month (e.g. January, February)
|
||||
@item :short-month
|
||||
short form of month (e.g. Jan, Feb)
|
||||
@item :hour12
|
||||
hour on a 12-hour clock
|
||||
@item :ampm
|
||||
am/pm marker in lowercase
|
||||
@item :gmt-offset
|
||||
the gmt-offset of the time, in +00:00 form
|
||||
@item :gmt-offset-or-z
|
||||
like :gmt-offset, but is Z when UTC
|
||||
@item :gmt-offset-hhmm
|
||||
like :gmt-offset, but in +0000 form
|
||||
@item :timezone
|
||||
timezone abbrevation for the time
|
||||
@end table
|
||||
|
||||
Elements marked by * can be placed in a list in the form:
|
||||
@lisp
|
||||
(:keyword padding &optional (padchar #\0))
|
||||
@end lisp
|
||||
The string representation of the value will be padded with the padchar.
|
||||
|
||||
You can see examples by examining the values in @var{+iso-8601-format+}, @var{+asctime-format+}, and @var{+rfc-1123-format+}.
|
||||
|
||||
Produces on @var{stream} the timestring corresponding to the @var{timestamp} with
|
||||
the given options. If @var{stream} is @code{nil}, only returns a string containing what
|
||||
would have been the output. If @var{stream} is @code{t}, prints the string to
|
||||
@var{*standard-output*}.
|
||||
|
||||
Example output:
|
||||
@lisp
|
||||
LOCAL-TIME> (format-timestring nil (now))
|
||||
"2008-03-01T19:42:34.608506+01:00"
|
||||
@end lisp
|
||||
@end defun
|
||||
|
||||
|
||||
@itindex format-rfc3339-timestring
|
||||
@defun format-rfc3339-timestring (destination timestamp &key omit-date-part omit-time-part omit-timezone-part (use-zulu t))
|
||||
|
||||
Formats the time like format-timestring, but in RFC 3339 format. The options control valid options in the RFC.
|
||||
@end defun
|
||||
|
||||
|
||||
@itindex format-rfc1123-timestring
|
||||
@defun format-rfc1123-timestring (destination timestamp &key (timezone *default-timezone*))
|
||||
|
||||
Formats the time like format-timestring, but in RFC 1123 format.
|
||||
@end defun
|
||||
|
||||
@c ===================================================================
|
||||
@node Clocks
|
||||
@section Clocks
|
||||
|
||||
@defvr Default *clock*
|
||||
|
||||
The *clock* special variable and the following generic functions are
|
||||
exposed so that applications may re-define the current time or date as
|
||||
required. This can be used for testing or to support alternate clocks.
|
||||
|
||||
The currently supported values are:
|
||||
|
||||
@itemize
|
||||
@item @code{t} - Use the standard system clock with no adjustments
|
||||
@item @code{leap-second-adjusted} - The system clock, adjusted for leap seconds using the information in *default-timezone*.
|
||||
@end itemize
|
||||
|
||||
@end defvr
|
||||
|
||||
@defun clock-now (clock)
|
||||
|
||||
Specialize this generic function to re-define the present moment
|
||||
@end defun
|
||||
|
||||
@defun clock-today (clock)
|
||||
|
||||
Specialize this generic function to re-define the present day
|
||||
@end defun
|
||||
|
||||
@c ===================================================================
|
||||
@node Other Features
|
||||
@chapter Other Features
|
||||
|
||||
@section Reader Macros
|
||||
|
||||
@itindex enable-read-macros
|
||||
@defun enable-read-macros
|
||||
|
||||
Adds @@TIMESTRING and #@@UNIVERSAL-TIME as reader macros.
|
||||
@end defun
|
||||
|
||||
|
||||
@section Support for non-Gregorian Calendars
|
||||
|
||||
@itindex astronomical-julian-date
|
||||
@defun astronomical-julian-date timestamp
|
||||
|
||||
Returns the julian date of the date portion of @var{timestamp}.
|
||||
@end defun
|
||||
|
||||
|
||||
@itindex modified-julian-date
|
||||
@defun astronomical-julian-date timestamp
|
||||
|
||||
Returns the modified julian date of the date portion of @var{timestamp}.
|
||||
@end defun
|
||||
|
||||
@c ===================================================================
|
||||
@node References
|
||||
@chapter References
|
||||
|
||||
@itemize
|
||||
|
||||
@item
|
||||
[NaggumPaper] Erik Naggum. @emph{The Long Painful History of Time}
|
||||
@url{http://naggum.no/lugm-time.html}, 1999.
|
||||
|
||||
@end itemize
|
||||
|
||||
|
||||
@c ===================================================================
|
||||
@node Comprehensive Index
|
||||
@unnumbered Index
|
||||
@printindex cp
|
||||
|
||||
@bye
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
body {font-family: century schoolbook, serif;
|
||||
line-height: 1.3;
|
||||
padding-left: 5em; padding-right: 1em;
|
||||
padding-bottom: 1em; max-width: 60em;}
|
||||
table {border-collapse: collapse}
|
||||
span.roman { font-family: century schoolbook, serif; font-weight: normal; }
|
||||
h1, h2, h3, h4, h5, h6 {font-family: Helvetica, sans-serif}
|
||||
/*h4 {padding-top: 0.75em;}*/
|
||||
dfn {font-family: inherit; font-variant: italic; font-weight: bolder }
|
||||
kbd {font-family: monospace; text-decoration: underline}
|
||||
/*var {font-family: Helvetica, sans-serif; font-variant: slanted}*/
|
||||
var {font-variant: slanted;}
|
||||
td {padding-right: 1em; padding-left: 1em}
|
||||
sub {font-size: smaller}
|
||||
.node {padding: 0; margin: 0}
|
||||
|
||||
.lisp { font-family: monospace;
|
||||
background-color: #F4F4F4; border: 1px solid #AAA;
|
||||
padding-top: 0.5em; padding-bottom: 0.5em; }
|
||||
|
||||
/* coloring */
|
||||
|
||||
.lisp-bg { background-color: #F4F4F4 ; color: black; }
|
||||
.lisp-bg:hover { background-color: #F4F4F4 ; color: black; }
|
||||
|
||||
.symbol { font-weight: bold; color: #770055; background-color : transparent; border: 0px; margin: 0px;}
|
||||
a.symbol:link { font-weight: bold; color : #229955; background-color : transparent; text-decoration: none; border: 0px; margin: 0px; }
|
||||
a.symbol:active { font-weight: bold; color : #229955; background-color : transparent; text-decoration: none; border: 0px; margin: 0px; }
|
||||
a.symbol:visited { font-weight: bold; color : #229955; background-color : transparent; text-decoration: none; border: 0px; margin: 0px; }
|
||||
a.symbol:hover { font-weight: bold; color : #229955; background-color : transparent; text-decoration: none; border: 0px; margin: 0px; }
|
||||
.special { font-weight: bold; color: #FF5000; background-color: inherit; }
|
||||
.keyword { font-weight: bold; color: #770000; background-color: inherit; }
|
||||
.comment { font-weight: normal; color: #007777; background-color: inherit; }
|
||||
.string { font-weight: bold; color: #777777; background-color: inherit; }
|
||||
.character { font-weight: bold; color: #0055AA; background-color: inherit; }
|
||||
.syntaxerror { font-weight: bold; color: #FF0000; background-color: inherit; }
|
||||
span.paren1 { font-weight: bold; color: #777777; }
|
||||
span.paren1:hover { color: #777777; background-color: #BAFFFF; }
|
||||
span.paren2 { color: #777777; }
|
||||
span.paren2:hover { color: #777777; background-color: #FFCACA; }
|
||||
span.paren3 { color: #777777; }
|
||||
span.paren3:hover { color: #777777; background-color: #FFFFBA; }
|
||||
span.paren4 { color: #777777; }
|
||||
span.paren4:hover { color: #777777; background-color: #CACAFF; }
|
||||
span.paren5 { color: #777777; }
|
||||
span.paren5:hover { color: #777777; background-color: #CAFFCA; }
|
||||
span.paren6 { color: #777777; }
|
||||
span.paren6:hover { color: #777777; background-color: #FFBAFF; }
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
(defsystem "local-time"
|
||||
:version "1.0.6"
|
||||
:license "BSD"
|
||||
:author "Daniel Lowe <dlowe@dlowe.net>"
|
||||
:description "A library for manipulating dates and times, based on a paper by Erik Naggum"
|
||||
:depends-on (:cl-fad)
|
||||
:in-order-to ((test-op (test-op "local-time/test")))
|
||||
:components ((:module "src"
|
||||
:serial t
|
||||
:components ((:file "package")
|
||||
(:file "local-time")))))
|
||||
|
||||
(defsystem "local-time/test"
|
||||
:version "1.0.6"
|
||||
:author "Daniel Lowe <dlowe@dlowe.net>"
|
||||
:description "Testing code for the local-time library"
|
||||
:depends-on (:stefil
|
||||
:local-time)
|
||||
:perform (test-op (o s) (uiop:symbol-call '#:stefil
|
||||
'#:funcall-test-with-feedback-message
|
||||
(uiop:find-symbol* '#:test '#:local-time.test)))
|
||||
:components ((:module "test"
|
||||
:serial t
|
||||
:components ((:file "package")
|
||||
(:file "simple")
|
||||
(:file "comparison")
|
||||
(:file "formatting")
|
||||
(:file "parsing")
|
||||
(:file "timezone")))))
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
(in-package :local-time)
|
||||
|
||||
(export 'set-local-time-cl-postgres-readers :local-time)
|
||||
|
||||
;; Postgresql days are measured from 2000-01-01, whereas local-time
|
||||
;; uses 2000-03-01. We expect the database server to be in the UTC timezone.
|
||||
(defconstant +postgres-day-offset-to-local-time+ -60)
|
||||
|
||||
(defun set-local-time-cl-postgres-readers (&optional (table cl-postgres:*sql-readtable*))
|
||||
(flet ((timestamp-reader (usecs)
|
||||
(multiple-value-bind (days usecs)
|
||||
(floor usecs +usecs-per-day+)
|
||||
(multiple-value-bind (secs usecs)
|
||||
(floor usecs 1000000)
|
||||
(local-time:make-timestamp :nsec (* usecs 1000)
|
||||
:sec secs
|
||||
:day (+ days +postgres-day-offset-to-local-time+))))))
|
||||
(cl-postgres:set-sql-datetime-readers
|
||||
:table table
|
||||
:date (lambda (days)
|
||||
(local-time:make-timestamp
|
||||
:nsec 0 :sec 0
|
||||
:day (+ days +postgres-day-offset-to-local-time+)))
|
||||
:timestamp #'timestamp-reader
|
||||
:timestamp-with-timezone #'timestamp-reader
|
||||
:interval
|
||||
(lambda (months days usecs)
|
||||
(declare (ignore months days usecs))
|
||||
(error "Intervals are not yet supported"))
|
||||
:time
|
||||
(lambda (usecs)
|
||||
(multiple-value-bind (days usecs)
|
||||
(floor usecs +usecs-per-day+)
|
||||
(assert (= days 0))
|
||||
(multiple-value-bind (secs usecs)
|
||||
(floor usecs 1000000)
|
||||
(let ((time-of-day (local-time:make-timestamp
|
||||
:nsec (* usecs 1000)
|
||||
:sec secs
|
||||
:day 0)))
|
||||
(check-type time-of-day time-of-day)
|
||||
time-of-day)))))))
|
||||
|
||||
(defmethod cl-postgres:to-sql-string ((arg local-time:timestamp))
|
||||
(format nil "'~a'"
|
||||
(local-time:format-rfc3339-timestring nil arg :timezone +utc-zone+)))
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -0,0 +1,91 @@
|
|||
(defpackage #:local-time
|
||||
(:use #:cl)
|
||||
(:export #:timestamp
|
||||
#:date
|
||||
#:time-of-day
|
||||
#:make-timestamp
|
||||
#:clone-timestamp
|
||||
#:day-of
|
||||
#:sec-of
|
||||
#:nsec-of
|
||||
#:timestamp<
|
||||
#:timestamp<=
|
||||
#:timestamp>
|
||||
#:timestamp>=
|
||||
#:timestamp=
|
||||
#:timestamp/=
|
||||
#:timestamp-maximum
|
||||
#:timestamp-minimum
|
||||
#:adjust-timestamp
|
||||
#:adjust-timestamp!
|
||||
#:timestamp-whole-year-difference
|
||||
#:days-in-month
|
||||
#:timestamp-
|
||||
#:timestamp+
|
||||
#:timestamp-difference
|
||||
#:timestamp-minimize-part
|
||||
#:timestamp-maximize-part
|
||||
#:with-decoded-timestamp
|
||||
#:decode-timestamp
|
||||
#:timestamp-century
|
||||
#:timestamp-day
|
||||
#:timestamp-day-of-week
|
||||
#:timestamp-decade
|
||||
#:timestamp-hour
|
||||
#:timestamp-microsecond
|
||||
#:timestamp-millennium
|
||||
#:timestamp-millisecond
|
||||
#:timestamp-minute
|
||||
#:timestamp-month
|
||||
#:timestamp-second
|
||||
#:timestamp-week
|
||||
#:timestamp-year
|
||||
#:parse-timestring
|
||||
#:format-timestring
|
||||
#:format-rfc1123-timestring
|
||||
#:to-rfc1123-timestring
|
||||
#:format-rfc3339-timestring
|
||||
#:to-rfc3339-timestring
|
||||
#:encode-timestamp
|
||||
#:parse-rfc3339-timestring
|
||||
#:universal-to-timestamp
|
||||
#:timestamp-to-universal
|
||||
#:unix-to-timestamp
|
||||
#:timestamp-to-unix
|
||||
#:timestamp-subtimezone
|
||||
#:define-timezone
|
||||
#:*default-timezone*
|
||||
#:*clock*
|
||||
#:leap-second-adjusted
|
||||
#:clock-now
|
||||
#:clock-today
|
||||
#:find-timezone-by-location-name
|
||||
#:reread-timezone-repository
|
||||
#:now
|
||||
#:today
|
||||
#:enable-read-macros
|
||||
#:+utc-zone+
|
||||
#:+gmt-zone+
|
||||
#:+month-names+
|
||||
#:+short-month-names+
|
||||
#:+day-names+
|
||||
#:+short-day-names+
|
||||
#:+seconds-per-day+
|
||||
#:+seconds-per-hour+
|
||||
#:+seconds-per-minute+
|
||||
#:+minutes-per-day+
|
||||
#:+minutes-per-hour+
|
||||
#:+hours-per-day+
|
||||
#:+days-per-week+
|
||||
#:+months-per-year+
|
||||
#:+iso-8601-format+
|
||||
#:+iso-8601-date-format+
|
||||
#:+iso-8601-time-format+
|
||||
#:+rfc3339-format+
|
||||
#:+rfc3339-format/date-only+
|
||||
#:+asctime-format+
|
||||
#:+rfc-1123-format+
|
||||
#:+iso-week-date-format+
|
||||
#:astronomical-julian-date
|
||||
#:modified-julian-date
|
||||
#:astronomical-modified-julian-date))
|
||||
|
|
@ -0,0 +1,128 @@
|
|||
(in-package #:local-time.test)
|
||||
|
||||
(defsuite* (comparison :in simple))
|
||||
|
||||
(defmacro defcmptest (comparator-name &body args)
|
||||
`(deftest ,(symbolicate 'test/simple/comparison/ comparator-name) ()
|
||||
(flet ((make (day &optional (sec 0) (nsec 0))
|
||||
(make-timestamp :day day :sec sec :nsec nsec)))
|
||||
,@(loop
|
||||
:for entry :in args
|
||||
:when (= (length entry) 1)
|
||||
:do (push 'is entry)
|
||||
:else
|
||||
:do (if (member (car entry) '(t true is) :test #'eq)
|
||||
'is
|
||||
'is)
|
||||
collect (let ((body `(,comparator-name (make ,@(second entry))
|
||||
(make ,@(third entry)))))
|
||||
(cond
|
||||
((eq (car entry) 'true)
|
||||
`(is ,body))
|
||||
((eq (car entry) 'false)
|
||||
`(is (not ,body)))
|
||||
(t (error "Don't know how to interpret ~S" entry))))))))
|
||||
|
||||
(defcmptest timestamp<
|
||||
(true (1 0 0)
|
||||
(2 0 0))
|
||||
(true (0 1 0)
|
||||
(0 2 0))
|
||||
(true (0 0 1)
|
||||
(0 0 2))
|
||||
|
||||
(false (2 0 0)
|
||||
(1 0 0))
|
||||
(false (0 2 0)
|
||||
(0 1 0))
|
||||
(false (0 0 2)
|
||||
(0 0 1)))
|
||||
|
||||
(defcmptest timestamp<=
|
||||
(true (1 0 0)
|
||||
(2 0 0))
|
||||
(true (0 1 0)
|
||||
(0 2 0))
|
||||
(true (0 0 1)
|
||||
(0 0 2))
|
||||
(true (1 0 0)
|
||||
(1 0 0))
|
||||
(true (1 1 0)
|
||||
(1 1 0))
|
||||
(true (1 1 1)
|
||||
(1 1 1))
|
||||
|
||||
(false (2 0 0)
|
||||
(1 0 0))
|
||||
(false (0 2 0)
|
||||
(0 1 0))
|
||||
(false (0 0 2)
|
||||
(0 0 1)))
|
||||
|
||||
(defcmptest timestamp>
|
||||
(true (2 0 0)
|
||||
(1 0 0))
|
||||
(true (0 2 0)
|
||||
(0 1 0))
|
||||
(true (0 0 2)
|
||||
(0 0 1))
|
||||
|
||||
(false (1 0 0)
|
||||
(2 0 0))
|
||||
(false (0 1 0)
|
||||
(0 2 0))
|
||||
(false (0 0 1)
|
||||
(0 0 2)))
|
||||
|
||||
(defcmptest timestamp>=
|
||||
(true (2 0 0)
|
||||
(1 0 0))
|
||||
(true (0 2 0)
|
||||
(0 1 0))
|
||||
(true (0 0 2)
|
||||
(0 0 1))
|
||||
(true (1 0 0)
|
||||
(1 0 0))
|
||||
(true (1 1 0)
|
||||
(1 1 0))
|
||||
(true (1 1 1)
|
||||
(1 1 1))
|
||||
|
||||
(false (1 0 0)
|
||||
(2 0 0))
|
||||
(false (0 1 0)
|
||||
(0 2 0))
|
||||
(false (0 0 1)
|
||||
(0 0 2)))
|
||||
|
||||
(defcmptest timestamp=
|
||||
(true (1 0 0)
|
||||
(1 0 0))
|
||||
(true (1 1 0)
|
||||
(1 1 0))
|
||||
(true (1 1 1)
|
||||
(1 1 1))
|
||||
|
||||
(false (1 0 0)
|
||||
(2 0 0))
|
||||
(false (0 1 0)
|
||||
(0 2 0))
|
||||
(false (0 0 1)
|
||||
(0 0 2)))
|
||||
|
||||
(deftest test/simple/comparison/timestamp=/2 ()
|
||||
(is (timestamp= (make-timestamp) (make-timestamp)))
|
||||
(is (not (timestamp= (make-timestamp) (make-timestamp :nsec 1)))))
|
||||
|
||||
(deftest test/simple/comparison/timestamp=/3 ()
|
||||
(is (eql (handler-case
|
||||
(timestamp= (make-timestamp) nil)
|
||||
(type-error ()
|
||||
:correct-error))
|
||||
:correct-error)))
|
||||
|
||||
(deftest test/simple/comparison/timestamp/= ()
|
||||
(is (timestamp/= (make-timestamp :nsec 1) (make-timestamp :nsec 2)))
|
||||
(is (timestamp/= (make-timestamp :nsec 1) (make-timestamp :nsec 2) (make-timestamp :nsec 3)))
|
||||
(is (not (timestamp/= (make-timestamp :nsec 1) (make-timestamp :nsec 2) (make-timestamp :nsec 1))))
|
||||
(is (not (timestamp/= (make-timestamp) (make-timestamp)))))
|
||||
|
|
@ -0,0 +1,97 @@
|
|||
(in-package #:local-time.test)
|
||||
|
||||
(defsuite* (formatting :in test))
|
||||
|
||||
(deftest test/formatting/format-timestring/1 ()
|
||||
(let ((*default-timezone* local-time:+utc-zone+)
|
||||
(test-timestamp (encode-timestamp 1000 2 3 4 5 6 2008 :offset 0)))
|
||||
(macrolet ((frob (&rest args)
|
||||
`(progn
|
||||
,@(loop
|
||||
:for (a b) :on args :by #'cddr
|
||||
:collect `(is (string= ,a ,b))))))
|
||||
(frob
|
||||
"2008-06-05T04:03:02.000001Z"
|
||||
(format-timestring nil test-timestamp)
|
||||
|
||||
"2008-06-05T04:03:02.000001-05:00"
|
||||
(let ((utc-5 (local-time::%make-simple-timezone "UTC-5" "UTC-5" -18000)))
|
||||
(format-timestring nil (encode-timestamp 1000 2 3 4 5 6 2008
|
||||
:offset (* 3600 -5))
|
||||
:timezone utc-5))
|
||||
|
||||
"Thu Jun 5 04:03:02 2008"
|
||||
(format-timestring nil test-timestamp :format +asctime-format+)
|
||||
|
||||
"Thu, 05 Jun 2008 04:03:02 +0000"
|
||||
(format-timestring nil test-timestamp :format +rfc-1123-format+)
|
||||
|
||||
""
|
||||
(format-timestring nil test-timestamp
|
||||
:format nil)
|
||||
|
||||
"04"
|
||||
(format-timestring nil test-timestamp
|
||||
:format '((:hour 2)))
|
||||
|
||||
"04:03"
|
||||
(format-timestring nil test-timestamp
|
||||
:format '((:hour 2) #\: (:min 2)))
|
||||
|
||||
"5th"
|
||||
(format-timestring nil test-timestamp
|
||||
:format '(:ordinal-day))
|
||||
|
||||
"2004-W53-6"
|
||||
(format-timestring nil (encode-timestamp 0 0 0 0 1 1 2005)
|
||||
:format +iso-week-date-format+)
|
||||
|
||||
"2004-W53-7"
|
||||
(format-timestring nil (encode-timestamp 0 0 0 0 2 1 2005)
|
||||
:format +iso-week-date-format+)
|
||||
|
||||
"2005-W52-6"
|
||||
(format-timestring nil (encode-timestamp 0 0 0 0 31 12 2005)
|
||||
:format +iso-week-date-format+)
|
||||
|
||||
"2007-W01-1"
|
||||
(format-timestring nil (encode-timestamp 0 0 0 0 1 1 2007)
|
||||
:format +iso-week-date-format+)
|
||||
|
||||
"2007-W52-7"
|
||||
(format-timestring nil (encode-timestamp 0 0 0 0 30 12 2007)
|
||||
:format +iso-week-date-format+)
|
||||
|
||||
"2008-W01-1"
|
||||
(format-timestring nil (encode-timestamp 0 0 0 0 31 12 2007)
|
||||
:format +iso-week-date-format+)
|
||||
|
||||
"2009-W53-5"
|
||||
(format-timestring nil (encode-timestamp 0 0 0 0 1 1 2010)
|
||||
:format +iso-week-date-format+)
|
||||
|
||||
"2009-W01-3"
|
||||
(format-timestring nil (encode-timestamp 0 0 0 0 31 12 2008)
|
||||
:format +iso-week-date-format+)))))
|
||||
|
||||
(deftest test/formatting/format-timestring/2 ()
|
||||
(with-output-to-string (*standard-output*)
|
||||
(let ((*default-timezone* (find-timezone-by-location-name "UTC")))
|
||||
(finishes (print (now))))))
|
||||
|
||||
(deftest test/formatting/ordinals ()
|
||||
(flet ((format-ordinal (day)
|
||||
(format-timestring nil (encode-timestamp 0 0 0 0 day 1 2008)
|
||||
:format '(:ordinal-day))))
|
||||
(string= "31st" (format-ordinal 31))
|
||||
(string= "11th" (format-ordinal 11))
|
||||
(string= "22nd" (format-ordinal 22))
|
||||
(string= "3rd" (format-ordinal 3))))
|
||||
|
||||
(deftest test/formatting/bug/1 ()
|
||||
(let ((*default-timezone* (find-timezone-by-location-name "Pacific/Auckland")))
|
||||
(finishes (format-timestring nil (now)))))
|
||||
|
||||
(deftest test/formatting/leap-year ()
|
||||
(let ((timestamp (parse-timestring "2004-02-29")))
|
||||
(is (timestamp= timestamp (parse-timestring (format-timestring nil timestamp))))))
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
(cl:in-package :cl-user)
|
||||
|
||||
(defpackage :local-time.test
|
||||
(:use :alexandria
|
||||
:common-lisp
|
||||
:stefil
|
||||
:local-time))
|
||||
|
||||
(in-package :local-time.test)
|
||||
|
||||
(defsuite* (test :in root-suite) ()
|
||||
(local-time::reread-timezone-repository)
|
||||
(run-child-tests))
|
||||
|
|
@ -0,0 +1,79 @@
|
|||
(in-package #:local-time.test)
|
||||
|
||||
(defsuite* (parsing :in test))
|
||||
|
||||
(deftest test/parsing/parse-format-consistency/range (&key (start-day -100000) (end-day 100000))
|
||||
(declare (optimize debug))
|
||||
(without-test-progress-printing
|
||||
(loop
|
||||
:with time = (make-timestamp)
|
||||
:for day :from start-day :upto end-day
|
||||
:for index :upfrom 0 :do
|
||||
(setf (day-of time) day)
|
||||
(when (zerop (mod index 10000))
|
||||
(print time))
|
||||
(let ((parsed (parse-timestring (format-timestring nil time))))
|
||||
(is (timestamp= parsed time))))))
|
||||
|
||||
(deftest test/parsing/parse-format-consistency ()
|
||||
(flet ((compare (nsec sec min hour day mon year str
|
||||
&key start end offset
|
||||
(allow-missing-elements t))
|
||||
(let* ((timestamp-a (encode-timestamp nsec sec min hour
|
||||
day mon year :offset offset))
|
||||
(used-offset (or offset
|
||||
(local-time::%guess-offset (sec-of timestamp-a)
|
||||
(day-of timestamp-a))))
|
||||
(timestamp-b (parse-timestring str
|
||||
:start start
|
||||
:end end
|
||||
:allow-missing-elements
|
||||
allow-missing-elements
|
||||
:offset used-offset)))
|
||||
(is (timestamp= timestamp-a timestamp-b)))))
|
||||
(let ((timestamp (now)))
|
||||
(is (timestamp= timestamp
|
||||
(parse-timestring
|
||||
(format-timestring nil timestamp)))))
|
||||
|
||||
(let* ((*default-timezone* (find-timezone-by-location-name "Europe/Budapest")))
|
||||
(compare 0 0 0 0 1 1 1 "0001-01-01T00:00:00,0"))
|
||||
|
||||
(compare 0 0 0 0 1 1 1 "0001-01-01T00:00:00Z" :offset 0)
|
||||
|
||||
(compare 0 0 0 0 1 1 2006 "2006-01-01T00:00:00,0")
|
||||
(compare 0 0 0 0 1 1 2006 "xxxx 2006-01-01T00:00:00,0 xxxx"
|
||||
:start 5
|
||||
:end 15)
|
||||
|
||||
(is (eql (day-of (parse-timestring "2006-06-06TZ")) 2288))
|
||||
|
||||
(compare 20000000 3 4 5 6 7 2008 "2008-07-06T05:04:03,02")
|
||||
(compare 0 2 0 0 23 3 2000 "--23T::02" :allow-missing-elements t)
|
||||
(compare 80000000 7 6 5 1 3 2000 "T05:06:07,08" :allow-missing-elements t)
|
||||
(compare 940703000 28 56 16 20 2 2008 "2008-02-20T16:56:28.940703Z"
|
||||
:offset 0)))
|
||||
|
||||
(deftest test/parsing/split ()
|
||||
(is (equal (local-time::%split-timestring "2006-01-02T03:04:05,6-05")
|
||||
'(2006 1 2 3 4 5 600000000 -5 0)))
|
||||
(is (equal (local-time::%split-timestring "2006-01-02T03:04:05,6-0515")
|
||||
'(2006 1 2 3 4 5 600000000 -5 -15)))
|
||||
(is (equal (local-time::%split-timestring "2006-01-02T03:04:05,6-05:15")
|
||||
'(2006 1 2 3 4 5 600000000 -5 -15))))
|
||||
|
||||
|
||||
(deftest test/parsing/reader ()
|
||||
(let ((now (now)))
|
||||
(setf (nsec-of now) 123456000)
|
||||
(is (timestamp= now
|
||||
(with-input-from-string (ins (format-timestring nil now))
|
||||
(local-time::%read-timestring ins #\@))))))
|
||||
|
||||
(deftest test/parsing/read-universal-time ()
|
||||
(let ((now (now)))
|
||||
(setf (nsec-of now) 0)
|
||||
(is (timestamp= now
|
||||
(with-input-from-string (ins (princ-to-string (timestamp-to-universal now)))
|
||||
(local-time::%read-universal-time ins #\@ nil))))))
|
||||
|
||||
|
|
@ -0,0 +1,284 @@
|
|||
(in-package #:local-time.test)
|
||||
|
||||
(defsuite* (simple :in test))
|
||||
|
||||
(eval-when (:compile-toplevel :load-toplevel :execute)
|
||||
(local-time::define-timezone eastern-tz
|
||||
(merge-pathnames #p"US/Eastern" local-time::*default-timezone-repository-path*))
|
||||
(local-time::define-timezone amsterdam-tz
|
||||
(merge-pathnames #p"Europe/Amsterdam" local-time::*default-timezone-repository-path*)))
|
||||
|
||||
(deftest test/simple/make-timestamp ()
|
||||
(let ((timestamp (make-timestamp :nsec 1 :sec 2 :day 3)))
|
||||
(is (= (nsec-of timestamp) 1))
|
||||
(is (= (sec-of timestamp) 2))
|
||||
(is (= (day-of timestamp) 3))))
|
||||
|
||||
(deftest test/simple/read-binary-integer ()
|
||||
(let ((tmp-file-path #p"/tmp/local-time-test"))
|
||||
(with-open-file (ouf tmp-file-path
|
||||
:direction :output
|
||||
:element-type 'unsigned-byte
|
||||
:if-exists :supersede)
|
||||
(dotimes (i 14)
|
||||
(write-byte 200 ouf)))
|
||||
(with-open-file (inf tmp-file-path :element-type 'unsigned-byte)
|
||||
(is (eql (local-time::%read-binary-integer inf 1) 200))
|
||||
(is (eql (local-time::%read-binary-integer inf 1 t) -56))
|
||||
(is (eql (local-time::%read-binary-integer inf 2) 51400))
|
||||
(is (eql (local-time::%read-binary-integer inf 2 t) -14136))
|
||||
(is (eql (local-time::%read-binary-integer inf 4) 3368601800))
|
||||
(is (eql (local-time::%read-binary-integer inf 4 t) -926365496)))))
|
||||
|
||||
(deftest test/simple/encode-timestamp ()
|
||||
(macrolet ((entry ((&rest encode-timestamp-args)
|
||||
day sec nsec)
|
||||
`(let ((timestamp (encode-timestamp ,@encode-timestamp-args)))
|
||||
(is (= (day-of timestamp) ,day))
|
||||
(is (= (sec-of timestamp) ,sec))
|
||||
(is (= (nsec-of timestamp) ,nsec)))))
|
||||
(entry (0 0 0 0 1 3 2000 :offset 0)
|
||||
0 0 0)
|
||||
(entry (0 0 0 0 29 2 2000 :offset 0)
|
||||
-1 0 0)
|
||||
(entry (0 0 0 0 2 3 2000 :offset 0)
|
||||
1 0 0)
|
||||
(entry (0 0 0 0 1 1 2000 :offset 0)
|
||||
-60 0 0)
|
||||
(entry (0 0 0 0 1 3 2001 :offset 0)
|
||||
365 0 0)))
|
||||
|
||||
(defmacro encode-decode-test (args &body body)
|
||||
`(let ((timestamp (encode-timestamp ,@(subseq args 0 7) :offset 0)))
|
||||
(is (equal '(,@args ,@(let ((stars nil))
|
||||
(dotimes (n (- 7 (length args)))
|
||||
(push '* stars))
|
||||
stars))
|
||||
(multiple-value-list
|
||||
(decode-timestamp timestamp :timezone local-time:+utc-zone+))))
|
||||
,@body))
|
||||
|
||||
(deftest test/simple/encode-decode-consistency/1 ()
|
||||
(encode-decode-test (5 5 5 5 5 5 1990 6 nil 0 "UTC"))
|
||||
(encode-decode-test (0 0 0 0 1 3 2001 4 nil 0 "UTC"))
|
||||
(encode-decode-test (0 0 0 0 1 3 1998 0 nil 0 "UTC"))
|
||||
(encode-decode-test (1 2 3 4 5 6 2008 4 nil 0 "UTC"))
|
||||
(encode-decode-test (0 0 0 0 1 1 1 1 nil 0 "UTC")))
|
||||
|
||||
(deftest test/simple/encode-decode-consistency/random ()
|
||||
(loop :repeat 1000 :do
|
||||
(let ((timestamp (make-timestamp :day (- (random 65535) 36767)
|
||||
:sec (random 86400)
|
||||
:nsec (random 1000000000))))
|
||||
(multiple-value-bind (ns ss mm hh day month year)
|
||||
(decode-timestamp timestamp :timezone local-time:+utc-zone+)
|
||||
(is (timestamp= timestamp
|
||||
(encode-timestamp ns ss mm hh day month year :offset 0)))))))
|
||||
|
||||
;;;;;;
|
||||
;;; TODO the rest is uncategorized, just simply converted from the old 5am suite
|
||||
|
||||
(deftest test/timestamp-conversions ()
|
||||
(is (eql 0 (timestamp-to-unix
|
||||
(encode-timestamp 0 0 0 0 1 1 1970 :offset 0))))
|
||||
(is (equal (values 2 3 4 5 6 2008 3 * *)
|
||||
(decode-universal-time
|
||||
(timestamp-to-universal
|
||||
(encode-timestamp 1 2 3 4 5 6 2008 :offset 0)) 0)))
|
||||
(let ((now (now)))
|
||||
(setf (nsec-of now) 0)
|
||||
(is (timestamp= now
|
||||
(unix-to-timestamp (timestamp-to-unix now)))))
|
||||
(let ((now (get-universal-time)))
|
||||
(is (equal now
|
||||
(timestamp-to-universal (universal-to-timestamp now))))))
|
||||
|
||||
(deftest test/year-difference ()
|
||||
(let ((a (parse-timestring "2006-01-01T00:00:00"))
|
||||
(b (parse-timestring "2001-01-01T00:00:00")))
|
||||
(is (= 5 (timestamp-whole-year-difference a b))))
|
||||
|
||||
(let ((a (parse-timestring "2006-01-01T00:00:00"))
|
||||
(b (parse-timestring "2001-01-02T00:00:00")))
|
||||
(is (= 4 (timestamp-whole-year-difference a b))))
|
||||
|
||||
(let* ((local-time::*default-timezone* amsterdam-tz)
|
||||
(a (parse-timestring "1978-10-01")))
|
||||
(is (= 0 (timestamp-whole-year-difference a a)))))
|
||||
|
||||
(deftest test/adjust-timestamp/day-of-week/basic ()
|
||||
(let ((sunday (parse-timestring "2020-09-13T00:00:00"))
|
||||
(saturday (parse-timestring "2020-09-19T00:00:00"))
|
||||
(base (parse-timestring "2020-09-15T00:00:00")))
|
||||
(loop for dow in '(:sunday :monday :tuesday)
|
||||
do (let ((modified (adjust-timestamp base (timezone +utc-zone+) (offset :day-of-week dow))))
|
||||
(is (and (timestamp>= modified sunday) (timestamp<= modified base)))))
|
||||
(loop for dow in '(:wednesday :thursday :friday :saturday)
|
||||
do (let ((modified (adjust-timestamp base (timezone +utc-zone+) (offset :day-of-week dow))))
|
||||
(is (and (timestamp> modified base) (timestamp<= modified saturday)))))))
|
||||
|
||||
(deftest test/adjust-timestamp/bug1 ()
|
||||
(let* ((timestamp (parse-timestring "2006-01-01T00:00:00Z"))
|
||||
(modified-timestamp (adjust-timestamp timestamp (timezone +utc-zone+) (offset :year 1))))
|
||||
(is (timestamp= (parse-timestring "2007-01-01T00:00:00Z") modified-timestamp))))
|
||||
|
||||
(deftest test/adjust-timestamp/bug2 ()
|
||||
(let* ((timestamp (parse-timestring "2009-03-01T01:00:00.000000+00:00"))
|
||||
(modified-timestamp (adjust-timestamp timestamp (timezone +utc-zone+) (offset :month 1))))
|
||||
(is (timestamp= (parse-timestring "2009-04-01T01:00:00.000000+00:00") modified-timestamp))))
|
||||
|
||||
(deftest test/adjust-timestamp/bug3 ()
|
||||
(let* ((timestamp (parse-timestring "2009-03-01T01:00:00.000000+00:00"))
|
||||
(modified-timestamp (adjust-timestamp timestamp (timezone +utc-zone+) (offset :day-of-week :monday))))
|
||||
(is (timestamp= (parse-timestring "2009-02-23T01:00:00.000000+00:00") modified-timestamp)))
|
||||
(let* ((timestamp (parse-timestring "2009-03-04T01:00:00.000000+00:00"))
|
||||
(modified-timestamp (adjust-timestamp timestamp (timezone +utc-zone+) (offset :day-of-week :monday))))
|
||||
(is (timestamp= (parse-timestring "2009-03-02T01:00:00.000000+00:00") modified-timestamp))))
|
||||
|
||||
(deftest test/adjust-timestamp/bug4 ()
|
||||
(let* ((timestamp (parse-timestring "2013-04-30T00:00:00.000000+00:00"))
|
||||
(modified-timestamp (adjust-timestamp timestamp (timezone +utc-zone+) (offset :day-of-week :wednesday))))
|
||||
(is (timestamp= (parse-timestring "2013-05-01T00:00:00.000000+00:00") modified-timestamp)))
|
||||
(let* ((timestamp (parse-timestring "2013-12-31T00:00:00.000000+00:00"))
|
||||
(modified-timestamp (adjust-timestamp timestamp (timezone +utc-zone+) (offset :day-of-week :wednesday))))
|
||||
(is (timestamp= (parse-timestring "2014-01-01T00:00:00.000000+00:00") modified-timestamp))))
|
||||
|
||||
#+nil
|
||||
(deftest test/adjust-days ()
|
||||
(let ((sunday (parse-timestring "2006-12-17T01:02:03Z")))
|
||||
(is (timestamp= (parse-timestring "2006-12-11T01:02:03Z")
|
||||
(adjust-timestamp sunday (offset :day-of-week :monday))))
|
||||
(is (timestamp= (parse-timestring "2006-12-20T01:02:03Z")
|
||||
(adjust-timestamp sunday (offset :day 3))))))
|
||||
|
||||
(deftest test/decode-date ()
|
||||
(loop
|
||||
:for (total-day year month day) :in '((-1 2000 02 29)
|
||||
(0 2000 03 01)
|
||||
(1 2000 03 02)
|
||||
(364 2001 02 28)
|
||||
(365 2001 03 01)
|
||||
(366 2001 03 02)
|
||||
(#.(* 2 365) 2002 03 01)
|
||||
(#.(* 4 365) 2004 02 29)
|
||||
(#.(1+ (* 4 365)) 2004 03 01))
|
||||
:do (multiple-value-bind (year* month* day*)
|
||||
(local-time::%timestamp-decode-date total-day)
|
||||
(is (= year year*))
|
||||
(is (= month month*))
|
||||
(is (= day day*)))))
|
||||
|
||||
(deftest test/timestamp-decoding-readers ()
|
||||
(let ((*default-timezone* +utc-zone+))
|
||||
(dolist (year '(1900 1975 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010))
|
||||
(dolist (month '(1 2 3 4 5 6 7 8 9 10 11 12))
|
||||
(dolist (day '(1 2 3 27 28 29 30 31))
|
||||
(when (valid-date-tuple? year month day)
|
||||
(let ((hour (random 24))
|
||||
(min (random 60))
|
||||
(sec (random 60))
|
||||
(nsec (random 1000000000)))
|
||||
(let ((time (encode-timestamp nsec sec min hour day month year :offset 0)))
|
||||
(is (= (floor year 10) (timestamp-decade time)))
|
||||
(is (= year (timestamp-year time)))
|
||||
(is (= month (timestamp-month time)))
|
||||
(is (= day (timestamp-day time)))
|
||||
(is (= hour (timestamp-hour time)))
|
||||
(is (= min (timestamp-minute time)))
|
||||
(is (= sec (timestamp-second time)))
|
||||
(is (= (floor nsec 1000000)
|
||||
(timestamp-millisecond time)))
|
||||
(is (= (floor nsec 1000)
|
||||
(timestamp-microsecond time)))))))))))
|
||||
|
||||
(deftest test/timestamp-century ()
|
||||
(let ((*default-timezone* +utc-zone+))
|
||||
(dolist (year-data '((-101 -2)
|
||||
(-100 -1)
|
||||
(-1 -1)
|
||||
(1 1)
|
||||
(100 1)
|
||||
(101 2)
|
||||
(1999 20)
|
||||
(2000 20)
|
||||
(2001 21)))
|
||||
(let ((time (encode-timestamp 0 0 0 0 1 1 (first year-data) :offset 0)))
|
||||
(is (= (second year-data) (timestamp-century time)))))))
|
||||
|
||||
(deftest test/timestamp-millennium ()
|
||||
(let ((*default-timezone* +utc-zone+))
|
||||
(dolist (year-data '((-101 -1)
|
||||
(-100 -1)
|
||||
(-1 -1)
|
||||
(1 1)
|
||||
(100 1)
|
||||
(101 1)
|
||||
(1001 2)
|
||||
(1999 2)
|
||||
(2000 2)
|
||||
(2001 3)))
|
||||
(let ((time (encode-timestamp 0 0 0 0 1 1 (first year-data) :offset 0)))
|
||||
(is (= (second year-data) (timestamp-millennium time)))))))
|
||||
|
||||
(defun valid-date-tuple? (year month day)
|
||||
;; it works only on the gregorian calendar
|
||||
(let ((month-days #(31 28 31 30 31 30 31 31 30 31 30 31)))
|
||||
(and (<= 1 month 12)
|
||||
(<= 1 day (+ (aref month-days (1- month))
|
||||
(if (and (= month 2)
|
||||
(zerop (mod year 4))
|
||||
(not (zerop (mod year 100)))
|
||||
(zerop (mod year 400)))
|
||||
1
|
||||
0))))))
|
||||
|
||||
(deftest test/encode-decode-timestamp ()
|
||||
(let ((*default-timezone* +utc-zone+))
|
||||
(loop for year :in '(1900 1975 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010) do
|
||||
(loop for month :from 1 :to 12 do
|
||||
(loop for day :in '(1 2 3 27 28 29 30 31) do
|
||||
(when (valid-date-tuple? year month day)
|
||||
(multiple-value-bind (nsec sec minute hour day* month* year* day-of-week)
|
||||
(decode-timestamp (encode-timestamp 0 0 0 0 day month year :offset 0))
|
||||
(declare (ignore nsec sec minute day-of-week))
|
||||
(is (= hour 0))
|
||||
(is (= year year*))
|
||||
(is (= month month*))
|
||||
(is (= day day*)))))))))
|
||||
|
||||
(deftest test/timestamp-maximize-part ()
|
||||
(timestamp= (timestamp-maximize-part
|
||||
(encode-timestamp 0 49 26 13 9 12 2010 :offset -18000)
|
||||
:min)
|
||||
(encode-timestamp 999999999 59 59 13 9 12 2010 :offset -18000)))
|
||||
|
||||
(deftest test/timestamp-minimize-part ()
|
||||
(timestamp= (timestamp-minimize-part
|
||||
(encode-timestamp 0 49 26 13 9 12 2010 :offset -18000)
|
||||
:min)
|
||||
(encode-timestamp 0 0 0 13 9 12 2010 :offset -18000)))
|
||||
|
||||
(deftest test/decode-iso-week ()
|
||||
(dolist (*default-timezone* (list eastern-tz +utc-zone+ amsterdam-tz))
|
||||
(dolist (testcase '((2005 01 01 2004 53 6)
|
||||
(2005 01 02 2004 53 7)
|
||||
(2005 12 31 2005 52 6)
|
||||
(2007 01 01 2007 1 1)
|
||||
(2007 12 30 2007 52 7)
|
||||
(2007 12 31 2008 1 1)
|
||||
(2008 01 01 2008 1 2)
|
||||
(2008 12 28 2008 52 7)
|
||||
(2008 12 29 2009 1 1)
|
||||
(2008 12 30 2009 1 2)
|
||||
(2008 12 31 2009 1 3)
|
||||
(2009 01 01 2009 1 4)
|
||||
(2009 12 31 2009 53 4)
|
||||
(2010 01 01 2009 53 5)
|
||||
(2010 01 02 2009 53 6)
|
||||
(2010 01 03 2009 53 7)
|
||||
(2016 01 04 2016 1 1)))
|
||||
(destructuring-bind (year month day iso-year iso-week iso-dow)
|
||||
testcase
|
||||
(let ((ts (encode-timestamp 0 0 0 12 day month year)))
|
||||
(is (equal (list iso-year iso-week iso-dow)
|
||||
(multiple-value-list (local-time::%timestamp-decode-iso-week ts)))))))))
|
||||
|
|
@ -0,0 +1,106 @@
|
|||
(in-package #:local-time.test)
|
||||
|
||||
(defsuite* (timezone :in test))
|
||||
(eval-when (:compile-toplevel :load-toplevel :execute)
|
||||
(local-time::define-timezone eastern-tz
|
||||
(merge-pathnames #p"EST5EDT" local-time::*default-timezone-repository-path*))
|
||||
(local-time::define-timezone utc-leaps
|
||||
(merge-pathnames #p"../zoneinfo-leaps/UTC" local-time::*default-timezone-repository-path*)))
|
||||
|
||||
|
||||
|
||||
(deftest transition-position/correct-position ()
|
||||
(let ((cases '((0 #(1 2 3 4 5) 0)
|
||||
(1 #(1 2 3 4 5) 0)
|
||||
(2 #(1 2 3 4 5) 1)
|
||||
(3 #(1 2 3 4 5) 2)
|
||||
(4 #(1 2 3 4 5) 3)
|
||||
(5 #(1 2 3 4 5) 4)
|
||||
(1 #(1 3 5) 0)
|
||||
(2 #(1 3 5) 0)
|
||||
(3 #(1 3 5) 1)
|
||||
(4 #(1 3 5) 1)
|
||||
(5 #(1 3 5) 2)
|
||||
(6 #(1 3 5) 2)
|
||||
(1 #(1 3 5 7) 0)
|
||||
(2 #(1 3 5 7) 0)
|
||||
(3 #(1 3 5 7) 1)
|
||||
(4 #(1 3 5 7) 1)
|
||||
(5 #(1 3 5 7) 2)
|
||||
(6 #(1 3 5 7) 2)
|
||||
(7 #(1 3 5 7) 3)
|
||||
(8 #(1 3 5 7) 3)
|
||||
)))
|
||||
(dolist (case cases)
|
||||
(destructuring-bind (needle haystack want)
|
||||
case
|
||||
(let ((got (local-time::transition-position needle haystack)))
|
||||
(is (= got want)
|
||||
"(transition-position ~a ~a) got ~a, want ~a"
|
||||
needle haystack got want))))))
|
||||
|
||||
(deftest test/timezone/decode-timestamp-dst ()
|
||||
;; Testing DST calculation with a known timezone
|
||||
(let ((test-cases '(
|
||||
;; Spring forward
|
||||
((2008 3 9 6 58) (2008 3 9 1 58))
|
||||
((2008 3 9 6 59) (2008 3 9 1 59))
|
||||
((2008 3 9 7 0) (2008 3 9 3 0))
|
||||
((2008 3 9 7 1) (2008 3 9 3 1))
|
||||
;; Fall back
|
||||
((2008 11 2 5 59) (2008 11 2 1 59))
|
||||
((2008 11 2 6 0) (2008 11 2 1 0))
|
||||
((2008 11 2 6 1) (2008 11 2 1 1)))))
|
||||
(dolist (test-case test-cases)
|
||||
(is (equal
|
||||
(let ((timestamp
|
||||
(apply 'local-time:encode-timestamp
|
||||
`(0 0 ,@(reverse (first test-case)) :offset 0))))
|
||||
(local-time:decode-timestamp timestamp :timezone eastern-tz))
|
||||
(apply 'values `(0 0 ,@(reverse (second test-case)))))))))
|
||||
|
||||
(deftest test/timezone/adjust-across-dst-by-days ()
|
||||
(let* ((old (parse-timestring "2014-03-09T01:00:00.000000-05:00"))
|
||||
(new (timestamp+ old 1 :day eastern-tz)))
|
||||
(is (= (* 23 60 60) (timestamp-difference new old)))))
|
||||
|
||||
(deftest test/timezone/adjust-across-dst-by-hours ()
|
||||
(let* ((old (parse-timestring "2014-03-09T01:00:00.000000-05:00"))
|
||||
(new (timestamp+ old 24 :hour eastern-tz)))
|
||||
(is (= (* 24 60 60) (timestamp-difference new old)))))
|
||||
|
||||
(deftest test/timezone/timestamp-minimize-part ()
|
||||
(is (timestamp=
|
||||
(timestamp-minimize-part
|
||||
(encode-timestamp 999999999 59 59 1 14 3 2010 :timezone eastern-tz)
|
||||
:month
|
||||
:timezone eastern-tz)
|
||||
(encode-timestamp 0 0 0 0 1 1 2010 :timezone eastern-tz)))
|
||||
(is (timestamp=
|
||||
(timestamp-minimize-part
|
||||
(encode-timestamp 0 0 0 2 14 3 2010 :timezone eastern-tz)
|
||||
:month
|
||||
:timezone eastern-tz)
|
||||
(encode-timestamp 0 0 0 0 1 1 2010 :timezone eastern-tz))))
|
||||
|
||||
(deftest test/timezone/timestamp-maximize-part ()
|
||||
(is (timestamp=
|
||||
(timestamp-maximize-part
|
||||
(encode-timestamp 999999999 59 59 1 7 11 2010 :timezone eastern-tz)
|
||||
:month
|
||||
:timezone eastern-tz)
|
||||
(encode-timestamp 999999999 59 59 23 31 12 2010 :timezone eastern-tz)))
|
||||
(is (timestamp=
|
||||
(timestamp-maximize-part
|
||||
(encode-timestamp 0 0 0 2 7 11 2010 :timezone eastern-tz)
|
||||
:month
|
||||
:timezone eastern-tz)
|
||||
(encode-timestamp 999999999 59 59 23 31 12 2010 :timezone eastern-tz))))
|
||||
|
||||
(deftest test/leaps/tai-to-utc ()
|
||||
(let ((*default-timezone* utc-leaps))
|
||||
(is (= 1435708799
|
||||
(local-time::%adjust-sec-for-leap-seconds 1435708824)
|
||||
(local-time::%adjust-sec-for-leap-seconds 1435708825)))
|
||||
(is (= 1435708800
|
||||
(local-time::%adjust-sec-for-leap-seconds 1435708826)))))
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue