rubyfox-server 2.3.0.pre2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +17 -0
- data/.rvmrc +1 -0
- data/Gemfile +3 -0
- data/LICENSE.txt +22 -0
- data/README.md +23 -0
- data/Rakefile +1 -0
- data/bin/smartfox +7 -0
- data/lib/rubyfox/server/cli.rb +59 -0
- data/lib/rubyfox/server/data/config/.keep +0 -0
- data/lib/rubyfox/server/data/config/_backups/.keep +0 -0
- data/lib/rubyfox/server/data/config/ascii/boot.txt +5 -0
- data/lib/rubyfox/server/data/config/ascii/ready.txt +9 -0
- data/lib/rubyfox/server/data/config/core.xml +44 -0
- data/lib/rubyfox/server/data/config/crossdomain.xml +10 -0
- data/lib/rubyfox/server/data/config/descriptors/.keep +0 -0
- data/lib/rubyfox/server/data/config/descriptors/config_room.txt +323 -0
- data/lib/rubyfox/server/data/config/descriptors/config_server.txt +621 -0
- data/lib/rubyfox/server/data/config/descriptors/config_zone.txt +1021 -0
- data/lib/rubyfox/server/data/config/descriptors/runtime_game.txt +63 -0
- data/lib/rubyfox/server/data/config/descriptors/runtime_room.txt +377 -0
- data/lib/rubyfox/server/data/config/descriptors/runtime_user.txt +589 -0
- data/lib/rubyfox/server/data/config/descriptors/runtime_zone.txt +354 -0
- data/lib/rubyfox/server/data/config/jetty/.keep +0 -0
- data/lib/rubyfox/server/data/config/jetty/jetty.xml +214 -0
- data/lib/rubyfox/server/data/config/jetty/realm.properties +21 -0
- data/lib/rubyfox/server/data/config/jetty/webdefault.xml +410 -0
- data/lib/rubyfox/server/data/config/log4j.properties +75 -0
- data/lib/rubyfox/server/data/config/myprop.properties +5 -0
- data/lib/rubyfox/server/data/config/server.xml +65 -0
- data/lib/rubyfox/server/data/config/templates/sfs2x.unix.txt +12 -0
- data/lib/rubyfox/server/data/config/templates/sfs2x.windows.txt +1 -0
- data/lib/rubyfox/server/data/config/templates/vmoptions.txt +3 -0
- data/lib/rubyfox/server/data/config/wordsFile.txt +13 -0
- data/lib/rubyfox/server/data/data/bannedusers/.keep +0 -0
- data/lib/rubyfox/server/data/data/bannedusers/users.bin +0 -0
- data/lib/rubyfox/server/data/data/buddylists/.keep +0 -0
- data/lib/rubyfox/server/data/data/buddylists/BasicExamples/7364666773646667 +0 -0
- data/lib/rubyfox/server/data/extensions/.keep +0 -0
- data/lib/rubyfox/server/data/extensions/__lib__/.keep +0 -0
- data/lib/rubyfox/server/data/lib/Jetty/.keep +0 -0
- data/lib/rubyfox/server/data/lib/Jetty/ant-1.6.5.jar +0 -0
- data/lib/rubyfox/server/data/lib/Jetty/core-3.1.1.jar +0 -0
- data/lib/rubyfox/server/data/lib/Jetty/jetty-6.1.26.jar +0 -0
- data/lib/rubyfox/server/data/lib/Jetty/jetty-util-6.1.26.jar +0 -0
- data/lib/rubyfox/server/data/lib/Jetty/jsp-2.1-glassfish-2.1.v20091210.jar +0 -0
- data/lib/rubyfox/server/data/lib/Jetty/jsp-2.1-jetty-6.1.26.jar +0 -0
- data/lib/rubyfox/server/data/lib/Jetty/jsp-api-2.1-glassfish-2.1.v20091210.jar +0 -0
- data/lib/rubyfox/server/data/lib/Jetty/servlet-api-2.5-20081211.jar +0 -0
- data/lib/rubyfox/server/data/lib/Lib/BaseHTTPServer.py +484 -0
- data/lib/rubyfox/server/data/lib/Lib/CGIHTTPServer.py +325 -0
- data/lib/rubyfox/server/data/lib/Lib/ConfigParser.py +472 -0
- data/lib/rubyfox/server/data/lib/Lib/Cookie.py +742 -0
- data/lib/rubyfox/server/data/lib/Lib/HTMLParser.py +383 -0
- data/lib/rubyfox/server/data/lib/Lib/MimeWriter.py +181 -0
- data/lib/rubyfox/server/data/lib/Lib/Queue.py +151 -0
- data/lib/rubyfox/server/data/lib/Lib/SimpleHTTPServer.py +198 -0
- data/lib/rubyfox/server/data/lib/Lib/SimpleXMLRPCServer.py +274 -0
- data/lib/rubyfox/server/data/lib/Lib/SocketServer.py +576 -0
- data/lib/rubyfox/server/data/lib/Lib/StringIO.py +239 -0
- data/lib/rubyfox/server/data/lib/Lib/UserDict$py.class +0 -0
- data/lib/rubyfox/server/data/lib/Lib/UserDict.py +60 -0
- data/lib/rubyfox/server/data/lib/Lib/UserList.py +94 -0
- data/lib/rubyfox/server/data/lib/Lib/UserString.py +182 -0
- data/lib/rubyfox/server/data/lib/Lib/__future__$py.class +0 -0
- data/lib/rubyfox/server/data/lib/Lib/__future__.py +104 -0
- data/lib/rubyfox/server/data/lib/Lib/aifc.py +961 -0
- data/lib/rubyfox/server/data/lib/Lib/anydbm.py +86 -0
- data/lib/rubyfox/server/data/lib/Lib/atexit.py +50 -0
- data/lib/rubyfox/server/data/lib/Lib/base64.py +77 -0
- data/lib/rubyfox/server/data/lib/Lib/bdb.py +563 -0
- data/lib/rubyfox/server/data/lib/Lib/binhex.py +531 -0
- data/lib/rubyfox/server/data/lib/Lib/bisect.py +78 -0
- data/lib/rubyfox/server/data/lib/Lib/calendar.py +246 -0
- data/lib/rubyfox/server/data/lib/Lib/cgi.py +1040 -0
- data/lib/rubyfox/server/data/lib/Lib/chunk.py +167 -0
- data/lib/rubyfox/server/data/lib/Lib/cmd.py +336 -0
- data/lib/rubyfox/server/data/lib/Lib/code$py.class +0 -0
- data/lib/rubyfox/server/data/lib/Lib/code.py +311 -0
- data/lib/rubyfox/server/data/lib/Lib/codecs$py.class +0 -0
- data/lib/rubyfox/server/data/lib/Lib/codecs.py +636 -0
- data/lib/rubyfox/server/data/lib/Lib/codeop$py.class +0 -0
- data/lib/rubyfox/server/data/lib/Lib/codeop.py +131 -0
- data/lib/rubyfox/server/data/lib/Lib/colorsys.py +123 -0
- data/lib/rubyfox/server/data/lib/Lib/commands.py +84 -0
- data/lib/rubyfox/server/data/lib/Lib/compileall.py +148 -0
- data/lib/rubyfox/server/data/lib/Lib/copy.py +330 -0
- data/lib/rubyfox/server/data/lib/Lib/copy_reg$py.class +0 -0
- data/lib/rubyfox/server/data/lib/Lib/copy_reg.py +78 -0
- data/lib/rubyfox/server/data/lib/Lib/datetime$py.class +0 -0
- data/lib/rubyfox/server/data/lib/Lib/datetime.py +2007 -0
- data/lib/rubyfox/server/data/lib/Lib/dbexts.py +726 -0
- data/lib/rubyfox/server/data/lib/Lib/difflib.py +1088 -0
- data/lib/rubyfox/server/data/lib/Lib/dircache.py +44 -0
- data/lib/rubyfox/server/data/lib/Lib/doctest.py +1173 -0
- data/lib/rubyfox/server/data/lib/Lib/dospath.py +341 -0
- data/lib/rubyfox/server/data/lib/Lib/dumbdbm.py +170 -0
- data/lib/rubyfox/server/data/lib/Lib/email/Charset.py +393 -0
- data/lib/rubyfox/server/data/lib/Lib/email/Encoders.py +94 -0
- data/lib/rubyfox/server/data/lib/Lib/email/Errors.py +26 -0
- data/lib/rubyfox/server/data/lib/Lib/email/Generator.py +378 -0
- data/lib/rubyfox/server/data/lib/Lib/email/Header.py +515 -0
- data/lib/rubyfox/server/data/lib/Lib/email/Iterators.py +25 -0
- data/lib/rubyfox/server/data/lib/Lib/email/MIMEAudio.py +71 -0
- data/lib/rubyfox/server/data/lib/Lib/email/MIMEBase.py +24 -0
- data/lib/rubyfox/server/data/lib/Lib/email/MIMEImage.py +45 -0
- data/lib/rubyfox/server/data/lib/Lib/email/MIMEMessage.py +32 -0
- data/lib/rubyfox/server/data/lib/Lib/email/MIMEMultipart.py +37 -0
- data/lib/rubyfox/server/data/lib/Lib/email/MIMENonMultipart.py +24 -0
- data/lib/rubyfox/server/data/lib/Lib/email/MIMEText.py +45 -0
- data/lib/rubyfox/server/data/lib/Lib/email/Message.py +837 -0
- data/lib/rubyfox/server/data/lib/Lib/email/Parser.py +292 -0
- data/lib/rubyfox/server/data/lib/Lib/email/Utils.py +340 -0
- data/lib/rubyfox/server/data/lib/Lib/email/__init__.py +72 -0
- data/lib/rubyfox/server/data/lib/Lib/email/_compat21.py +69 -0
- data/lib/rubyfox/server/data/lib/Lib/email/_compat22.py +70 -0
- data/lib/rubyfox/server/data/lib/Lib/email/_parseaddr.py +480 -0
- data/lib/rubyfox/server/data/lib/Lib/email/base64MIME.py +184 -0
- data/lib/rubyfox/server/data/lib/Lib/email/quopriMIME.py +323 -0
- data/lib/rubyfox/server/data/lib/Lib/email/test/__init__.py +2 -0
- data/lib/rubyfox/server/data/lib/Lib/email/test/data/PyBanner048.gif +0 -0
- data/lib/rubyfox/server/data/lib/Lib/email/test/data/audiotest.au +0 -0
- data/lib/rubyfox/server/data/lib/Lib/email/test/data/msg_01.txt +19 -0
- data/lib/rubyfox/server/data/lib/Lib/email/test/data/msg_02.txt +135 -0
- data/lib/rubyfox/server/data/lib/Lib/email/test/data/msg_03.txt +16 -0
- data/lib/rubyfox/server/data/lib/Lib/email/test/data/msg_04.txt +37 -0
- data/lib/rubyfox/server/data/lib/Lib/email/test/data/msg_05.txt +28 -0
- data/lib/rubyfox/server/data/lib/Lib/email/test/data/msg_06.txt +33 -0
- data/lib/rubyfox/server/data/lib/Lib/email/test/data/msg_07.txt +83 -0
- data/lib/rubyfox/server/data/lib/Lib/email/test/data/msg_08.txt +24 -0
- data/lib/rubyfox/server/data/lib/Lib/email/test/data/msg_09.txt +24 -0
- data/lib/rubyfox/server/data/lib/Lib/email/test/data/msg_10.txt +32 -0
- data/lib/rubyfox/server/data/lib/Lib/email/test/data/msg_11.txt +7 -0
- data/lib/rubyfox/server/data/lib/Lib/email/test/data/msg_12.txt +36 -0
- data/lib/rubyfox/server/data/lib/Lib/email/test/data/msg_13.txt +94 -0
- data/lib/rubyfox/server/data/lib/Lib/email/test/data/msg_14.txt +23 -0
- data/lib/rubyfox/server/data/lib/Lib/email/test/data/msg_15.txt +52 -0
- data/lib/rubyfox/server/data/lib/Lib/email/test/data/msg_16.txt +123 -0
- data/lib/rubyfox/server/data/lib/Lib/email/test/data/msg_17.txt +12 -0
- data/lib/rubyfox/server/data/lib/Lib/email/test/data/msg_18.txt +6 -0
- data/lib/rubyfox/server/data/lib/Lib/email/test/data/msg_19.txt +43 -0
- data/lib/rubyfox/server/data/lib/Lib/email/test/data/msg_20.txt +22 -0
- data/lib/rubyfox/server/data/lib/Lib/email/test/data/msg_21.txt +20 -0
- data/lib/rubyfox/server/data/lib/Lib/email/test/data/msg_22.txt +46 -0
- data/lib/rubyfox/server/data/lib/Lib/email/test/data/msg_23.txt +8 -0
- data/lib/rubyfox/server/data/lib/Lib/email/test/data/msg_24.txt +10 -0
- data/lib/rubyfox/server/data/lib/Lib/email/test/data/msg_25.txt +117 -0
- data/lib/rubyfox/server/data/lib/Lib/email/test/data/msg_26.txt +45 -0
- data/lib/rubyfox/server/data/lib/Lib/email/test/data/msg_27.txt +15 -0
- data/lib/rubyfox/server/data/lib/Lib/email/test/data/msg_28.txt +25 -0
- data/lib/rubyfox/server/data/lib/Lib/email/test/data/msg_29.txt +22 -0
- data/lib/rubyfox/server/data/lib/Lib/email/test/data/msg_30.txt +23 -0
- data/lib/rubyfox/server/data/lib/Lib/email/test/data/msg_31.txt +15 -0
- data/lib/rubyfox/server/data/lib/Lib/email/test/data/msg_32.txt +14 -0
- data/lib/rubyfox/server/data/lib/Lib/email/test/data/msg_33.txt +29 -0
- data/lib/rubyfox/server/data/lib/Lib/email/test/data/msg_34.txt +19 -0
- data/lib/rubyfox/server/data/lib/Lib/email/test/data/msg_35.txt +4 -0
- data/lib/rubyfox/server/data/lib/Lib/email/test/test_email.py +2718 -0
- data/lib/rubyfox/server/data/lib/Lib/email/test/test_email_codecs.py +68 -0
- data/lib/rubyfox/server/data/lib/Lib/email/test/test_email_torture.py +136 -0
- data/lib/rubyfox/server/data/lib/Lib/encodings/__init__$py.class +0 -0
- data/lib/rubyfox/server/data/lib/Lib/encodings/__init__.py +97 -0
- data/lib/rubyfox/server/data/lib/Lib/encodings/aliases$py.class +0 -0
- data/lib/rubyfox/server/data/lib/Lib/encodings/aliases.py +115 -0
- data/lib/rubyfox/server/data/lib/Lib/encodings/ascii.py +35 -0
- data/lib/rubyfox/server/data/lib/Lib/encodings/base64_codec.py +62 -0
- data/lib/rubyfox/server/data/lib/Lib/encodings/charmap.py +51 -0
- data/lib/rubyfox/server/data/lib/Lib/encodings/cp037.py +280 -0
- data/lib/rubyfox/server/data/lib/Lib/encodings/cp1006.py +138 -0
- data/lib/rubyfox/server/data/lib/Lib/encodings/cp1026.py +280 -0
- data/lib/rubyfox/server/data/lib/Lib/encodings/cp1140.py +45 -0
- data/lib/rubyfox/server/data/lib/Lib/encodings/cp1250.py +123 -0
- data/lib/rubyfox/server/data/lib/Lib/encodings/cp1251.py +157 -0
- data/lib/rubyfox/server/data/lib/Lib/encodings/cp1252.py +76 -0
- data/lib/rubyfox/server/data/lib/Lib/encodings/cp1253.py +151 -0
- data/lib/rubyfox/server/data/lib/Lib/encodings/cp1254.py +82 -0
- data/lib/rubyfox/server/data/lib/Lib/encodings/cp1255.py +143 -0
- data/lib/rubyfox/server/data/lib/Lib/encodings/cp1256.py +129 -0
- data/lib/rubyfox/server/data/lib/Lib/encodings/cp1257.py +131 -0
- data/lib/rubyfox/server/data/lib/Lib/encodings/cp1258.py +90 -0
- data/lib/rubyfox/server/data/lib/Lib/encodings/cp424.py +280 -0
- data/lib/rubyfox/server/data/lib/Lib/encodings/cp437.py +172 -0
- data/lib/rubyfox/server/data/lib/Lib/encodings/cp500.py +280 -0
- data/lib/rubyfox/server/data/lib/Lib/encodings/cp737.py +172 -0
- data/lib/rubyfox/server/data/lib/Lib/encodings/cp775.py +172 -0
- data/lib/rubyfox/server/data/lib/Lib/encodings/cp850.py +172 -0
- data/lib/rubyfox/server/data/lib/Lib/encodings/cp852.py +172 -0
- data/lib/rubyfox/server/data/lib/Lib/encodings/cp855.py +172 -0
- data/lib/rubyfox/server/data/lib/Lib/encodings/cp856.py +172 -0
- data/lib/rubyfox/server/data/lib/Lib/encodings/cp857.py +171 -0
- data/lib/rubyfox/server/data/lib/Lib/encodings/cp860.py +172 -0
- data/lib/rubyfox/server/data/lib/Lib/encodings/cp861.py +172 -0
- data/lib/rubyfox/server/data/lib/Lib/encodings/cp862.py +172 -0
- data/lib/rubyfox/server/data/lib/Lib/encodings/cp863.py +172 -0
- data/lib/rubyfox/server/data/lib/Lib/encodings/cp864.py +170 -0
- data/lib/rubyfox/server/data/lib/Lib/encodings/cp865.py +172 -0
- data/lib/rubyfox/server/data/lib/Lib/encodings/cp866.py +172 -0
- data/lib/rubyfox/server/data/lib/Lib/encodings/cp869.py +172 -0
- data/lib/rubyfox/server/data/lib/Lib/encodings/cp874.py +171 -0
- data/lib/rubyfox/server/data/lib/Lib/encodings/cp875.py +281 -0
- data/lib/rubyfox/server/data/lib/Lib/encodings/hex_codec.py +62 -0
- data/lib/rubyfox/server/data/lib/Lib/encodings/iso8859_1.py +44 -0
- data/lib/rubyfox/server/data/lib/Lib/encodings/iso8859_10.py +90 -0
- data/lib/rubyfox/server/data/lib/Lib/encodings/iso8859_13.py +100 -0
- data/lib/rubyfox/server/data/lib/Lib/encodings/iso8859_14.py +75 -0
- data/lib/rubyfox/server/data/lib/Lib/encodings/iso8859_15.py +52 -0
- data/lib/rubyfox/server/data/lib/Lib/encodings/iso8859_2.py +101 -0
- data/lib/rubyfox/server/data/lib/Lib/encodings/iso8859_3.py +79 -0
- data/lib/rubyfox/server/data/lib/Lib/encodings/iso8859_4.py +94 -0
- data/lib/rubyfox/server/data/lib/Lib/encodings/iso8859_5.py +138 -0
- data/lib/rubyfox/server/data/lib/Lib/encodings/iso8859_6.py +137 -0
- data/lib/rubyfox/server/data/lib/Lib/encodings/iso8859_7.py +124 -0
- data/lib/rubyfox/server/data/lib/Lib/encodings/iso8859_8.py +112 -0
- data/lib/rubyfox/server/data/lib/Lib/encodings/iso8859_9.py +50 -0
- data/lib/rubyfox/server/data/lib/Lib/encodings/koi8_r.py +172 -0
- data/lib/rubyfox/server/data/lib/Lib/encodings/koi8_u.py +54 -0
- data/lib/rubyfox/server/data/lib/Lib/encodings/latin_1.py +35 -0
- data/lib/rubyfox/server/data/lib/Lib/encodings/mac_cyrillic.py +167 -0
- data/lib/rubyfox/server/data/lib/Lib/encodings/mac_greek.py +170 -0
- data/lib/rubyfox/server/data/lib/Lib/encodings/mac_iceland.py +166 -0
- data/lib/rubyfox/server/data/lib/Lib/encodings/mac_latin2.py +170 -0
- data/lib/rubyfox/server/data/lib/Lib/encodings/mac_roman.py +167 -0
- data/lib/rubyfox/server/data/lib/Lib/encodings/mac_turkish.py +167 -0
- data/lib/rubyfox/server/data/lib/Lib/encodings/mbcs.py +36 -0
- data/lib/rubyfox/server/data/lib/Lib/encodings/quopri_codec.py +58 -0
- data/lib/rubyfox/server/data/lib/Lib/encodings/raw_unicode_escape.py +30 -0
- data/lib/rubyfox/server/data/lib/Lib/encodings/rot_13.py +105 -0
- data/lib/rubyfox/server/data/lib/Lib/encodings/undefined.py +34 -0
- data/lib/rubyfox/server/data/lib/Lib/encodings/unicode_escape.py +30 -0
- data/lib/rubyfox/server/data/lib/Lib/encodings/unicode_internal.py +30 -0
- data/lib/rubyfox/server/data/lib/Lib/encodings/utf_16.py +61 -0
- data/lib/rubyfox/server/data/lib/Lib/encodings/utf_16_be.py +31 -0
- data/lib/rubyfox/server/data/lib/Lib/encodings/utf_16_le.py +31 -0
- data/lib/rubyfox/server/data/lib/Lib/encodings/utf_7.py +27 -0
- data/lib/rubyfox/server/data/lib/Lib/encodings/utf_8$py.class +0 -0
- data/lib/rubyfox/server/data/lib/Lib/encodings/utf_8.py +31 -0
- data/lib/rubyfox/server/data/lib/Lib/encodings/uu_codec.py +112 -0
- data/lib/rubyfox/server/data/lib/Lib/encodings/zlib_codec.py +63 -0
- data/lib/rubyfox/server/data/lib/Lib/fileinput.py +349 -0
- data/lib/rubyfox/server/data/lib/Lib/fnmatch.py +107 -0
- data/lib/rubyfox/server/data/lib/Lib/formatter.py +454 -0
- data/lib/rubyfox/server/data/lib/Lib/fpformat.py +142 -0
- data/lib/rubyfox/server/data/lib/Lib/ftplib.py +804 -0
- data/lib/rubyfox/server/data/lib/Lib/getopt.py +143 -0
- data/lib/rubyfox/server/data/lib/Lib/glob.py +56 -0
- data/lib/rubyfox/server/data/lib/Lib/gopherlib.py +205 -0
- data/lib/rubyfox/server/data/lib/Lib/gzip.py +390 -0
- data/lib/rubyfox/server/data/lib/Lib/hmac.py +99 -0
- data/lib/rubyfox/server/data/lib/Lib/htmlentitydefs.py +257 -0
- data/lib/rubyfox/server/data/lib/Lib/htmllib.py +475 -0
- data/lib/rubyfox/server/data/lib/Lib/httplib.py +1238 -0
- data/lib/rubyfox/server/data/lib/Lib/imaplib.py +1208 -0
- data/lib/rubyfox/server/data/lib/Lib/imghdr.py +154 -0
- data/lib/rubyfox/server/data/lib/Lib/inspect$py.class +0 -0
- data/lib/rubyfox/server/data/lib/Lib/inspect.py +787 -0
- data/lib/rubyfox/server/data/lib/Lib/isql.py +238 -0
- data/lib/rubyfox/server/data/lib/Lib/javaos$py.class +0 -0
- data/lib/rubyfox/server/data/lib/Lib/javaos.py +395 -0
- data/lib/rubyfox/server/data/lib/Lib/javapath$py.class +0 -0
- data/lib/rubyfox/server/data/lib/Lib/javapath.py +349 -0
- data/lib/rubyfox/server/data/lib/Lib/javashell.py +194 -0
- data/lib/rubyfox/server/data/lib/Lib/jreload.py +119 -0
- data/lib/rubyfox/server/data/lib/Lib/jxxload_help/DiscardHelp.java +59 -0
- data/lib/rubyfox/server/data/lib/Lib/jxxload_help/JavaLoaderFactory.java +9 -0
- data/lib/rubyfox/server/data/lib/Lib/jxxload_help/PackageManager.java +58 -0
- data/lib/rubyfox/server/data/lib/Lib/jxxload_help/PathVFS.java +98 -0
- data/lib/rubyfox/server/data/lib/Lib/jxxload_help/PathVFSJavaLoader.java +49 -0
- data/lib/rubyfox/server/data/lib/Lib/keyword.py +97 -0
- data/lib/rubyfox/server/data/lib/Lib/linecache$py.class +0 -0
- data/lib/rubyfox/server/data/lib/Lib/linecache.py +101 -0
- data/lib/rubyfox/server/data/lib/Lib/macpath.py +242 -0
- data/lib/rubyfox/server/data/lib/Lib/macurl2path.py +95 -0
- data/lib/rubyfox/server/data/lib/Lib/mailbox.py +313 -0
- data/lib/rubyfox/server/data/lib/Lib/mailcap.py +255 -0
- data/lib/rubyfox/server/data/lib/Lib/markupbase.py +317 -0
- data/lib/rubyfox/server/data/lib/Lib/marshal.py +315 -0
- data/lib/rubyfox/server/data/lib/Lib/mhlib.py +1003 -0
- data/lib/rubyfox/server/data/lib/Lib/mimetools.py +226 -0
- data/lib/rubyfox/server/data/lib/Lib/mimetypes.py +435 -0
- data/lib/rubyfox/server/data/lib/Lib/mimify.py +464 -0
- data/lib/rubyfox/server/data/lib/Lib/multifile.py +160 -0
- data/lib/rubyfox/server/data/lib/Lib/mutex.py +51 -0
- data/lib/rubyfox/server/data/lib/Lib/netrc.py +108 -0
- data/lib/rubyfox/server/data/lib/Lib/nntplib.py +575 -0
- data/lib/rubyfox/server/data/lib/Lib/ntpath.py +482 -0
- data/lib/rubyfox/server/data/lib/Lib/nturl2path.py +66 -0
- data/lib/rubyfox/server/data/lib/Lib/pawt/__init__.py +35 -0
- data/lib/rubyfox/server/data/lib/Lib/pawt/colors.py +144 -0
- data/lib/rubyfox/server/data/lib/Lib/pawt/swing.py +42 -0
- data/lib/rubyfox/server/data/lib/Lib/pdb.py +979 -0
- data/lib/rubyfox/server/data/lib/Lib/pickle.py +990 -0
- data/lib/rubyfox/server/data/lib/Lib/pipes.py +297 -0
- data/lib/rubyfox/server/data/lib/Lib/popen2.py +304 -0
- data/lib/rubyfox/server/data/lib/Lib/poplib.py +335 -0
- data/lib/rubyfox/server/data/lib/Lib/posixfile.py +240 -0
- data/lib/rubyfox/server/data/lib/Lib/posixpath.py +414 -0
- data/lib/rubyfox/server/data/lib/Lib/pprint.py +310 -0
- data/lib/rubyfox/server/data/lib/Lib/profile.py +556 -0
- data/lib/rubyfox/server/data/lib/Lib/pstats.py +641 -0
- data/lib/rubyfox/server/data/lib/Lib/pyclbr.py +337 -0
- data/lib/rubyfox/server/data/lib/Lib/quopri.py +237 -0
- data/lib/rubyfox/server/data/lib/Lib/random$py.class +0 -0
- data/lib/rubyfox/server/data/lib/Lib/random.py +779 -0
- data/lib/rubyfox/server/data/lib/Lib/re$py.class +0 -0
- data/lib/rubyfox/server/data/lib/Lib/re.py +11 -0
- data/lib/rubyfox/server/data/lib/Lib/reconvert.py +192 -0
- data/lib/rubyfox/server/data/lib/Lib/reindex$py.class +0 -0
- data/lib/rubyfox/server/data/lib/Lib/repr.py +95 -0
- data/lib/rubyfox/server/data/lib/Lib/rfc822.py +1010 -0
- data/lib/rubyfox/server/data/lib/Lib/sched.py +106 -0
- data/lib/rubyfox/server/data/lib/Lib/select.py +211 -0
- data/lib/rubyfox/server/data/lib/Lib/servlet-api-2.5-20081211.jar +0 -0
- data/lib/rubyfox/server/data/lib/Lib/setsfactory.py +10 -0
- data/lib/rubyfox/server/data/lib/Lib/sfs2x-lms.jar +0 -0
- data/lib/rubyfox/server/data/lib/Lib/sgmllib.py +516 -0
- data/lib/rubyfox/server/data/lib/Lib/shelve.py +158 -0
- data/lib/rubyfox/server/data/lib/Lib/shlex.py +209 -0
- data/lib/rubyfox/server/data/lib/Lib/shutil$py.class +0 -0
- data/lib/rubyfox/server/data/lib/Lib/shutil.py +138 -0
- data/lib/rubyfox/server/data/lib/Lib/site.py +263 -0
- data/lib/rubyfox/server/data/lib/Lib/smtplib.py +729 -0
- data/lib/rubyfox/server/data/lib/Lib/sndhdr.py +228 -0
- data/lib/rubyfox/server/data/lib/Lib/socket.py +902 -0
- data/lib/rubyfox/server/data/lib/Lib/sre$py.class +0 -0
- data/lib/rubyfox/server/data/lib/Lib/sre.py +311 -0
- data/lib/rubyfox/server/data/lib/Lib/sre_compile$py.class +0 -0
- data/lib/rubyfox/server/data/lib/Lib/sre_compile.py +455 -0
- data/lib/rubyfox/server/data/lib/Lib/sre_constants$py.class +0 -0
- data/lib/rubyfox/server/data/lib/Lib/sre_constants.py +259 -0
- data/lib/rubyfox/server/data/lib/Lib/sre_parse$py.class +0 -0
- data/lib/rubyfox/server/data/lib/Lib/sre_parse.py +738 -0
- data/lib/rubyfox/server/data/lib/Lib/stat$py.class +0 -0
- data/lib/rubyfox/server/data/lib/Lib/stat.py +86 -0
- data/lib/rubyfox/server/data/lib/Lib/string$py.class +0 -0
- data/lib/rubyfox/server/data/lib/Lib/string.py +437 -0
- data/lib/rubyfox/server/data/lib/Lib/symbol.py +95 -0
- data/lib/rubyfox/server/data/lib/Lib/telnetlib.py +662 -0
- data/lib/rubyfox/server/data/lib/Lib/tempfile.py +255 -0
- data/lib/rubyfox/server/data/lib/Lib/test/Graph.py +62 -0
- data/lib/rubyfox/server/data/lib/Lib/test/README +372 -0
- data/lib/rubyfox/server/data/lib/Lib/test/__init__.py +1 -0
- data/lib/rubyfox/server/data/lib/Lib/test/audiotest.au +0 -0
- data/lib/rubyfox/server/data/lib/Lib/test/autotest.py +6 -0
- data/lib/rubyfox/server/data/lib/Lib/test/badsyntax_future3.py +10 -0
- data/lib/rubyfox/server/data/lib/Lib/test/badsyntax_future4.py +10 -0
- data/lib/rubyfox/server/data/lib/Lib/test/badsyntax_future5.py +12 -0
- data/lib/rubyfox/server/data/lib/Lib/test/badsyntax_future6.py +10 -0
- data/lib/rubyfox/server/data/lib/Lib/test/badsyntax_future7.py +11 -0
- data/lib/rubyfox/server/data/lib/Lib/test/badsyntax_nocaret.py +2 -0
- data/lib/rubyfox/server/data/lib/Lib/test/blob.jar +0 -0
- data/lib/rubyfox/server/data/lib/Lib/test/bugs/bugs100.py +139 -0
- data/lib/rubyfox/server/data/lib/Lib/test/bugs/bugs101.py +57 -0
- data/lib/rubyfox/server/data/lib/Lib/test/bugs/jdkbugs.py +10 -0
- data/lib/rubyfox/server/data/lib/Lib/test/bugs/pr101.py +59 -0
- data/lib/rubyfox/server/data/lib/Lib/test/bugs/pr104.py +9 -0
- data/lib/rubyfox/server/data/lib/Lib/test/bugs/pr112.py +14 -0
- data/lib/rubyfox/server/data/lib/Lib/test/bugs/pr119.py +16 -0
- data/lib/rubyfox/server/data/lib/Lib/test/bugs/pr127.py +10 -0
- data/lib/rubyfox/server/data/lib/Lib/test/bugs/pr133/__init__.py +1 -0
- data/lib/rubyfox/server/data/lib/Lib/test/bugs/pr133/test.py +2 -0
- data/lib/rubyfox/server/data/lib/Lib/test/bugs/pr133.py +12 -0
- data/lib/rubyfox/server/data/lib/Lib/test/bugs/pr134.py +9 -0
- data/lib/rubyfox/server/data/lib/Lib/test/bugs/pr139.py +7 -0
- data/lib/rubyfox/server/data/lib/Lib/test/bugs/pr142.py +1 -0
- data/lib/rubyfox/server/data/lib/Lib/test/bugs/pr144.py +2 -0
- data/lib/rubyfox/server/data/lib/Lib/test/bugs/pr148.py +2 -0
- data/lib/rubyfox/server/data/lib/Lib/test/bugs/pr149.py +7 -0
- data/lib/rubyfox/server/data/lib/Lib/test/bugs/pr155.py +13 -0
- data/lib/rubyfox/server/data/lib/Lib/test/bugs/pr170.py +7 -0
- data/lib/rubyfox/server/data/lib/Lib/test/bugs/pr171.py +9 -0
- data/lib/rubyfox/server/data/lib/Lib/test/bugs/pr174.py +9 -0
- data/lib/rubyfox/server/data/lib/Lib/test/bugs/pr178.py +10 -0
- data/lib/rubyfox/server/data/lib/Lib/test/bugs/pr183.py +5 -0
- data/lib/rubyfox/server/data/lib/Lib/test/bugs/pr186.py +10 -0
- data/lib/rubyfox/server/data/lib/Lib/test/bugs/pr191.py +5 -0
- data/lib/rubyfox/server/data/lib/Lib/test/bugs/pr192.py +81 -0
- data/lib/rubyfox/server/data/lib/Lib/test/bugs/pr195.py +11 -0
- data/lib/rubyfox/server/data/lib/Lib/test/bugs/pr208.py +26 -0
- data/lib/rubyfox/server/data/lib/Lib/test/bugs/pr233.py +8 -0
- data/lib/rubyfox/server/data/lib/Lib/test/bugs/pr234.py +16 -0
- data/lib/rubyfox/server/data/lib/Lib/test/bugs/pr235.py +14 -0
- data/lib/rubyfox/server/data/lib/Lib/test/bugs/pr239.py +6 -0
- data/lib/rubyfox/server/data/lib/Lib/test/bugs/pr241.py +16 -0
- data/lib/rubyfox/server/data/lib/Lib/test/bugs/pr242.py +12 -0
- data/lib/rubyfox/server/data/lib/Lib/test/data/PyBanner048.gif +0 -0
- data/lib/rubyfox/server/data/lib/Lib/test/data/msg_01.txt +19 -0
- data/lib/rubyfox/server/data/lib/Lib/test/data/msg_02.txt +135 -0
- data/lib/rubyfox/server/data/lib/Lib/test/data/msg_03.txt +16 -0
- data/lib/rubyfox/server/data/lib/Lib/test/data/msg_04.txt +37 -0
- data/lib/rubyfox/server/data/lib/Lib/test/data/msg_05.txt +28 -0
- data/lib/rubyfox/server/data/lib/Lib/test/data/msg_06.txt +33 -0
- data/lib/rubyfox/server/data/lib/Lib/test/data/msg_07.txt +83 -0
- data/lib/rubyfox/server/data/lib/Lib/test/data/msg_08.txt +24 -0
- data/lib/rubyfox/server/data/lib/Lib/test/data/msg_09.txt +24 -0
- data/lib/rubyfox/server/data/lib/Lib/test/data/msg_10.txt +32 -0
- data/lib/rubyfox/server/data/lib/Lib/test/data/msg_11.txt +7 -0
- data/lib/rubyfox/server/data/lib/Lib/test/data/msg_12.txt +36 -0
- data/lib/rubyfox/server/data/lib/Lib/test/data/msg_13.txt +94 -0
- data/lib/rubyfox/server/data/lib/Lib/test/data/msg_14.txt +23 -0
- data/lib/rubyfox/server/data/lib/Lib/test/data/msg_15.txt +52 -0
- data/lib/rubyfox/server/data/lib/Lib/test/data/msg_16.txt +123 -0
- data/lib/rubyfox/server/data/lib/Lib/test/data/msg_17.txt +12 -0
- data/lib/rubyfox/server/data/lib/Lib/test/data/msg_18.txt +6 -0
- data/lib/rubyfox/server/data/lib/Lib/test/data/msg_19.txt +43 -0
- data/lib/rubyfox/server/data/lib/Lib/test/data/msg_20.txt +22 -0
- data/lib/rubyfox/server/data/lib/Lib/test/data/msg_21.txt +22 -0
- data/lib/rubyfox/server/data/lib/Lib/test/data/msg_22.txt +46 -0
- data/lib/rubyfox/server/data/lib/Lib/test/data/msg_23.txt +8 -0
- data/lib/rubyfox/server/data/lib/Lib/test/double_const.py +30 -0
- data/lib/rubyfox/server/data/lib/Lib/test/greyrgb.uue +1547 -0
- data/lib/rubyfox/server/data/lib/Lib/test/javatests/AnonInner.java +20 -0
- data/lib/rubyfox/server/data/lib/Lib/test/javatests/Foo.java +3 -0
- data/lib/rubyfox/server/data/lib/Lib/test/javatests/JOverload.java +132 -0
- data/lib/rubyfox/server/data/lib/Lib/test/javatests/ListTest.java +638 -0
- data/lib/rubyfox/server/data/lib/Lib/test/javatests/SubFoo.java +3 -0
- data/lib/rubyfox/server/data/lib/Lib/test/javatests/TestSupport.java +49 -0
- data/lib/rubyfox/server/data/lib/Lib/test/javatests/__init__.py +0 -0
- data/lib/rubyfox/server/data/lib/Lib/test/jser2_classes.py +47 -0
- data/lib/rubyfox/server/data/lib/Lib/test/output/test_MimeWriter +110 -0
- data/lib/rubyfox/server/data/lib/Lib/test/output/test_array +4 -0
- data/lib/rubyfox/server/data/lib/Lib/test/output/test_asynchat +3 -0
- data/lib/rubyfox/server/data/lib/Lib/test/output/test_augassign +51 -0
- data/lib/rubyfox/server/data/lib/Lib/test/output/test_binascii +29 -0
- data/lib/rubyfox/server/data/lib/Lib/test/output/test_builtin +53 -0
- data/lib/rubyfox/server/data/lib/Lib/test/output/test_cfgparser +9 -0
- data/lib/rubyfox/server/data/lib/Lib/test/output/test_cgi +29 -0
- data/lib/rubyfox/server/data/lib/Lib/test/output/test_charmapcodec +16 -0
- data/lib/rubyfox/server/data/lib/Lib/test/output/test_class +101 -0
- data/lib/rubyfox/server/data/lib/Lib/test/output/test_coercion +1054 -0
- data/lib/rubyfox/server/data/lib/Lib/test/output/test_compare +101 -0
- data/lib/rubyfox/server/data/lib/Lib/test/output/test_compile +7 -0
- data/lib/rubyfox/server/data/lib/Lib/test/output/test_cookie +32 -0
- data/lib/rubyfox/server/data/lib/Lib/test/output/test_exceptions +52 -0
- data/lib/rubyfox/server/data/lib/Lib/test/output/test_extcall +112 -0
- data/lib/rubyfox/server/data/lib/Lib/test/output/test_frozen +4 -0
- data/lib/rubyfox/server/data/lib/Lib/test/output/test_future +9 -0
- data/lib/rubyfox/server/data/lib/Lib/test/output/test_gettext +46 -0
- data/lib/rubyfox/server/data/lib/Lib/test/output/test_global +5 -0
- data/lib/rubyfox/server/data/lib/Lib/test/output/test_grammar +66 -0
- data/lib/rubyfox/server/data/lib/Lib/test/output/test_httplib +10 -0
- data/lib/rubyfox/server/data/lib/Lib/test/output/test_janoninner +5 -0
- data/lib/rubyfox/server/data/lib/Lib/test/output/test_javalist +6 -0
- data/lib/rubyfox/server/data/lib/Lib/test/output/test_jbasic +13 -0
- data/lib/rubyfox/server/data/lib/Lib/test/output/test_jser +12 -0
- data/lib/rubyfox/server/data/lib/Lib/test/output/test_jsubclass +5 -0
- data/lib/rubyfox/server/data/lib/Lib/test/output/test_linuxaudiodev +7 -0
- data/lib/rubyfox/server/data/lib/Lib/test/output/test_longexp +2 -0
- data/lib/rubyfox/server/data/lib/Lib/test/output/test_math +26 -0
- data/lib/rubyfox/server/data/lib/Lib/test/output/test_md5 +9 -0
- data/lib/rubyfox/server/data/lib/Lib/test/output/test_methods +6 -0
- data/lib/rubyfox/server/data/lib/Lib/test/output/test_mimetools +5 -0
- data/lib/rubyfox/server/data/lib/Lib/test/output/test_mmap +34 -0
- data/lib/rubyfox/server/data/lib/Lib/test/output/test_new +7 -0
- data/lib/rubyfox/server/data/lib/Lib/test/output/test_nis +2 -0
- data/lib/rubyfox/server/data/lib/Lib/test/output/test_opcodes +4 -0
- data/lib/rubyfox/server/data/lib/Lib/test/output/test_openpty +2 -0
- data/lib/rubyfox/server/data/lib/Lib/test/output/test_operations +28 -0
- data/lib/rubyfox/server/data/lib/Lib/test/output/test_pkg +45 -0
- data/lib/rubyfox/server/data/lib/Lib/test/output/test_poll +17 -0
- data/lib/rubyfox/server/data/lib/Lib/test/output/test_popen2 +9 -0
- data/lib/rubyfox/server/data/lib/Lib/test/output/test_posixpath +2 -0
- data/lib/rubyfox/server/data/lib/Lib/test/output/test_pow +17 -0
- data/lib/rubyfox/server/data/lib/Lib/test/output/test_profile +17 -0
- data/lib/rubyfox/server/data/lib/Lib/test/output/test_pty +3 -0
- data/lib/rubyfox/server/data/lib/Lib/test/output/test_pwd +7 -0
- data/lib/rubyfox/server/data/lib/Lib/test/output/test_pyexpat +110 -0
- data/lib/rubyfox/server/data/lib/Lib/test/output/test_re +15 -0
- data/lib/rubyfox/server/data/lib/Lib/test/output/test_regex +29 -0
- data/lib/rubyfox/server/data/lib/Lib/test/output/test_rgbimg +2 -0
- data/lib/rubyfox/server/data/lib/Lib/test/output/test_richcmp +187 -0
- data/lib/rubyfox/server/data/lib/Lib/test/output/test_rotor +5 -0
- data/lib/rubyfox/server/data/lib/Lib/test/output/test_scope +24 -0
- data/lib/rubyfox/server/data/lib/Lib/test/output/test_signal +2 -0
- data/lib/rubyfox/server/data/lib/Lib/test/output/test_string +18 -0
- data/lib/rubyfox/server/data/lib/Lib/test/output/test_thread +4 -0
- data/lib/rubyfox/server/data/lib/Lib/test/output/test_threadedtempfile +5 -0
- data/lib/rubyfox/server/data/lib/Lib/test/output/test_time +9 -0
- data/lib/rubyfox/server/data/lib/Lib/test/output/test_tokenize +648 -0
- data/lib/rubyfox/server/data/lib/Lib/test/output/test_types +15 -0
- data/lib/rubyfox/server/data/lib/Lib/test/output/test_ucn +7 -0
- data/lib/rubyfox/server/data/lib/Lib/test/output/test_unicode +21 -0
- data/lib/rubyfox/server/data/lib/Lib/test/output/test_unicode_file +2 -0
- data/lib/rubyfox/server/data/lib/Lib/test/output/test_unicodedata +5 -0
- data/lib/rubyfox/server/data/lib/Lib/test/output/test_unpack +15 -0
- data/lib/rubyfox/server/data/lib/Lib/test/output/test_urlparse +47 -0
- data/lib/rubyfox/server/data/lib/Lib/test/output/test_winreg +3 -0
- data/lib/rubyfox/server/data/lib/Lib/test/output/test_winsound +2 -0
- data/lib/rubyfox/server/data/lib/Lib/test/output/test_xreadline +4 -0
- data/lib/rubyfox/server/data/lib/Lib/test/pickletester.py +285 -0
- data/lib/rubyfox/server/data/lib/Lib/test/pydocfodder.py +210 -0
- data/lib/rubyfox/server/data/lib/Lib/test/pystone.py +252 -0
- data/lib/rubyfox/server/data/lib/Lib/test/re_tests.py +590 -0
- data/lib/rubyfox/server/data/lib/Lib/test/regex_tests.py +287 -0
- data/lib/rubyfox/server/data/lib/Lib/test/regrtest.py +1096 -0
- data/lib/rubyfox/server/data/lib/Lib/test/reperf.py +23 -0
- data/lib/rubyfox/server/data/lib/Lib/test/sortperf.py +141 -0
- data/lib/rubyfox/server/data/lib/Lib/test/string_tests.py +265 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test.xml +115 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test.xml.out +115 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_MimeWriter.py +170 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_SimpleXMLRPCServer.py +88 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_StringIO.py +113 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test___all__.py +158 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test___future__.py +59 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_al.py +23 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_array.py +438 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_asynchat.py +58 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_atexit.py +66 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_audioop.py +264 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_augassign.py +261 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_b1.py +632 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_b2.py +365 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_base64.py +53 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_bastion.py +3 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_binascii.py +119 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_binhex.py +50 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_binop.py +328 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_bisect.py +127 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_bsddb.py +76 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_bufio.py +60 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_bugfixes.py +31 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_builtin.py +13 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_calendar.py +61 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_call.py +131 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_capi.py +16 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_cd.py +26 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_cfgparser.py +284 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_cgi.py +188 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_charmapcodec.py +43 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_cl.py +78 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_class.py +317 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_cmath.py +35 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_codecs.py +31 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_codeop.py +190 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_coercion.py +118 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_commands.py +52 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_compare.py +56 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_compile.py +129 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_complex.py +68 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_contains.py +133 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_cookie.py +47 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_copy_reg.py +30 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_cpickle.py +81 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_crypt.py +11 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_curses.py +210 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_datetime.py +2958 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_dbm.py +43 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_descr.py +4094 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_descrtut.py +501 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_difflib.py +2 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_dircache.py +74 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_dl.py +33 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_doctest.py +2 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_doctest2.py +108 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_dospath.py +61 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_dumbdbm.py +79 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_email.py +13 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_email_codecs.py +11 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_enumerate.py +150 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_errno.py +49 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_exceptions.py +206 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_extcall.py +268 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_fcntl.py +53 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_file.py +63 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_fileinput.py +159 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_fnmatch.py +46 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_fork1.py +75 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_format.py +218 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_fpformat.py +75 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_frozen.py +26 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_funcattrs.py +384 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_future.py +47 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_future1.py +11 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_future2.py +10 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_future3.py +11 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_gc.py +346 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_gdbm.py +46 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_generators.py +1385 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_getargs.py +26 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_getopt.py +110 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_gettext.py +200 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_gl.py +150 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_glob.py +115 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_global.py +51 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_grammar.py +732 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_grp.py +27 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_gzip.py +82 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_hash.py +36 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_hmac.py +108 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_hotshot.py +117 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_htmllib.py +42 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_htmlparser.py +294 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_httplib.py +58 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_imageop.py +171 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_imgfile.py +116 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_import.py +71 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_importhooks.py +215 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_inspect.py +365 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_iter.py +784 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_janoninner.py +15 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_javalist.py +53 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_javashell.py +182 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_jbasic.py +119 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_joverload.py +138 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_jreload.py +33 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_jser.py +57 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_jser2.py +93 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_jsubclass.py +49 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_jy_compile.py +168 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_jy_generators.py +165 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_jy_internals.py +130 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_largefile.py +169 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_linuxaudiodev.py +89 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_locale.py +44 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_long.py +445 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_long_future.py +55 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_long_int_args.py +61 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_longexp.py +16 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_mailbox.py +113 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_marshal.py +44 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_math.py +153 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_md5.py +30 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_methods.py +62 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_mhlib.py +353 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_mimetools.py +18 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_mimetypes.py +59 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_minidom.py +648 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_mmap.py +317 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_module.py +77 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_multifile.py +66 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_mutants.py +285 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_netrc.py +42 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_new.py +108 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_nis.py +32 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_ntpath.py +114 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_opcodes.py +65 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_openpty.py +21 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_operations.py +475 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_operator.py +218 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_os.py +187 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_parser.py +383 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_pep247.py +50 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_pickle.py +40 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_pkg.py +259 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_pkgimport.py +84 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_poll.py +3 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_popen2.py +72 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_posixpath.py +40 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_pow.py +107 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_pprint.py +104 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_profile.py +86 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_profilehooks.py +360 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_pty.py +98 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_pwd.py +71 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_pyclbr.py +154 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_pyexpat.py +202 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_queue.py +158 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_quopri.py +157 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_random.py +19 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_re.py +304 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_regex.py +113 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_repr.py +278 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_rfc822.py +211 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_rgbimg.py +63 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_richcmp.py +261 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_rotor.py +28 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_sax.py +727 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_scope.py +530 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_select.py +228 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_select_new.py +229 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_sets.py +793 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_sgmllib.py +314 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_sha.py +52 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_signal.py +66 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_socket.py +1116 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_socket_ssl.py +27 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_socketserver.py +165 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_sre.py +434 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_str2unicode.py +90 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_strftime.py +146 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_string.py +223 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_strop.py +133 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_struct.py +441 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_structseq.py +28 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_subclasses.py +204 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_sunaudiodev.py +28 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_sundry.py +102 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_support.py +265 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_symtable.py +8 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_tempfile.py +10 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_thread.py +116 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_threaded_import.py +56 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_threadedtempfile.py +86 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_threading.py +55 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_time.py +47 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_timing.py +21 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_tokenize.py +9 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_trace.py +219 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_traceback.py +49 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_types.py +762 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_ucn.py +113 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_unary.py +58 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_unicode.py +815 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_unicode_file.py +95 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_unicodedata.py +125 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_unpack.py +105 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_urllib.py +109 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_urllib2.py +31 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_urlparse.py +94 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_userdict.py +120 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_userlist.py +269 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_userstring.py +43 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_uu.py +158 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_wave.py +34 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_weakref.py +573 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_winreg.py +151 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_winsound.py +6 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_xmllib.py +35 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_xmlrpc.py +37 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_xreadline.py +43 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_zipfile.py +78 -0
- data/lib/rubyfox/server/data/lib/Lib/test/test_zlib.py +482 -0
- data/lib/rubyfox/server/data/lib/Lib/test/testall.py +43 -0
- data/lib/rubyfox/server/data/lib/Lib/test/testcodec.py +48 -0
- data/lib/rubyfox/server/data/lib/Lib/test/testimg.uue +1170 -0
- data/lib/rubyfox/server/data/lib/Lib/test/testimgr.uue +1170 -0
- data/lib/rubyfox/server/data/lib/Lib/test/testrgb.uue +971 -0
- data/lib/rubyfox/server/data/lib/Lib/test/tokenize_tests.py +175 -0
- data/lib/rubyfox/server/data/lib/Lib/test/whrandom.py +96 -0
- data/lib/rubyfox/server/data/lib/Lib/test/zxjdbc/dbextstest.py +266 -0
- data/lib/rubyfox/server/data/lib/Lib/test/zxjdbc/jndi.py +33 -0
- data/lib/rubyfox/server/data/lib/Lib/test/zxjdbc/runner.py +204 -0
- data/lib/rubyfox/server/data/lib/Lib/test/zxjdbc/sptest.py +227 -0
- data/lib/rubyfox/server/data/lib/Lib/test/zxjdbc/test.xml +363 -0
- data/lib/rubyfox/server/data/lib/Lib/test/zxjdbc/test_zxjdbc_dbapi20.py +26 -0
- data/lib/rubyfox/server/data/lib/Lib/test/zxjdbc/zxtest.py +1242 -0
- data/lib/rubyfox/server/data/lib/Lib/this.py +28 -0
- data/lib/rubyfox/server/data/lib/Lib/threading.py +698 -0
- data/lib/rubyfox/server/data/lib/Lib/token$py.class +0 -0
- data/lib/rubyfox/server/data/lib/Lib/token.py +140 -0
- data/lib/rubyfox/server/data/lib/Lib/tokenize$py.class +0 -0
- data/lib/rubyfox/server/data/lib/Lib/tokenize.py +287 -0
- data/lib/rubyfox/server/data/lib/Lib/traceback$py.class +0 -0
- data/lib/rubyfox/server/data/lib/Lib/traceback.py +301 -0
- data/lib/rubyfox/server/data/lib/Lib/tzparse.py +98 -0
- data/lib/rubyfox/server/data/lib/Lib/unittest.py +723 -0
- data/lib/rubyfox/server/data/lib/Lib/urllib.py +1465 -0
- data/lib/rubyfox/server/data/lib/Lib/urllib2.py +1144 -0
- data/lib/rubyfox/server/data/lib/Lib/urlparse.py +276 -0
- data/lib/rubyfox/server/data/lib/Lib/user.py +45 -0
- data/lib/rubyfox/server/data/lib/Lib/uu.py +195 -0
- data/lib/rubyfox/server/data/lib/Lib/warnings$py.class +0 -0
- data/lib/rubyfox/server/data/lib/Lib/warnings.py +258 -0
- data/lib/rubyfox/server/data/lib/Lib/weakref.py +280 -0
- data/lib/rubyfox/server/data/lib/Lib/whichdb.py +87 -0
- data/lib/rubyfox/server/data/lib/Lib/whrandom.py +140 -0
- data/lib/rubyfox/server/data/lib/Lib/xdrlib.py +285 -0
- data/lib/rubyfox/server/data/lib/Lib/xml/FtCore.py +58 -0
- data/lib/rubyfox/server/data/lib/Lib/xml/Uri.py +380 -0
- data/lib/rubyfox/server/data/lib/Lib/xml/__init__.py +41 -0
- data/lib/rubyfox/server/data/lib/Lib/xml/dom/MessageSource.py +54 -0
- data/lib/rubyfox/server/data/lib/Lib/xml/dom/NodeFilter.py +27 -0
- data/lib/rubyfox/server/data/lib/Lib/xml/dom/__init__.py +232 -0
- data/lib/rubyfox/server/data/lib/Lib/xml/dom/domreg.py +99 -0
- data/lib/rubyfox/server/data/lib/Lib/xml/dom/minicompat.py +184 -0
- data/lib/rubyfox/server/data/lib/Lib/xml/dom/minidom.py +1943 -0
- data/lib/rubyfox/server/data/lib/Lib/xml/dom/pulldom.py +350 -0
- data/lib/rubyfox/server/data/lib/Lib/xml/dom/xmlbuilder.py +388 -0
- data/lib/rubyfox/server/data/lib/Lib/xml/sax/__init__.py +102 -0
- data/lib/rubyfox/server/data/lib/Lib/xml/sax/_exceptions.py +127 -0
- data/lib/rubyfox/server/data/lib/Lib/xml/sax/drivers2/__init__.py +1 -0
- data/lib/rubyfox/server/data/lib/Lib/xml/sax/drivers2/drv_javasax.py +333 -0
- data/lib/rubyfox/server/data/lib/Lib/xml/sax/handler.py +345 -0
- data/lib/rubyfox/server/data/lib/Lib/xml/sax/saxlib.py +430 -0
- data/lib/rubyfox/server/data/lib/Lib/xml/sax/saxutils.py +813 -0
- data/lib/rubyfox/server/data/lib/Lib/xml/sax/xmlreader.py +378 -0
- data/lib/rubyfox/server/data/lib/Lib/xmllib.py +926 -0
- data/lib/rubyfox/server/data/lib/Lib/xmlrpclib.py +1019 -0
- data/lib/rubyfox/server/data/lib/Lib/zipfile.py +586 -0
- data/lib/rubyfox/server/data/lib/Lib/zlib.py +156 -0
- data/lib/rubyfox/server/data/lib/boot.jar +0 -0
- data/lib/rubyfox/server/data/lib/cachedir/.keep +0 -0
- data/lib/rubyfox/server/data/lib/commons-beanutils-1.7.0.jar +0 -0
- data/lib/rubyfox/server/data/lib/commons-collections-3.2.1.jar +0 -0
- data/lib/rubyfox/server/data/lib/commons-dbcp-1.4.jar +0 -0
- data/lib/rubyfox/server/data/lib/commons-io-1.4.jar +0 -0
- data/lib/rubyfox/server/data/lib/commons-lang-2.4.jar +0 -0
- data/lib/rubyfox/server/data/lib/commons-logging-1.1.1.jar +0 -0
- data/lib/rubyfox/server/data/lib/commons-pool-1.5.4.jar +0 -0
- data/lib/rubyfox/server/data/lib/commons-vfs-1.0.jar +0 -0
- data/lib/rubyfox/server/data/lib/ezmorph-1.0.6.jar +0 -0
- data/lib/rubyfox/server/data/lib/httpclient-4.0.3.jar +0 -0
- data/lib/rubyfox/server/data/lib/httpcore-4.0.1.jar +0 -0
- data/lib/rubyfox/server/data/lib/imap.jar +0 -0
- data/lib/rubyfox/server/data/lib/jconsole/COPYING.txt +504 -0
- data/lib/rubyfox/server/data/lib/jconsole/bug_test_case.py +49 -0
- data/lib/rubyfox/server/data/lib/jconsole/console$py.class +0 -0
- data/lib/rubyfox/server/data/lib/jconsole/console.py +439 -0
- data/lib/rubyfox/server/data/lib/jconsole/history$py.class +0 -0
- data/lib/rubyfox/server/data/lib/jconsole/history.py +82 -0
- data/lib/rubyfox/server/data/lib/jconsole/history_test_case.py +133 -0
- data/lib/rubyfox/server/data/lib/jconsole/introspect$py.class +0 -0
- data/lib/rubyfox/server/data/lib/jconsole/introspect.py +373 -0
- data/lib/rubyfox/server/data/lib/jconsole/introspect_test_case.py +19 -0
- data/lib/rubyfox/server/data/lib/jconsole/issue_17_test_case.py +36 -0
- data/lib/rubyfox/server/data/lib/jconsole/jintrospect$py.class +0 -0
- data/lib/rubyfox/server/data/lib/jconsole/jintrospect.py +316 -0
- data/lib/rubyfox/server/data/lib/jconsole/jintrospect_test_case.py +107 -0
- data/lib/rubyfox/server/data/lib/jconsole/popup$py.class +0 -0
- data/lib/rubyfox/server/data/lib/jconsole/popup.py +178 -0
- data/lib/rubyfox/server/data/lib/jconsole/run_tests.py +8 -0
- data/lib/rubyfox/server/data/lib/jconsole/static_test_case.py +36 -0
- data/lib/rubyfox/server/data/lib/jconsole/testcase.py +38 -0
- data/lib/rubyfox/server/data/lib/jconsole/tip$py.class +0 -0
- data/lib/rubyfox/server/data/lib/jconsole/tip.py +47 -0
- data/lib/rubyfox/server/data/lib/jmx-util-1.2.3.jar +0 -0
- data/lib/rubyfox/server/data/lib/joda-time-1.6.jar +0 -0
- data/lib/rubyfox/server/data/lib/js.jar +0 -0
- data/lib/rubyfox/server/data/lib/json-lib-2.2.3-jdk15.jar +0 -0
- data/lib/rubyfox/server/data/lib/jython.jar +0 -0
- data/lib/rubyfox/server/data/lib/log4j-1.2.15.jar +0 -0
- data/lib/rubyfox/server/data/lib/logs-backup-app.jar +0 -0
- data/lib/rubyfox/server/data/lib/mailapi.jar +0 -0
- data/lib/rubyfox/server/data/lib/pop3.jar +0 -0
- data/lib/rubyfox/server/data/lib/scala-library.jar +0 -0
- data/lib/rubyfox/server/data/lib/sfs2x-admin.jar +0 -0
- data/lib/rubyfox/server/data/lib/sfs2x-core.jar +0 -0
- data/lib/rubyfox/server/data/lib/sfs2x-util.jar +0 -0
- data/lib/rubyfox/server/data/lib/sfs2x.jar +0 -0
- data/lib/rubyfox/server/data/lib/slf4j-api-1.5.10.jar +0 -0
- data/lib/rubyfox/server/data/lib/slf4j-log4j12.jar +0 -0
- data/lib/rubyfox/server/data/lib/smtp.jar +0 -0
- data/lib/rubyfox/server/data/lib/terracotta-api-1.1.1.jar +0 -0
- data/lib/rubyfox/server/data/lib/ws-engine.jar +0 -0
- data/lib/rubyfox/server/data/lib/xpp3_min-1.1.4c.jar +0 -0
- data/lib/rubyfox/server/data/lib/xstream-1.3.1.jar +0 -0
- data/lib/rubyfox/server/data/logs/.keep +0 -0
- data/lib/rubyfox/server/data/logs/bluebox/.keep +0 -0
- data/lib/rubyfox/server/data/logs/boot/.keep +0 -0
- data/lib/rubyfox/server/data/logs/http/.keep +0 -0
- data/lib/rubyfox/server/data/logs/smartfox.log +295 -0
- data/lib/rubyfox/server/data/root/.keep +0 -0
- data/lib/rubyfox/server/data/root/_css_/default.css +170 -0
- data/lib/rubyfox/server/data/root/_css_/reset.css +49 -0
- data/lib/rubyfox/server/data/root/_images_/background_gradient.png +0 -0
- data/lib/rubyfox/server/data/root/_images_/background_logo.png +0 -0
- data/lib/rubyfox/server/data/root/_images_/favicon.png +0 -0
- data/lib/rubyfox/server/data/root/_images_/logo_smartfoxserver.png +0 -0
- data/lib/rubyfox/server/data/root/admin/.keep +0 -0
- data/lib/rubyfox/server/data/root/admin/AdminTool.html +108 -0
- data/lib/rubyfox/server/data/root/admin/AdminTool.swf +0 -0
- data/lib/rubyfox/server/data/root/admin/ReleaseNotes.txt +29 -0
- data/lib/rubyfox/server/data/root/admin/assets/icons/tabs/adobeFlashPlayer.png +0 -0
- data/lib/rubyfox/server/data/root/admin/assets/icons/tabs/advanced.png +0 -0
- data/lib/rubyfox/server/data/root/admin/assets/icons/tabs/banManager.png +0 -0
- data/lib/rubyfox/server/data/root/admin/assets/icons/tabs/bannedIPs.png +0 -0
- data/lib/rubyfox/server/data/root/admin/assets/icons/tabs/bannedUsernames.png +0 -0
- data/lib/rubyfox/server/data/root/admin/assets/icons/tabs/bookmarks.png +0 -0
- data/lib/rubyfox/server/data/root/admin/assets/icons/tabs/bootLog.png +0 -0
- data/lib/rubyfox/server/data/root/admin/assets/icons/tabs/buddyList.png +0 -0
- data/lib/rubyfox/server/data/root/admin/assets/icons/tabs/buddyProperties.png +0 -0
- data/lib/rubyfox/server/data/root/admin/assets/icons/tabs/connection.png +0 -0
- data/lib/rubyfox/server/data/root/admin/assets/icons/tabs/databaseManager.png +0 -0
- data/lib/rubyfox/server/data/root/admin/assets/icons/tabs/floodFilter.png +0 -0
- data/lib/rubyfox/server/data/root/admin/assets/icons/tabs/gameSettings.png +0 -0
- data/lib/rubyfox/server/data/root/admin/assets/icons/tabs/general.png +0 -0
- data/lib/rubyfox/server/data/root/admin/assets/icons/tabs/globalServerStatus.png +0 -0
- data/lib/rubyfox/server/data/root/admin/assets/icons/tabs/iPFilter.png +0 -0
- data/lib/rubyfox/server/data/root/admin/assets/icons/tabs/jVMSettings.png +0 -0
- data/lib/rubyfox/server/data/root/admin/assets/icons/tabs/logsDownload.png +0 -0
- data/lib/rubyfox/server/data/root/admin/assets/icons/tabs/mailer.png +0 -0
- data/lib/rubyfox/server/data/root/admin/assets/icons/tabs/permissionsAndEvents.png +0 -0
- data/lib/rubyfox/server/data/root/admin/assets/icons/tabs/privilegeManager.png +0 -0
- data/lib/rubyfox/server/data/root/admin/assets/icons/tabs/remoteAdmin.png +0 -0
- data/lib/rubyfox/server/data/root/admin/assets/icons/tabs/roomExtension.png +0 -0
- data/lib/rubyfox/server/data/root/admin/assets/icons/tabs/roomVariables.png +0 -0
- data/lib/rubyfox/server/data/root/admin/assets/icons/tabs/roomsAndGroups.png +0 -0
- data/lib/rubyfox/server/data/root/admin/assets/icons/tabs/runtimeLog.png +0 -0
- data/lib/rubyfox/server/data/root/admin/assets/icons/tabs/runtimeRoomSettings.png +0 -0
- data/lib/rubyfox/server/data/root/admin/assets/icons/tabs/runtimeUserSettings.png +0 -0
- data/lib/rubyfox/server/data/root/admin/assets/icons/tabs/runtimeZoneSettings.png +0 -0
- data/lib/rubyfox/server/data/root/admin/assets/icons/tabs/systemQueueStatus.png +0 -0
- data/lib/rubyfox/server/data/root/admin/assets/icons/tabs/userManagement.png +0 -0
- data/lib/rubyfox/server/data/root/admin/assets/icons/tabs/userVariables.png +0 -0
- data/lib/rubyfox/server/data/root/admin/assets/icons/tabs/usersTraffic.png +0 -0
- data/lib/rubyfox/server/data/root/admin/assets/icons/tabs/webServer.png +0 -0
- data/lib/rubyfox/server/data/root/admin/assets/icons/tabs/wordsFilter.png +0 -0
- data/lib/rubyfox/server/data/root/admin/assets/icons/tabs/zoneExtension.png +0 -0
- data/lib/rubyfox/server/data/root/admin/index.html +108 -0
- data/lib/rubyfox/server/data/root/admin/modules/BanManager/BanManager.swf +0 -0
- data/lib/rubyfox/server/data/root/admin/modules/BanManager/icon.png +0 -0
- data/lib/rubyfox/server/data/root/admin/modules/BlueBoxMonitor/BlueBoxMonitor.swf +0 -0
- data/lib/rubyfox/server/data/root/admin/modules/BlueBoxMonitor/icon.png +0 -0
- data/lib/rubyfox/server/data/root/admin/modules/LicenseManager/LicenseManager.swf +0 -0
- data/lib/rubyfox/server/data/root/admin/modules/LicenseManager/icon.png +0 -0
- data/lib/rubyfox/server/data/root/admin/modules/LogViewer/LogViewer.swf +0 -0
- data/lib/rubyfox/server/data/root/admin/modules/LogViewer/icon.png +0 -0
- data/lib/rubyfox/server/data/root/admin/modules/RuntimeStatistics/RuntimeStatistics.swf +0 -0
- data/lib/rubyfox/server/data/root/admin/modules/RuntimeStatistics/icon.png +0 -0
- data/lib/rubyfox/server/data/root/admin/modules/ServerConfigurator/ServerConfigurator.swf +0 -0
- data/lib/rubyfox/server/data/root/admin/modules/ServerConfigurator/icon.png +0 -0
- data/lib/rubyfox/server/data/root/admin/modules/ZoneConfigurator/ZoneConfigurator.swf +0 -0
- data/lib/rubyfox/server/data/root/admin/modules/ZoneConfigurator/icon.png +0 -0
- data/lib/rubyfox/server/data/root/admin/modules/ZoneMonitor/ZoneMonitor.swf +0 -0
- data/lib/rubyfox/server/data/root/admin/modules/ZoneMonitor/icon.png +0 -0
- data/lib/rubyfox/server/data/root/admin/modules/config.xml +12 -0
- data/lib/rubyfox/server/data/root/admin/playerProductInstall.swf +0 -0
- data/lib/rubyfox/server/data/root/admin/swfobject.js +777 -0
- data/lib/rubyfox/server/data/root/crossdomain.xml +6 -0
- data/lib/rubyfox/server/data/root/index.html +63 -0
- data/lib/rubyfox/server/data/sfs2x-service +435 -0
- data/lib/rubyfox/server/data/sfs2x-service.vmoptions +5 -0
- data/lib/rubyfox/server/data/sfs2x.sh +12 -0
- data/lib/rubyfox/server/data/www/.keep +0 -0
- data/lib/rubyfox/server/data/www/BlueBox.war +0 -0
- data/lib/rubyfox/server/data/www/root/_css_/default.css +170 -0
- data/lib/rubyfox/server/data/www/root/_css_/reset.css +49 -0
- data/lib/rubyfox/server/data/www/root/_images_/background_gradient.png +0 -0
- data/lib/rubyfox/server/data/www/root/_images_/background_logo.png +0 -0
- data/lib/rubyfox/server/data/www/root/_images_/favicon.png +0 -0
- data/lib/rubyfox/server/data/www/root/_images_/logo_smartfoxserver.png +0 -0
- data/lib/rubyfox/server/data/www/root/admin/.keep +0 -0
- data/lib/rubyfox/server/data/www/root/admin/AdminTool.html +108 -0
- data/lib/rubyfox/server/data/www/root/admin/AdminTool.swf +0 -0
- data/lib/rubyfox/server/data/www/root/admin/ReleaseNotes.txt +63 -0
- data/lib/rubyfox/server/data/www/root/admin/assets/icons/tabs/adobeFlashPlayer.png +0 -0
- data/lib/rubyfox/server/data/www/root/admin/assets/icons/tabs/advanced.png +0 -0
- data/lib/rubyfox/server/data/www/root/admin/assets/icons/tabs/banManager.png +0 -0
- data/lib/rubyfox/server/data/www/root/admin/assets/icons/tabs/bannedIPs.png +0 -0
- data/lib/rubyfox/server/data/www/root/admin/assets/icons/tabs/bannedUsernames.png +0 -0
- data/lib/rubyfox/server/data/www/root/admin/assets/icons/tabs/bookmarks.png +0 -0
- data/lib/rubyfox/server/data/www/root/admin/assets/icons/tabs/bootLog.png +0 -0
- data/lib/rubyfox/server/data/www/root/admin/assets/icons/tabs/buddyList.png +0 -0
- data/lib/rubyfox/server/data/www/root/admin/assets/icons/tabs/buddyProperties.png +0 -0
- data/lib/rubyfox/server/data/www/root/admin/assets/icons/tabs/connection.png +0 -0
- data/lib/rubyfox/server/data/www/root/admin/assets/icons/tabs/databaseManager.png +0 -0
- data/lib/rubyfox/server/data/www/root/admin/assets/icons/tabs/floodFilter.png +0 -0
- data/lib/rubyfox/server/data/www/root/admin/assets/icons/tabs/gameSettings.png +0 -0
- data/lib/rubyfox/server/data/www/root/admin/assets/icons/tabs/general.png +0 -0
- data/lib/rubyfox/server/data/www/root/admin/assets/icons/tabs/globalServerStatus.png +0 -0
- data/lib/rubyfox/server/data/www/root/admin/assets/icons/tabs/hTML5WebSockets.png +0 -0
- data/lib/rubyfox/server/data/www/root/admin/assets/icons/tabs/iPFilter.png +0 -0
- data/lib/rubyfox/server/data/www/root/admin/assets/icons/tabs/jVMSettings.png +0 -0
- data/lib/rubyfox/server/data/www/root/admin/assets/icons/tabs/logsDownload.png +0 -0
- data/lib/rubyfox/server/data/www/root/admin/assets/icons/tabs/mailer.png +0 -0
- data/lib/rubyfox/server/data/www/root/admin/assets/icons/tabs/permissionsAndEvents.png +0 -0
- data/lib/rubyfox/server/data/www/root/admin/assets/icons/tabs/privilegeManager.png +0 -0
- data/lib/rubyfox/server/data/www/root/admin/assets/icons/tabs/remoteAdmin.png +0 -0
- data/lib/rubyfox/server/data/www/root/admin/assets/icons/tabs/roomExtension.png +0 -0
- data/lib/rubyfox/server/data/www/root/admin/assets/icons/tabs/roomVariables.png +0 -0
- data/lib/rubyfox/server/data/www/root/admin/assets/icons/tabs/roomsAndGroups.png +0 -0
- data/lib/rubyfox/server/data/www/root/admin/assets/icons/tabs/runtimeLog.png +0 -0
- data/lib/rubyfox/server/data/www/root/admin/assets/icons/tabs/runtimeRoomSettings.png +0 -0
- data/lib/rubyfox/server/data/www/root/admin/assets/icons/tabs/runtimeUserSettings.png +0 -0
- data/lib/rubyfox/server/data/www/root/admin/assets/icons/tabs/runtimeZoneSettings.png +0 -0
- data/lib/rubyfox/server/data/www/root/admin/assets/icons/tabs/systemQueueStatus.png +0 -0
- data/lib/rubyfox/server/data/www/root/admin/assets/icons/tabs/userManagement.png +0 -0
- data/lib/rubyfox/server/data/www/root/admin/assets/icons/tabs/userVariables.png +0 -0
- data/lib/rubyfox/server/data/www/root/admin/assets/icons/tabs/usersTraffic.png +0 -0
- data/lib/rubyfox/server/data/www/root/admin/assets/icons/tabs/webServer.png +0 -0
- data/lib/rubyfox/server/data/www/root/admin/assets/icons/tabs/wordsFilter.png +0 -0
- data/lib/rubyfox/server/data/www/root/admin/assets/icons/tabs/zoneExtension.png +0 -0
- data/lib/rubyfox/server/data/www/root/admin/index.html +108 -0
- data/lib/rubyfox/server/data/www/root/admin/modules/BanManager/BanManager.swf +0 -0
- data/lib/rubyfox/server/data/www/root/admin/modules/BanManager/icon.png +0 -0
- data/lib/rubyfox/server/data/www/root/admin/modules/BlueBoxMonitor/BlueBoxMonitor.swf +0 -0
- data/lib/rubyfox/server/data/www/root/admin/modules/BlueBoxMonitor/icon.png +0 -0
- data/lib/rubyfox/server/data/www/root/admin/modules/Dashboard/Dashboard.swf +0 -0
- data/lib/rubyfox/server/data/www/root/admin/modules/Dashboard/icon.png +0 -0
- data/lib/rubyfox/server/data/www/root/admin/modules/LicenseManager/LicenseManager.swf +0 -0
- data/lib/rubyfox/server/data/www/root/admin/modules/LicenseManager/icon.png +0 -0
- data/lib/rubyfox/server/data/www/root/admin/modules/LogViewer/LogViewer.swf +0 -0
- data/lib/rubyfox/server/data/www/root/admin/modules/LogViewer/icon.png +0 -0
- data/lib/rubyfox/server/data/www/root/admin/modules/RuntimeStatistics/RuntimeStatistics.swf +0 -0
- data/lib/rubyfox/server/data/www/root/admin/modules/RuntimeStatistics/icon.png +0 -0
- data/lib/rubyfox/server/data/www/root/admin/modules/ServerConfigurator/ServerConfigurator.swf +0 -0
- data/lib/rubyfox/server/data/www/root/admin/modules/ServerConfigurator/icon.png +0 -0
- data/lib/rubyfox/server/data/www/root/admin/modules/ZoneConfigurator/ZoneConfigurator.swf +0 -0
- data/lib/rubyfox/server/data/www/root/admin/modules/ZoneConfigurator/icon.png +0 -0
- data/lib/rubyfox/server/data/www/root/admin/modules/ZoneMonitor/ZoneMonitor.swf +0 -0
- data/lib/rubyfox/server/data/www/root/admin/modules/ZoneMonitor/icon.png +0 -0
- data/lib/rubyfox/server/data/www/root/admin/modules/config.xml +12 -0
- data/lib/rubyfox/server/data/www/root/admin/playerProductInstall.swf +0 -0
- data/lib/rubyfox/server/data/www/root/admin/swfobject.js +777 -0
- data/lib/rubyfox/server/data/www/root/crossdomain.xml +6 -0
- data/lib/rubyfox/server/data/www/root/examples/.keep +0 -0
- data/lib/rubyfox/server/data/www/root/examples/index.html +43 -0
- data/lib/rubyfox/server/data/www/root/index.html +63 -0
- data/lib/rubyfox/server/data/zones/.keep +0 -0
- data/lib/rubyfox/server/environment.rb +31 -0
- data/lib/rubyfox/server/version.rb +5 -0
- data/lib/rubyfox/server.rb +9 -0
- data/rubyfox-server.gemspec +22 -0
- metadata +1076 -0
|
@@ -0,0 +1,2007 @@
|
|
|
1
|
+
"""Concrete date/time and related types -- prototype implemented in Python.
|
|
2
|
+
|
|
3
|
+
See http://www.zope.org/Members/fdrake/DateTimeWiki/FrontPage
|
|
4
|
+
|
|
5
|
+
See also http://dir.yahoo.com/Reference/calendars/
|
|
6
|
+
|
|
7
|
+
For a primer on DST, including many current DST rules, see
|
|
8
|
+
http://webexhibits.org/daylightsaving/
|
|
9
|
+
|
|
10
|
+
For more about DST than you ever wanted to know, see
|
|
11
|
+
ftp://elsie.nci.nih.gov/pub/
|
|
12
|
+
|
|
13
|
+
Sources for time zone and DST data: http://www.twinsun.com/tz/tz-link.htm
|
|
14
|
+
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
import time as _time
|
|
18
|
+
import math as _math
|
|
19
|
+
|
|
20
|
+
MINYEAR = 1
|
|
21
|
+
MAXYEAR = 9999
|
|
22
|
+
|
|
23
|
+
# Utility functions, adapted from Python's Demo/classes/Dates.py, which
|
|
24
|
+
# also assumes the current Gregorian calendar indefinitely extended in
|
|
25
|
+
# both directions. Difference: Dates.py calls January 1 of year 0 day
|
|
26
|
+
# number 1. The code here calls January 1 of year 1 day number 1. This is
|
|
27
|
+
# to match the definition of the "proleptic Gregorian" calendar in Dershowitz
|
|
28
|
+
# and Reingold's "Calendrical Calculations", where it's the base calendar
|
|
29
|
+
# for all computations. See the book for algorithms for converting between
|
|
30
|
+
# proleptic Gregorian ordinals and many other calendar systems.
|
|
31
|
+
|
|
32
|
+
_DAYS_IN_MONTH = [None, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
|
|
33
|
+
|
|
34
|
+
_DAYS_BEFORE_MONTH = [None]
|
|
35
|
+
dbm = 0
|
|
36
|
+
for dim in _DAYS_IN_MONTH[1:]:
|
|
37
|
+
_DAYS_BEFORE_MONTH.append(dbm)
|
|
38
|
+
dbm += dim
|
|
39
|
+
del dbm, dim
|
|
40
|
+
|
|
41
|
+
def _is_leap(year):
|
|
42
|
+
"year -> 1 if leap year, else 0."
|
|
43
|
+
return year % 4 == 0 and (year % 100 != 0 or year % 400 == 0)
|
|
44
|
+
|
|
45
|
+
def _days_in_year(year):
|
|
46
|
+
"year -> number of days in year (366 if a leap year, else 365)."
|
|
47
|
+
return 365 + _is_leap(year)
|
|
48
|
+
|
|
49
|
+
def _days_before_year(year):
|
|
50
|
+
"year -> number of days before January 1st of year."
|
|
51
|
+
y = year - 1
|
|
52
|
+
return y*365 + y//4 - y//100 + y//400
|
|
53
|
+
|
|
54
|
+
def _days_in_month(year, month):
|
|
55
|
+
"year, month -> number of days in that month in that year."
|
|
56
|
+
assert 1 <= month <= 12, month
|
|
57
|
+
if month == 2 and _is_leap(year):
|
|
58
|
+
return 29
|
|
59
|
+
return _DAYS_IN_MONTH[month]
|
|
60
|
+
|
|
61
|
+
def _days_before_month(year, month):
|
|
62
|
+
"year, month -> number of days in year preceeding first day of month."
|
|
63
|
+
if not 1 <= month <= 12:
|
|
64
|
+
raise ValueError('month must be in 1..12', month)
|
|
65
|
+
return _DAYS_BEFORE_MONTH[month] + (month > 2 and _is_leap(year))
|
|
66
|
+
|
|
67
|
+
def _ymd2ord(year, month, day):
|
|
68
|
+
"year, month, day -> ordinal, considering 01-Jan-0001 as day 1."
|
|
69
|
+
if not 1 <= month <= 12:
|
|
70
|
+
raise ValueError('month must be in 1..12', month)
|
|
71
|
+
dim = _days_in_month(year, month)
|
|
72
|
+
if not 1 <= day <= dim:
|
|
73
|
+
raise ValueError('day must be in 1..%d' % dim, day)
|
|
74
|
+
return (_days_before_year(year) +
|
|
75
|
+
_days_before_month(year, month) +
|
|
76
|
+
day)
|
|
77
|
+
|
|
78
|
+
_DI400Y = _days_before_year(401) # number of days in 400 years
|
|
79
|
+
_DI100Y = _days_before_year(101) # " " " " 100 "
|
|
80
|
+
_DI4Y = _days_before_year(5) # " " " " 4 "
|
|
81
|
+
|
|
82
|
+
# A 4-year cycle has an extra leap day over what we'd get from pasting
|
|
83
|
+
# together 4 single years.
|
|
84
|
+
assert _DI4Y == 4 * 365 + 1
|
|
85
|
+
|
|
86
|
+
# Similarly, a 400-year cycle has an extra leap day over what we'd get from
|
|
87
|
+
# pasting together 4 100-year cycles.
|
|
88
|
+
assert _DI400Y == 4 * _DI100Y + 1
|
|
89
|
+
|
|
90
|
+
# OTOH, a 100-year cycle has one fewer leap day than we'd get from
|
|
91
|
+
# pasting together 25 4-year cycles.
|
|
92
|
+
assert _DI100Y == 25 * _DI4Y - 1
|
|
93
|
+
|
|
94
|
+
def _ord2ymd(n):
|
|
95
|
+
"ordinal -> (year, month, day), considering 01-Jan-0001 as day 1."
|
|
96
|
+
|
|
97
|
+
# n is a 1-based index, starting at 1-Jan-1. The pattern of leap years
|
|
98
|
+
# repeats exactly every 400 years. The basic strategy is to find the
|
|
99
|
+
# closest 400-year boundary at or before n, then work with the offset
|
|
100
|
+
# from that boundary to n. Life is much clearer if we subtract 1 from
|
|
101
|
+
# n first -- then the values of n at 400-year boundaries are exactly
|
|
102
|
+
# those divisible by _DI400Y:
|
|
103
|
+
#
|
|
104
|
+
# D M Y n n-1
|
|
105
|
+
# -- --- ---- ---------- ----------------
|
|
106
|
+
# 31 Dec -400 -_DI400Y -_DI400Y -1
|
|
107
|
+
# 1 Jan -399 -_DI400Y +1 -_DI400Y 400-year boundary
|
|
108
|
+
# ...
|
|
109
|
+
# 30 Dec 000 -1 -2
|
|
110
|
+
# 31 Dec 000 0 -1
|
|
111
|
+
# 1 Jan 001 1 0 400-year boundary
|
|
112
|
+
# 2 Jan 001 2 1
|
|
113
|
+
# 3 Jan 001 3 2
|
|
114
|
+
# ...
|
|
115
|
+
# 31 Dec 400 _DI400Y _DI400Y -1
|
|
116
|
+
# 1 Jan 401 _DI400Y +1 _DI400Y 400-year boundary
|
|
117
|
+
n -= 1
|
|
118
|
+
n400, n = divmod(n, _DI400Y)
|
|
119
|
+
year = n400 * 400 + 1 # ..., -399, 1, 401, ...
|
|
120
|
+
|
|
121
|
+
# Now n is the (non-negative) offset, in days, from January 1 of year, to
|
|
122
|
+
# the desired date. Now compute how many 100-year cycles precede n.
|
|
123
|
+
# Note that it's possible for n100 to equal 4! In that case 4 full
|
|
124
|
+
# 100-year cycles precede the desired day, which implies the desired
|
|
125
|
+
# day is December 31 at the end of a 400-year cycle.
|
|
126
|
+
n100, n = divmod(n, _DI100Y)
|
|
127
|
+
|
|
128
|
+
# Now compute how many 4-year cycles precede it.
|
|
129
|
+
n4, n = divmod(n, _DI4Y)
|
|
130
|
+
|
|
131
|
+
# And now how many single years. Again n1 can be 4, and again meaning
|
|
132
|
+
# that the desired day is December 31 at the end of the 4-year cycle.
|
|
133
|
+
n1, n = divmod(n, 365)
|
|
134
|
+
|
|
135
|
+
year += n100 * 100 + n4 * 4 + n1
|
|
136
|
+
if n1 == 4 or n100 == 4:
|
|
137
|
+
assert n == 0
|
|
138
|
+
return year-1, 12, 31
|
|
139
|
+
|
|
140
|
+
# Now the year is correct, and n is the offset from January 1. We find
|
|
141
|
+
# the month via an estimate that's either exact or one too large.
|
|
142
|
+
leapyear = n1 == 3 and (n4 != 24 or n100 == 3)
|
|
143
|
+
assert leapyear == _is_leap(year)
|
|
144
|
+
month = (n + 50) >> 5
|
|
145
|
+
preceding = _DAYS_BEFORE_MONTH[month] + (month > 2 and leapyear)
|
|
146
|
+
if preceding > n: # estimate is too large
|
|
147
|
+
month -= 1
|
|
148
|
+
preceding -= _DAYS_IN_MONTH[month] + (month == 2 and leapyear)
|
|
149
|
+
n -= preceding
|
|
150
|
+
assert 0 <= n < _days_in_month(year, month)
|
|
151
|
+
|
|
152
|
+
# Now the year and month are correct, and n is the offset from the
|
|
153
|
+
# start of that month: we're done!
|
|
154
|
+
return year, month, n+1
|
|
155
|
+
|
|
156
|
+
# Month and day names. For localized versions, see the calendar module.
|
|
157
|
+
_MONTHNAMES = [None, "Jan", "Feb", "Mar", "Apr", "May", "Jun",
|
|
158
|
+
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]
|
|
159
|
+
_DAYNAMES = [None, "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"]
|
|
160
|
+
|
|
161
|
+
|
|
162
|
+
def _build_struct_time(y, m, d, hh, mm, ss, dstflag):
|
|
163
|
+
wday = (_ymd2ord(y, m, d) + 6) % 7
|
|
164
|
+
dnum = _days_before_month(y, m) + d
|
|
165
|
+
return _time.struct_time((y, m, d, hh, mm, ss, wday, dnum, dstflag))
|
|
166
|
+
|
|
167
|
+
def _format_time(hh, mm, ss, us):
|
|
168
|
+
# Skip trailing microseconds when us==0.
|
|
169
|
+
result = "%02d:%02d:%02d" % (hh, mm, ss)
|
|
170
|
+
if us:
|
|
171
|
+
result += ".%06d" % us
|
|
172
|
+
return result
|
|
173
|
+
|
|
174
|
+
# Correctly substitute for %z and %Z escapes in strftime formats.
|
|
175
|
+
def _wrap_strftime(object, format, timetuple):
|
|
176
|
+
year = timetuple[0]
|
|
177
|
+
if year < 1900:
|
|
178
|
+
raise ValueError("year=%d is before 1900; the datetime strftime() "
|
|
179
|
+
"methods require year >= 1900" % year)
|
|
180
|
+
# Don't call _utcoffset() or tzname() unless actually needed.
|
|
181
|
+
zreplace = None # the string to use for %z
|
|
182
|
+
Zreplace = None # the string to use for %Z
|
|
183
|
+
|
|
184
|
+
# Scan format for %z and %Z escapes, replacing as needed.
|
|
185
|
+
newformat = []
|
|
186
|
+
push = newformat.append
|
|
187
|
+
i, n = 0, len(format)
|
|
188
|
+
while i < n:
|
|
189
|
+
ch = format[i]
|
|
190
|
+
i += 1
|
|
191
|
+
if ch == '%':
|
|
192
|
+
if i < n:
|
|
193
|
+
ch = format[i]
|
|
194
|
+
i += 1
|
|
195
|
+
if ch == 'z':
|
|
196
|
+
if zreplace is None:
|
|
197
|
+
zreplace = ""
|
|
198
|
+
if hasattr(object, "_utcoffset"):
|
|
199
|
+
offset = object._utcoffset()
|
|
200
|
+
if offset is not None:
|
|
201
|
+
sign = '+'
|
|
202
|
+
if offset < 0:
|
|
203
|
+
offset = -offset
|
|
204
|
+
sign = '-'
|
|
205
|
+
h, m = divmod(offset, 60)
|
|
206
|
+
zreplace = '%c%02d%02d' % (sign, h, m)
|
|
207
|
+
assert '%' not in zreplace
|
|
208
|
+
newformat.append(zreplace)
|
|
209
|
+
elif ch == 'Z':
|
|
210
|
+
if Zreplace is None:
|
|
211
|
+
Zreplace = ""
|
|
212
|
+
if hasattr(object, "tzname"):
|
|
213
|
+
s = object.tzname()
|
|
214
|
+
if s is not None:
|
|
215
|
+
# strftime is going to have at this: escape %
|
|
216
|
+
Zreplace = s.replace('%', '%%')
|
|
217
|
+
newformat.append(Zreplace)
|
|
218
|
+
else:
|
|
219
|
+
push('%')
|
|
220
|
+
push(ch)
|
|
221
|
+
else:
|
|
222
|
+
push('%')
|
|
223
|
+
else:
|
|
224
|
+
push(ch)
|
|
225
|
+
newformat = "".join(newformat)
|
|
226
|
+
return _time.strftime(newformat, timetuple)
|
|
227
|
+
|
|
228
|
+
def _call_tzinfo_method(tzinfo, methname, tzinfoarg):
|
|
229
|
+
if tzinfo is None:
|
|
230
|
+
return None
|
|
231
|
+
return getattr(tzinfo, methname)(tzinfoarg)
|
|
232
|
+
|
|
233
|
+
# Just raise TypeError if the arg isn't None or a string.
|
|
234
|
+
def _check_tzname(name):
|
|
235
|
+
if name is not None and not isinstance(name, str):
|
|
236
|
+
raise TypeError("tzinfo.tzname() must return None or string, "
|
|
237
|
+
"not '%s'" % type(name))
|
|
238
|
+
|
|
239
|
+
# name is the offset-producing method, "utcoffset" or "dst".
|
|
240
|
+
# offset is what it returned.
|
|
241
|
+
# If offset isn't None or timedelta, raises TypeError.
|
|
242
|
+
# If offset is None, returns None.
|
|
243
|
+
# Else offset is checked for being in range, and a whole # of minutes.
|
|
244
|
+
# If it is, its integer value is returned. Else ValueError is raised.
|
|
245
|
+
def _check_utc_offset(name, offset):
|
|
246
|
+
assert name in ("utcoffset", "dst")
|
|
247
|
+
if offset is None:
|
|
248
|
+
return None
|
|
249
|
+
if not isinstance(offset, timedelta):
|
|
250
|
+
raise TypeError("tzinfo.%s() must return None "
|
|
251
|
+
"or timedelta, not '%s'" % (name, type(offset)))
|
|
252
|
+
days = offset.days
|
|
253
|
+
if days < -1 or days > 0:
|
|
254
|
+
offset = 1440 # trigger out-of-range
|
|
255
|
+
else:
|
|
256
|
+
seconds = days * 86400 + offset.seconds
|
|
257
|
+
minutes, seconds = divmod(seconds, 60)
|
|
258
|
+
if seconds or offset.microseconds:
|
|
259
|
+
raise ValueError("tzinfo.%s() must return a whole number "
|
|
260
|
+
"of minutes" % name)
|
|
261
|
+
offset = minutes
|
|
262
|
+
if -1440 < offset < 1440:
|
|
263
|
+
return offset
|
|
264
|
+
raise ValueError("%s()=%d, must be in -1439..1439" % (name, offset))
|
|
265
|
+
|
|
266
|
+
def _check_date_fields(year, month, day):
|
|
267
|
+
if not MINYEAR <= year <= MAXYEAR:
|
|
268
|
+
raise ValueError('year must be in %d..%d' % (MINYEAR, MAXYEAR), year)
|
|
269
|
+
if not 1 <= month <= 12:
|
|
270
|
+
raise ValueError('month must be in 1..12', month)
|
|
271
|
+
dim = _days_in_month(year, month)
|
|
272
|
+
if not 1 <= day <= dim:
|
|
273
|
+
raise ValueError('day must be in 1..%d' % dim, day)
|
|
274
|
+
|
|
275
|
+
def _check_time_fields(hour, minute, second, microsecond):
|
|
276
|
+
if not 0 <= hour <= 23:
|
|
277
|
+
raise ValueError('hour must be in 0..23', hour)
|
|
278
|
+
if not 0 <= minute <= 59:
|
|
279
|
+
raise ValueError('minute must be in 0..59', minute)
|
|
280
|
+
if not 0 <= second <= 59:
|
|
281
|
+
raise ValueError('second must be in 0..59', second)
|
|
282
|
+
if not 0 <= microsecond <= 999999:
|
|
283
|
+
raise ValueError('microsecond must be in 0..999999', microsecond)
|
|
284
|
+
|
|
285
|
+
def _check_tzinfo_arg(tz):
|
|
286
|
+
if tz is not None and not isinstance(tz, tzinfo):
|
|
287
|
+
raise TypeError("tzinfo argument must be None or of a tzinfo subclass")
|
|
288
|
+
|
|
289
|
+
|
|
290
|
+
# Notes on comparison: In general, datetime module comparison operators raise
|
|
291
|
+
# TypeError when they don't know how to do a comparison themself. If they
|
|
292
|
+
# returned NotImplemented instead, comparison could (silently) fall back to
|
|
293
|
+
# the default compare-objects-by-comparing-their-memory-addresses strategy,
|
|
294
|
+
# and that's not helpful. There are two exceptions:
|
|
295
|
+
#
|
|
296
|
+
# 1. For date and datetime, if the other object has a "timetuple" attr,
|
|
297
|
+
# NotImplemented is returned. This is a hook to allow other kinds of
|
|
298
|
+
# datetime-like objects a chance to intercept the comparison.
|
|
299
|
+
#
|
|
300
|
+
# 2. Else __eq__ and __ne__ return False and True, respectively. This is
|
|
301
|
+
# so opertaions like
|
|
302
|
+
#
|
|
303
|
+
# x == y
|
|
304
|
+
# x != y
|
|
305
|
+
# x in sequence
|
|
306
|
+
# x not in sequence
|
|
307
|
+
# dict[x] = y
|
|
308
|
+
#
|
|
309
|
+
# don't raise annoying TypeErrors just because a datetime object
|
|
310
|
+
# is part of a heterogeneous collection. If there's no known way to
|
|
311
|
+
# compare X to a datetime, saying they're not equal is reasonable.
|
|
312
|
+
|
|
313
|
+
def _cmperror(x, y):
|
|
314
|
+
raise TypeError("can't compare '%s' to '%s'" % (
|
|
315
|
+
type(x).__name__, type(y).__name__))
|
|
316
|
+
|
|
317
|
+
# This is a start at a struct tm workalike. Goals:
|
|
318
|
+
#
|
|
319
|
+
# + Works the same way across platforms.
|
|
320
|
+
# + Handles all the fields datetime needs handled, without 1970-2038 glitches.
|
|
321
|
+
#
|
|
322
|
+
# Note: I suspect it's best if this flavor of tm does *not* try to
|
|
323
|
+
# second-guess timezones or DST. Instead fold whatever adjustments you want
|
|
324
|
+
# into the minutes argument (and the constructor will normalize).
|
|
325
|
+
|
|
326
|
+
_ORD1970 = _ymd2ord(1970, 1, 1) # base ordinal for UNIX epoch
|
|
327
|
+
|
|
328
|
+
class tmxxx:
|
|
329
|
+
|
|
330
|
+
ordinal = None
|
|
331
|
+
|
|
332
|
+
def __init__(self, year, month, day, hour=0, minute=0, second=0,
|
|
333
|
+
microsecond=0):
|
|
334
|
+
# Normalize all the inputs, and store the normalized values.
|
|
335
|
+
if not 0 <= microsecond <= 999999:
|
|
336
|
+
carry, microsecond = divmod(microsecond, 1000000)
|
|
337
|
+
second += carry
|
|
338
|
+
if not 0 <= second <= 59:
|
|
339
|
+
carry, second = divmod(second, 60)
|
|
340
|
+
minute += carry
|
|
341
|
+
if not 0 <= minute <= 59:
|
|
342
|
+
carry, minute = divmod(minute, 60)
|
|
343
|
+
hour += carry
|
|
344
|
+
if not 0 <= hour <= 23:
|
|
345
|
+
carry, hour = divmod(hour, 24)
|
|
346
|
+
day += carry
|
|
347
|
+
|
|
348
|
+
# That was easy. Now it gets muddy: the proper range for day
|
|
349
|
+
# can't be determined without knowing the correct month and year,
|
|
350
|
+
# but if day is, e.g., plus or minus a million, the current month
|
|
351
|
+
# and year values make no sense (and may also be out of bounds
|
|
352
|
+
# themselves).
|
|
353
|
+
# Saying 12 months == 1 year should be non-controversial.
|
|
354
|
+
if not 1 <= month <= 12:
|
|
355
|
+
carry, month = divmod(month-1, 12)
|
|
356
|
+
year += carry
|
|
357
|
+
month += 1
|
|
358
|
+
assert 1 <= month <= 12
|
|
359
|
+
|
|
360
|
+
# Now only day can be out of bounds (year may also be out of bounds
|
|
361
|
+
# for a datetime object, but we don't care about that here).
|
|
362
|
+
# If day is out of bounds, what to do is arguable, but at least the
|
|
363
|
+
# method here is principled and explainable.
|
|
364
|
+
dim = _days_in_month(year, month)
|
|
365
|
+
if not 1 <= day <= dim:
|
|
366
|
+
# Move day-1 days from the first of the month. First try to
|
|
367
|
+
# get off cheap if we're only one day out of range (adjustments
|
|
368
|
+
# for timezone alone can't be worse than that).
|
|
369
|
+
if day == 0: # move back a day
|
|
370
|
+
month -= 1
|
|
371
|
+
if month > 0:
|
|
372
|
+
day = _days_in_month(year, month)
|
|
373
|
+
else:
|
|
374
|
+
year, month, day = year-1, 12, 31
|
|
375
|
+
elif day == dim + 1: # move forward a day
|
|
376
|
+
month += 1
|
|
377
|
+
day = 1
|
|
378
|
+
if month > 12:
|
|
379
|
+
month = 1
|
|
380
|
+
year += 1
|
|
381
|
+
else:
|
|
382
|
+
self.ordinal = _ymd2ord(year, month, 1) + (day - 1)
|
|
383
|
+
year, month, day = _ord2ymd(self.ordinal)
|
|
384
|
+
|
|
385
|
+
self.year, self.month, self.day = year, month, day
|
|
386
|
+
self.hour, self.minute, self.second = hour, minute, second
|
|
387
|
+
self.microsecond = microsecond
|
|
388
|
+
|
|
389
|
+
def toordinal(self):
|
|
390
|
+
"""Return proleptic Gregorian ordinal for the year, month and day.
|
|
391
|
+
|
|
392
|
+
January 1 of year 1 is day 1. Only the year, month and day values
|
|
393
|
+
contribute to the result.
|
|
394
|
+
"""
|
|
395
|
+
if self.ordinal is None:
|
|
396
|
+
self.ordinal = _ymd2ord(self.year, self.month, self.day)
|
|
397
|
+
return self.ordinal
|
|
398
|
+
|
|
399
|
+
def time(self):
|
|
400
|
+
"Return Unixish timestamp, as a float (assuming UTC)."
|
|
401
|
+
days = self.toordinal() - _ORD1970 # convert to UNIX epoch
|
|
402
|
+
seconds = ((days * 24. + self.hour)*60. + self.minute)*60.
|
|
403
|
+
return seconds + self.second + self.microsecond / 1e6
|
|
404
|
+
|
|
405
|
+
def ctime(self):
|
|
406
|
+
"Return ctime() style string."
|
|
407
|
+
weekday = self.toordinal() % 7 or 7
|
|
408
|
+
return "%s %s %2d %02d:%02d:%02d %04d" % (
|
|
409
|
+
_DAYNAMES[weekday],
|
|
410
|
+
_MONTHNAMES[self.month],
|
|
411
|
+
self.day,
|
|
412
|
+
self.hour, self.minute, self.second,
|
|
413
|
+
self.year)
|
|
414
|
+
|
|
415
|
+
class timedelta(object):
|
|
416
|
+
"""Represent the difference between two datetime objects.
|
|
417
|
+
|
|
418
|
+
Supported operators:
|
|
419
|
+
|
|
420
|
+
- add, subtract timedelta
|
|
421
|
+
- unary plus, minus, abs
|
|
422
|
+
- compare to timedelta
|
|
423
|
+
- multiply, divide by int/long
|
|
424
|
+
|
|
425
|
+
In addition, datetime supports subtraction of two datetime objects
|
|
426
|
+
returning a timedelta, and addition or subtraction of a datetime
|
|
427
|
+
and a timedelta giving a datetime.
|
|
428
|
+
|
|
429
|
+
Representation: (days, seconds, microseconds). Why? Because I
|
|
430
|
+
felt like it.
|
|
431
|
+
"""
|
|
432
|
+
|
|
433
|
+
def __new__(cls, days=0, seconds=0, microseconds=0,
|
|
434
|
+
# XXX The following should only be used as keyword args:
|
|
435
|
+
milliseconds=0, minutes=0, hours=0, weeks=0):
|
|
436
|
+
# Doing this efficiently and accurately in C is going to be difficult
|
|
437
|
+
# and error-prone, due to ubiquitous overflow possibilities, and that
|
|
438
|
+
# C double doesn't have enough bits of precision to represent
|
|
439
|
+
# microseconds over 10K years faithfully. The code here tries to make
|
|
440
|
+
# explicit where go-fast assumptions can be relied on, in order to
|
|
441
|
+
# guide the C implementation; it's way more convoluted than speed-
|
|
442
|
+
# ignoring auto-overflow-to-long idiomatic Python could be.
|
|
443
|
+
|
|
444
|
+
# XXX Check that all inputs are ints, longs or floats.
|
|
445
|
+
|
|
446
|
+
# Final values, all integer.
|
|
447
|
+
# s and us fit in 32-bit signed ints; d isn't bounded.
|
|
448
|
+
d = s = us = 0
|
|
449
|
+
|
|
450
|
+
# Normalize everything to days, seconds, microseconds.
|
|
451
|
+
days += weeks*7
|
|
452
|
+
seconds += minutes*60 + hours*3600
|
|
453
|
+
microseconds += milliseconds*1000
|
|
454
|
+
|
|
455
|
+
# Get rid of all fractions, and normalize s and us.
|
|
456
|
+
# Take a deep breath <wink>.
|
|
457
|
+
if isinstance(days, float):
|
|
458
|
+
dayfrac, days = _math.modf(days)
|
|
459
|
+
daysecondsfrac, daysecondswhole = _math.modf(dayfrac * (24.*3600.))
|
|
460
|
+
assert daysecondswhole == int(daysecondswhole) # can't overflow
|
|
461
|
+
s = int(daysecondswhole)
|
|
462
|
+
assert days == long(days)
|
|
463
|
+
d = long(days)
|
|
464
|
+
else:
|
|
465
|
+
daysecondsfrac = 0.0
|
|
466
|
+
d = days
|
|
467
|
+
assert isinstance(daysecondsfrac, float)
|
|
468
|
+
assert abs(daysecondsfrac) <= 1.0
|
|
469
|
+
assert isinstance(d, (int, long))
|
|
470
|
+
assert abs(s) <= 24 * 3600
|
|
471
|
+
# days isn't referenced again before redefinition
|
|
472
|
+
|
|
473
|
+
if isinstance(seconds, float):
|
|
474
|
+
secondsfrac, seconds = _math.modf(seconds)
|
|
475
|
+
assert seconds == long(seconds)
|
|
476
|
+
seconds = long(seconds)
|
|
477
|
+
secondsfrac += daysecondsfrac
|
|
478
|
+
assert abs(secondsfrac) <= 2.0
|
|
479
|
+
else:
|
|
480
|
+
secondsfrac = daysecondsfrac
|
|
481
|
+
# daysecondsfrac isn't referenced again
|
|
482
|
+
assert isinstance(secondsfrac, float)
|
|
483
|
+
assert abs(secondsfrac) <= 2.0
|
|
484
|
+
|
|
485
|
+
assert isinstance(seconds, (int, long))
|
|
486
|
+
days, seconds = divmod(seconds, 24*3600)
|
|
487
|
+
d += days
|
|
488
|
+
s += int(seconds) # can't overflow
|
|
489
|
+
assert isinstance(s, int)
|
|
490
|
+
assert abs(s) <= 2 * 24 * 3600
|
|
491
|
+
# seconds isn't referenced again before redefinition
|
|
492
|
+
|
|
493
|
+
usdouble = secondsfrac * 1e6
|
|
494
|
+
assert abs(usdouble) < 2.1e6 # exact value not critical
|
|
495
|
+
# secondsfrac isn't referenced again
|
|
496
|
+
|
|
497
|
+
if isinstance(microseconds, float):
|
|
498
|
+
microseconds += usdouble
|
|
499
|
+
microseconds = round(microseconds)
|
|
500
|
+
seconds, microseconds = divmod(microseconds, 1e6)
|
|
501
|
+
assert microseconds == int(microseconds)
|
|
502
|
+
assert seconds == long(seconds)
|
|
503
|
+
days, seconds = divmod(seconds, 24.*3600.)
|
|
504
|
+
assert days == long(days)
|
|
505
|
+
assert seconds == int(seconds)
|
|
506
|
+
d += long(days)
|
|
507
|
+
s += int(seconds) # can't overflow
|
|
508
|
+
assert isinstance(s, int)
|
|
509
|
+
assert abs(s) <= 3 * 24 * 3600
|
|
510
|
+
else:
|
|
511
|
+
seconds, microseconds = divmod(microseconds, 1000000)
|
|
512
|
+
days, seconds = divmod(seconds, 24*3600)
|
|
513
|
+
d += days
|
|
514
|
+
s += int(seconds) # can't overflow
|
|
515
|
+
assert isinstance(s, int)
|
|
516
|
+
assert abs(s) <= 3 * 24 * 3600
|
|
517
|
+
microseconds = float(microseconds)
|
|
518
|
+
microseconds += usdouble
|
|
519
|
+
microseconds = round(microseconds)
|
|
520
|
+
assert abs(s) <= 3 * 24 * 3600
|
|
521
|
+
assert abs(microseconds) < 3.1e6
|
|
522
|
+
|
|
523
|
+
# Just a little bit of carrying possible for microseconds and seconds.
|
|
524
|
+
assert isinstance(microseconds, float)
|
|
525
|
+
assert int(microseconds) == microseconds
|
|
526
|
+
us = int(microseconds)
|
|
527
|
+
seconds, us = divmod(us, 1000000)
|
|
528
|
+
s += seconds # cant't overflow
|
|
529
|
+
assert isinstance(s, int)
|
|
530
|
+
days, s = divmod(s, 24*3600)
|
|
531
|
+
d += days
|
|
532
|
+
|
|
533
|
+
assert isinstance(d, (int, long))
|
|
534
|
+
assert isinstance(s, int) and 0 <= s < 24*3600
|
|
535
|
+
assert isinstance(us, int) and 0 <= us < 1000000
|
|
536
|
+
|
|
537
|
+
self = object.__new__(cls)
|
|
538
|
+
|
|
539
|
+
self.__days = d
|
|
540
|
+
self.__seconds = s
|
|
541
|
+
self.__microseconds = us
|
|
542
|
+
if abs(d) > 999999999:
|
|
543
|
+
raise OverflowError("timedelta # of days is too large: %d" % d)
|
|
544
|
+
|
|
545
|
+
return self
|
|
546
|
+
|
|
547
|
+
def __repr__(self):
|
|
548
|
+
if self.__microseconds:
|
|
549
|
+
return "%s(%d, %d, %d)" % ('datetime.' + self.__class__.__name__,
|
|
550
|
+
self.__days,
|
|
551
|
+
self.__seconds,
|
|
552
|
+
self.__microseconds)
|
|
553
|
+
if self.__seconds:
|
|
554
|
+
return "%s(%d, %d)" % ('datetime.' + self.__class__.__name__,
|
|
555
|
+
self.__days,
|
|
556
|
+
self.__seconds)
|
|
557
|
+
return "%s(%d)" % ('datetime.' + self.__class__.__name__, self.__days)
|
|
558
|
+
|
|
559
|
+
def __str__(self):
|
|
560
|
+
mm, ss = divmod(self.__seconds, 60)
|
|
561
|
+
hh, mm = divmod(mm, 60)
|
|
562
|
+
s = "%d:%02d:%02d" % (hh, mm, ss)
|
|
563
|
+
if self.__days:
|
|
564
|
+
def plural(n):
|
|
565
|
+
return n, abs(n) != 1 and "s" or ""
|
|
566
|
+
s = ("%d day%s, " % plural(self.__days)) + s
|
|
567
|
+
if self.__microseconds:
|
|
568
|
+
s = s + ".%06d" % self.__microseconds
|
|
569
|
+
return s
|
|
570
|
+
|
|
571
|
+
days = property(lambda self: self.__days, doc="days")
|
|
572
|
+
seconds = property(lambda self: self.__seconds, doc="seconds")
|
|
573
|
+
microseconds = property(lambda self: self.__microseconds,
|
|
574
|
+
doc="microseconds")
|
|
575
|
+
|
|
576
|
+
def __add__(self, other):
|
|
577
|
+
if isinstance(other, timedelta):
|
|
578
|
+
return self.__class__(self.__days + other.__days,
|
|
579
|
+
self.__seconds + other.__seconds,
|
|
580
|
+
self.__microseconds + other.__microseconds)
|
|
581
|
+
return NotImplemented
|
|
582
|
+
|
|
583
|
+
__radd__ = __add__
|
|
584
|
+
|
|
585
|
+
def __sub__(self, other):
|
|
586
|
+
if isinstance(other, timedelta):
|
|
587
|
+
return self + -other
|
|
588
|
+
return NotImplemented
|
|
589
|
+
|
|
590
|
+
def __rsub__(self, other):
|
|
591
|
+
if isinstance(other, timedelta):
|
|
592
|
+
return -self + other
|
|
593
|
+
return NotImplemented
|
|
594
|
+
|
|
595
|
+
def __neg__(self):
|
|
596
|
+
return self.__class__(-self.__days,
|
|
597
|
+
-self.__seconds,
|
|
598
|
+
-self.__microseconds)
|
|
599
|
+
|
|
600
|
+
def __pos__(self):
|
|
601
|
+
return self
|
|
602
|
+
|
|
603
|
+
def __abs__(self):
|
|
604
|
+
if self.__days < 0:
|
|
605
|
+
return -self
|
|
606
|
+
else:
|
|
607
|
+
return self
|
|
608
|
+
|
|
609
|
+
def __mul__(self, other):
|
|
610
|
+
if isinstance(other, (int, long)):
|
|
611
|
+
return self.__class__(self.__days * other,
|
|
612
|
+
self.__seconds * other,
|
|
613
|
+
self.__microseconds * other)
|
|
614
|
+
return NotImplemented
|
|
615
|
+
|
|
616
|
+
__rmul__ = __mul__
|
|
617
|
+
|
|
618
|
+
def __div__(self, other):
|
|
619
|
+
if isinstance(other, (int, long)):
|
|
620
|
+
usec = ((self.__days * (24*3600L) + self.__seconds) * 1000000 +
|
|
621
|
+
self.__microseconds)
|
|
622
|
+
return self.__class__(0, 0, usec // other)
|
|
623
|
+
return NotImplemented
|
|
624
|
+
|
|
625
|
+
__floordiv__ = __div__
|
|
626
|
+
|
|
627
|
+
# Comparisons.
|
|
628
|
+
|
|
629
|
+
def __eq__(self, other):
|
|
630
|
+
if isinstance(other, timedelta):
|
|
631
|
+
return self.__cmp(other) == 0
|
|
632
|
+
else:
|
|
633
|
+
return False
|
|
634
|
+
|
|
635
|
+
def __ne__(self, other):
|
|
636
|
+
if isinstance(other, timedelta):
|
|
637
|
+
return self.__cmp(other) != 0
|
|
638
|
+
else:
|
|
639
|
+
return True
|
|
640
|
+
|
|
641
|
+
def __le__(self, other):
|
|
642
|
+
if isinstance(other, timedelta):
|
|
643
|
+
return self.__cmp(other) <= 0
|
|
644
|
+
else:
|
|
645
|
+
_cmperror(self, other)
|
|
646
|
+
|
|
647
|
+
def __lt__(self, other):
|
|
648
|
+
if isinstance(other, timedelta):
|
|
649
|
+
return self.__cmp(other) < 0
|
|
650
|
+
else:
|
|
651
|
+
_cmperror(self, other)
|
|
652
|
+
|
|
653
|
+
def __ge__(self, other):
|
|
654
|
+
if isinstance(other, timedelta):
|
|
655
|
+
return self.__cmp(other) >= 0
|
|
656
|
+
else:
|
|
657
|
+
_cmperror(self, other)
|
|
658
|
+
|
|
659
|
+
def __gt__(self, other):
|
|
660
|
+
if isinstance(other, timedelta):
|
|
661
|
+
return self.__cmp(other) > 0
|
|
662
|
+
else:
|
|
663
|
+
_cmperror(self, other)
|
|
664
|
+
|
|
665
|
+
def __cmp(self, other):
|
|
666
|
+
assert isinstance(other, timedelta)
|
|
667
|
+
return cmp(self.__getstate(), other.__getstate())
|
|
668
|
+
|
|
669
|
+
def __hash__(self):
|
|
670
|
+
return hash(self.__getstate())
|
|
671
|
+
|
|
672
|
+
def __nonzero__(self):
|
|
673
|
+
return (self.__days != 0 or
|
|
674
|
+
self.__seconds != 0 or
|
|
675
|
+
self.__microseconds != 0)
|
|
676
|
+
|
|
677
|
+
# Pickle support.
|
|
678
|
+
|
|
679
|
+
__safe_for_unpickling__ = True # For Python 2.2
|
|
680
|
+
|
|
681
|
+
def __getstate(self):
|
|
682
|
+
return (self.__days, self.__seconds, self.__microseconds)
|
|
683
|
+
|
|
684
|
+
def __reduce__(self):
|
|
685
|
+
return (self.__class__, self.__getstate())
|
|
686
|
+
|
|
687
|
+
timedelta.min = timedelta(-999999999)
|
|
688
|
+
timedelta.max = timedelta(days=999999999, hours=23, minutes=59, seconds=59,
|
|
689
|
+
microseconds=999999)
|
|
690
|
+
timedelta.resolution = timedelta(microseconds=1)
|
|
691
|
+
|
|
692
|
+
class date(object):
|
|
693
|
+
"""Concrete date type.
|
|
694
|
+
|
|
695
|
+
Constructors:
|
|
696
|
+
|
|
697
|
+
__new__()
|
|
698
|
+
fromtimestamp()
|
|
699
|
+
today()
|
|
700
|
+
fromordinal()
|
|
701
|
+
|
|
702
|
+
Operators:
|
|
703
|
+
|
|
704
|
+
__repr__, __str__
|
|
705
|
+
__cmp__, __hash__
|
|
706
|
+
__add__, __radd__, __sub__ (add/radd only with timedelta arg)
|
|
707
|
+
|
|
708
|
+
Methods:
|
|
709
|
+
|
|
710
|
+
timetuple()
|
|
711
|
+
toordinal()
|
|
712
|
+
weekday()
|
|
713
|
+
isoweekday(), isocalendar(), isoformat()
|
|
714
|
+
ctime()
|
|
715
|
+
strftime()
|
|
716
|
+
|
|
717
|
+
Properties (readonly):
|
|
718
|
+
year, month, day
|
|
719
|
+
"""
|
|
720
|
+
|
|
721
|
+
def __new__(cls, year, month=None, day=None):
|
|
722
|
+
"""Constructor.
|
|
723
|
+
|
|
724
|
+
Arguments:
|
|
725
|
+
|
|
726
|
+
year, month, day (required, base 1)
|
|
727
|
+
"""
|
|
728
|
+
if isinstance(year, str):
|
|
729
|
+
# Pickle support
|
|
730
|
+
self = object.__new__(cls)
|
|
731
|
+
self.__setstate((year,))
|
|
732
|
+
return self
|
|
733
|
+
_check_date_fields(year, month, day)
|
|
734
|
+
self = object.__new__(cls)
|
|
735
|
+
self.__year = year
|
|
736
|
+
self.__month = month
|
|
737
|
+
self.__day = day
|
|
738
|
+
return self
|
|
739
|
+
|
|
740
|
+
# Additional constructors
|
|
741
|
+
|
|
742
|
+
def fromtimestamp(cls, t):
|
|
743
|
+
"Construct a date from a POSIX timestamp (like time.time())."
|
|
744
|
+
y, m, d, hh, mm, ss, weekday, jday, dst = _time.localtime(t)
|
|
745
|
+
return cls(y, m, d)
|
|
746
|
+
fromtimestamp = classmethod(fromtimestamp)
|
|
747
|
+
|
|
748
|
+
def today(cls):
|
|
749
|
+
"Construct a date from time.time()."
|
|
750
|
+
t = _time.time()
|
|
751
|
+
return cls.fromtimestamp(t)
|
|
752
|
+
today = classmethod(today)
|
|
753
|
+
|
|
754
|
+
def fromordinal(cls, n):
|
|
755
|
+
"""Contruct a date from a proleptic Gregorian ordinal.
|
|
756
|
+
|
|
757
|
+
January 1 of year 1 is day 1. Only the year, month and day are
|
|
758
|
+
non-zero in the result.
|
|
759
|
+
"""
|
|
760
|
+
y, m, d = _ord2ymd(n)
|
|
761
|
+
return cls(y, m, d)
|
|
762
|
+
fromordinal = classmethod(fromordinal)
|
|
763
|
+
|
|
764
|
+
# Conversions to string
|
|
765
|
+
|
|
766
|
+
def __repr__(self):
|
|
767
|
+
"Convert to formal string, for repr()."
|
|
768
|
+
return "%s(%d, %d, %d)" % ('datetime.' + self.__class__.__name__,
|
|
769
|
+
self.__year,
|
|
770
|
+
self.__month,
|
|
771
|
+
self.__day)
|
|
772
|
+
# XXX These shouldn't depend on time.localtime(), because that
|
|
773
|
+
# clips the usable dates to [1970 .. 2038). At least ctime() is
|
|
774
|
+
# easily done without using strftime() -- that's better too because
|
|
775
|
+
# strftime("%c", ...) is locale specific.
|
|
776
|
+
|
|
777
|
+
def ctime(self):
|
|
778
|
+
"Format a la ctime()."
|
|
779
|
+
return tmxxx(self.__year, self.__month, self.__day).ctime()
|
|
780
|
+
|
|
781
|
+
def strftime(self, fmt):
|
|
782
|
+
"Format using strftime()."
|
|
783
|
+
return _wrap_strftime(self, fmt, self.timetuple())
|
|
784
|
+
|
|
785
|
+
def isoformat(self):
|
|
786
|
+
"""Return the date formatted according to ISO.
|
|
787
|
+
|
|
788
|
+
This is 'YYYY-MM-DD'.
|
|
789
|
+
|
|
790
|
+
References:
|
|
791
|
+
- http://www.w3.org/TR/NOTE-datetime
|
|
792
|
+
- http://www.cl.cam.ac.uk/~mgk25/iso-time.html
|
|
793
|
+
"""
|
|
794
|
+
return "%04d-%02d-%02d" % (self.__year, self.__month, self.__day)
|
|
795
|
+
|
|
796
|
+
__str__ = isoformat
|
|
797
|
+
|
|
798
|
+
# Read-only field accessors
|
|
799
|
+
year = property(lambda self: self.__year,
|
|
800
|
+
doc="year (%d-%d)" % (MINYEAR, MAXYEAR))
|
|
801
|
+
month = property(lambda self: self.__month, doc="month (1-12)")
|
|
802
|
+
day = property(lambda self: self.__day, doc="day (1-31)")
|
|
803
|
+
|
|
804
|
+
# Standard conversions, __cmp__, __hash__ (and helpers)
|
|
805
|
+
|
|
806
|
+
def timetuple(self):
|
|
807
|
+
"Return local time tuple compatible with time.localtime()."
|
|
808
|
+
return _build_struct_time(self.__year, self.__month, self.__day,
|
|
809
|
+
0, 0, 0, -1)
|
|
810
|
+
|
|
811
|
+
def toordinal(self):
|
|
812
|
+
"""Return proleptic Gregorian ordinal for the year, month and day.
|
|
813
|
+
|
|
814
|
+
January 1 of year 1 is day 1. Only the year, month and day values
|
|
815
|
+
contribute to the result.
|
|
816
|
+
"""
|
|
817
|
+
return _ymd2ord(self.__year, self.__month, self.__day)
|
|
818
|
+
|
|
819
|
+
def replace(self, year=None, month=None, day=None):
|
|
820
|
+
"""Return a new date with new values for the specified fields."""
|
|
821
|
+
if year is None:
|
|
822
|
+
year = self.__year
|
|
823
|
+
if month is None:
|
|
824
|
+
month = self.__month
|
|
825
|
+
if day is None:
|
|
826
|
+
day = self.__day
|
|
827
|
+
_check_date_fields(year, month, day)
|
|
828
|
+
return date(year, month, day)
|
|
829
|
+
|
|
830
|
+
# Comparisons.
|
|
831
|
+
|
|
832
|
+
def __eq__(self, other):
|
|
833
|
+
if isinstance(other, date):
|
|
834
|
+
return self.__cmp(other) == 0
|
|
835
|
+
elif hasattr(other, "timetuple"):
|
|
836
|
+
return NotImplemented
|
|
837
|
+
else:
|
|
838
|
+
return False
|
|
839
|
+
|
|
840
|
+
def __ne__(self, other):
|
|
841
|
+
if isinstance(other, date):
|
|
842
|
+
return self.__cmp(other) != 0
|
|
843
|
+
elif hasattr(other, "timetuple"):
|
|
844
|
+
return NotImplemented
|
|
845
|
+
else:
|
|
846
|
+
return True
|
|
847
|
+
|
|
848
|
+
def __le__(self, other):
|
|
849
|
+
if isinstance(other, date):
|
|
850
|
+
return self.__cmp(other) <= 0
|
|
851
|
+
elif hasattr(other, "timetuple"):
|
|
852
|
+
return NotImplemented
|
|
853
|
+
else:
|
|
854
|
+
_cmperror(self, other)
|
|
855
|
+
|
|
856
|
+
def __lt__(self, other):
|
|
857
|
+
if isinstance(other, date):
|
|
858
|
+
return self.__cmp(other) < 0
|
|
859
|
+
elif hasattr(other, "timetuple"):
|
|
860
|
+
return NotImplemented
|
|
861
|
+
else:
|
|
862
|
+
_cmperror(self, other)
|
|
863
|
+
|
|
864
|
+
def __ge__(self, other):
|
|
865
|
+
if isinstance(other, date):
|
|
866
|
+
return self.__cmp(other) >= 0
|
|
867
|
+
elif hasattr(other, "timetuple"):
|
|
868
|
+
return NotImplemented
|
|
869
|
+
else:
|
|
870
|
+
_cmperror(self, other)
|
|
871
|
+
|
|
872
|
+
def __gt__(self, other):
|
|
873
|
+
if isinstance(other, date):
|
|
874
|
+
return self.__cmp(other) > 0
|
|
875
|
+
elif hasattr(other, "timetuple"):
|
|
876
|
+
return NotImplemented
|
|
877
|
+
else:
|
|
878
|
+
_cmperror(self, other)
|
|
879
|
+
|
|
880
|
+
def __cmp(self, other):
|
|
881
|
+
assert isinstance(other, date)
|
|
882
|
+
y, m, d = self.__year, self.__month, self.__day
|
|
883
|
+
y2, m2, d2 = other.__year, other.__month, other.__day
|
|
884
|
+
return cmp((y, m, d), (y2, m2, d2))
|
|
885
|
+
|
|
886
|
+
def __hash__(self):
|
|
887
|
+
"Hash."
|
|
888
|
+
return hash(self.__getstate())
|
|
889
|
+
|
|
890
|
+
# Computations
|
|
891
|
+
|
|
892
|
+
def _checkOverflow(self, year):
|
|
893
|
+
if not MINYEAR <= year <= MAXYEAR:
|
|
894
|
+
raise OverflowError("date +/-: result year %d not in %d..%d" %
|
|
895
|
+
(year, MINYEAR, MAXYEAR))
|
|
896
|
+
|
|
897
|
+
def __add__(self, other):
|
|
898
|
+
"Add a date to a timedelta."
|
|
899
|
+
if isinstance(other, timedelta):
|
|
900
|
+
t = tmxxx(self.__year,
|
|
901
|
+
self.__month,
|
|
902
|
+
self.__day + other.days)
|
|
903
|
+
self._checkOverflow(t.year)
|
|
904
|
+
result = self.__class__(t.year, t.month, t.day)
|
|
905
|
+
return result
|
|
906
|
+
raise TypeError
|
|
907
|
+
# XXX Should be 'return NotImplemented', but there's a bug in 2.2...
|
|
908
|
+
|
|
909
|
+
__radd__ = __add__
|
|
910
|
+
|
|
911
|
+
def __sub__(self, other):
|
|
912
|
+
"""Subtract two dates, or a date and a timedelta."""
|
|
913
|
+
if isinstance(other, timedelta):
|
|
914
|
+
return self + timedelta(-other.days)
|
|
915
|
+
if isinstance(other, date):
|
|
916
|
+
days1 = self.toordinal()
|
|
917
|
+
days2 = other.toordinal()
|
|
918
|
+
return timedelta(days1 - days2)
|
|
919
|
+
return NotImplemented
|
|
920
|
+
|
|
921
|
+
def weekday(self):
|
|
922
|
+
"Return day of the week, where Monday == 0 ... Sunday == 6."
|
|
923
|
+
return (self.toordinal() + 6) % 7
|
|
924
|
+
|
|
925
|
+
# Day-of-the-week and week-of-the-year, according to ISO
|
|
926
|
+
|
|
927
|
+
def isoweekday(self):
|
|
928
|
+
"Return day of the week, where Monday == 1 ... Sunday == 7."
|
|
929
|
+
# 1-Jan-0001 is a Monday
|
|
930
|
+
return self.toordinal() % 7 or 7
|
|
931
|
+
|
|
932
|
+
def isocalendar(self):
|
|
933
|
+
"""Return a 3-tuple containing ISO year, week number, and weekday.
|
|
934
|
+
|
|
935
|
+
The first ISO week of the year is the (Mon-Sun) week
|
|
936
|
+
containing the year's first Thursday; everything else derives
|
|
937
|
+
from that.
|
|
938
|
+
|
|
939
|
+
The first week is 1; Monday is 1 ... Sunday is 7.
|
|
940
|
+
|
|
941
|
+
ISO calendar algorithm taken from
|
|
942
|
+
http://www.phys.uu.nl/~vgent/calendar/isocalendar.htm
|
|
943
|
+
"""
|
|
944
|
+
year = self.__year
|
|
945
|
+
week1monday = _isoweek1monday(year)
|
|
946
|
+
today = _ymd2ord(self.__year, self.__month, self.__day)
|
|
947
|
+
# Internally, week and day have origin 0
|
|
948
|
+
week, day = divmod(today - week1monday, 7)
|
|
949
|
+
if week < 0:
|
|
950
|
+
year -= 1
|
|
951
|
+
week1monday = _isoweek1monday(year)
|
|
952
|
+
week, day = divmod(today - week1monday, 7)
|
|
953
|
+
elif week >= 52:
|
|
954
|
+
if today >= _isoweek1monday(year+1):
|
|
955
|
+
year += 1
|
|
956
|
+
week = 0
|
|
957
|
+
return year, week+1, day+1
|
|
958
|
+
|
|
959
|
+
# Pickle support.
|
|
960
|
+
|
|
961
|
+
__safe_for_unpickling__ = True # For Python 2.2
|
|
962
|
+
|
|
963
|
+
def __getstate(self):
|
|
964
|
+
yhi, ylo = divmod(self.__year, 256)
|
|
965
|
+
return ("%c%c%c%c" % (yhi, ylo, self.__month, self.__day), )
|
|
966
|
+
|
|
967
|
+
def __setstate(self, t):
|
|
968
|
+
assert isinstance(t, tuple) and len(t) == 1, `t`
|
|
969
|
+
string = t[0]
|
|
970
|
+
assert len(string) == 4
|
|
971
|
+
yhi, ylo, self.__month, self.__day = map(ord, string)
|
|
972
|
+
self.__year = yhi * 256 + ylo
|
|
973
|
+
|
|
974
|
+
def __reduce__(self):
|
|
975
|
+
return (self.__class__, self.__getstate())
|
|
976
|
+
|
|
977
|
+
_date_class = date # so functions w/ args named "date" can get at the class
|
|
978
|
+
|
|
979
|
+
date.min = date(1, 1, 1)
|
|
980
|
+
date.max = date(9999, 12, 31)
|
|
981
|
+
date.resolution = timedelta(days=1)
|
|
982
|
+
|
|
983
|
+
class tzinfo(object):
|
|
984
|
+
"""Abstract base class for time zone info classes.
|
|
985
|
+
|
|
986
|
+
Subclasses must override the name(), utcoffset() and dst() methods.
|
|
987
|
+
"""
|
|
988
|
+
|
|
989
|
+
def tzname(self, dt):
|
|
990
|
+
"datetime -> string name of time zone."
|
|
991
|
+
raise NotImplementedError("tzinfo subclass must override tzname()")
|
|
992
|
+
|
|
993
|
+
def utcoffset(self, dt):
|
|
994
|
+
"datetime -> minutes east of UTC (negative for west of UTC)"
|
|
995
|
+
raise NotImplementedError("tzinfo subclass must override utcoffset()")
|
|
996
|
+
|
|
997
|
+
def dst(self, dt):
|
|
998
|
+
"""datetime -> DST offset in minutes east of UTC.
|
|
999
|
+
|
|
1000
|
+
Return 0 if DST not in effect. utcoffset() must include the DST
|
|
1001
|
+
offset.
|
|
1002
|
+
"""
|
|
1003
|
+
raise NotImplementedError("tzinfo subclass must override dst()")
|
|
1004
|
+
|
|
1005
|
+
def fromutc(self, dt):
|
|
1006
|
+
"datetime in UTC -> datetime in local time."
|
|
1007
|
+
|
|
1008
|
+
if not isinstance(dt, datetime):
|
|
1009
|
+
raise TypeError("fromutc() requires a datetime argument")
|
|
1010
|
+
if dt.tzinfo is not self:
|
|
1011
|
+
raise ValueError("dt.tzinfo is not self")
|
|
1012
|
+
|
|
1013
|
+
dtoff = dt.utcoffset()
|
|
1014
|
+
if dtoff is None:
|
|
1015
|
+
raise ValueError("fromutc() requires a non-None utcoffset() "
|
|
1016
|
+
"result")
|
|
1017
|
+
|
|
1018
|
+
# See the long comment block at the end of this file for an
|
|
1019
|
+
# explanation of this algorithm.
|
|
1020
|
+
dtdst = dt.dst()
|
|
1021
|
+
if dtdst is None:
|
|
1022
|
+
raise ValueError("fromutc() requires a non-None dst() result")
|
|
1023
|
+
delta = dtoff - dtdst
|
|
1024
|
+
if delta:
|
|
1025
|
+
dt += delta
|
|
1026
|
+
dtdst = dt.dst()
|
|
1027
|
+
if dtdst is None:
|
|
1028
|
+
raise ValueError("fromutc(): dt.dst gave inconsistent "
|
|
1029
|
+
"results; cannot convert")
|
|
1030
|
+
if dtdst:
|
|
1031
|
+
return dt + dtdst
|
|
1032
|
+
else:
|
|
1033
|
+
return dt
|
|
1034
|
+
|
|
1035
|
+
# Pickle support.
|
|
1036
|
+
|
|
1037
|
+
__safe_for_unpickling__ = True # For Python 2.2
|
|
1038
|
+
|
|
1039
|
+
def __reduce__(self):
|
|
1040
|
+
getinitargs = getattr(self, "__getinitargs__", None)
|
|
1041
|
+
if getinitargs:
|
|
1042
|
+
args = getinitargs()
|
|
1043
|
+
else:
|
|
1044
|
+
args = ()
|
|
1045
|
+
getstate = getattr(self, "__getstate__", None)
|
|
1046
|
+
if getstate:
|
|
1047
|
+
state = getstate()
|
|
1048
|
+
else:
|
|
1049
|
+
state = getattr(self, "__dict__", None) or None
|
|
1050
|
+
if state is None:
|
|
1051
|
+
return (self.__class__, args)
|
|
1052
|
+
else:
|
|
1053
|
+
return (self.__class__, args, state)
|
|
1054
|
+
|
|
1055
|
+
_tzinfo_class = tzinfo # so functions w/ args named "tinfo" can get at it
|
|
1056
|
+
|
|
1057
|
+
class time(object):
|
|
1058
|
+
"""Time with time zone.
|
|
1059
|
+
|
|
1060
|
+
Constructors:
|
|
1061
|
+
|
|
1062
|
+
__new__()
|
|
1063
|
+
|
|
1064
|
+
Operators:
|
|
1065
|
+
|
|
1066
|
+
__repr__, __str__
|
|
1067
|
+
__cmp__, __hash__
|
|
1068
|
+
|
|
1069
|
+
Methods:
|
|
1070
|
+
|
|
1071
|
+
strftime()
|
|
1072
|
+
isoformat()
|
|
1073
|
+
utcoffset()
|
|
1074
|
+
tzname()
|
|
1075
|
+
dst()
|
|
1076
|
+
|
|
1077
|
+
Properties (readonly):
|
|
1078
|
+
hour, minute, second, microsecond, tzinfo
|
|
1079
|
+
"""
|
|
1080
|
+
|
|
1081
|
+
def __new__(cls, hour=0, minute=0, second=0, microsecond=0, tzinfo=None):
|
|
1082
|
+
"""Constructor.
|
|
1083
|
+
|
|
1084
|
+
Arguments:
|
|
1085
|
+
|
|
1086
|
+
hour, minute (required)
|
|
1087
|
+
second, microsecond (default to zero)
|
|
1088
|
+
tzinfo (default to None)
|
|
1089
|
+
"""
|
|
1090
|
+
self = object.__new__(cls)
|
|
1091
|
+
if isinstance(hour, str):
|
|
1092
|
+
# Pickle support
|
|
1093
|
+
self.__setstate((hour, minute or None))
|
|
1094
|
+
return self
|
|
1095
|
+
_check_tzinfo_arg(tzinfo)
|
|
1096
|
+
_check_time_fields(hour, minute, second, microsecond)
|
|
1097
|
+
self.__hour = hour
|
|
1098
|
+
self.__minute = minute
|
|
1099
|
+
self.__second = second
|
|
1100
|
+
self.__microsecond = microsecond
|
|
1101
|
+
self._tzinfo = tzinfo
|
|
1102
|
+
return self
|
|
1103
|
+
|
|
1104
|
+
# Read-only field accessors
|
|
1105
|
+
hour = property(lambda self: self.__hour, doc="hour (0-23)")
|
|
1106
|
+
minute = property(lambda self: self.__minute, doc="minute (0-59)")
|
|
1107
|
+
second = property(lambda self: self.__second, doc="second (0-59)")
|
|
1108
|
+
microsecond = property(lambda self: self.__microsecond,
|
|
1109
|
+
doc="microsecond (0-999999)")
|
|
1110
|
+
tzinfo = property(lambda self: self._tzinfo, doc="timezone info object")
|
|
1111
|
+
|
|
1112
|
+
# Standard conversions, __hash__ (and helpers)
|
|
1113
|
+
|
|
1114
|
+
# Comparisons.
|
|
1115
|
+
|
|
1116
|
+
def __eq__(self, other):
|
|
1117
|
+
if isinstance(other, time):
|
|
1118
|
+
return self.__cmp(other) == 0
|
|
1119
|
+
else:
|
|
1120
|
+
return False
|
|
1121
|
+
|
|
1122
|
+
def __ne__(self, other):
|
|
1123
|
+
if isinstance(other, time):
|
|
1124
|
+
return self.__cmp(other) != 0
|
|
1125
|
+
else:
|
|
1126
|
+
return True
|
|
1127
|
+
|
|
1128
|
+
def __le__(self, other):
|
|
1129
|
+
if isinstance(other, time):
|
|
1130
|
+
return self.__cmp(other) <= 0
|
|
1131
|
+
else:
|
|
1132
|
+
_cmperror(self, other)
|
|
1133
|
+
|
|
1134
|
+
def __lt__(self, other):
|
|
1135
|
+
if isinstance(other, time):
|
|
1136
|
+
return self.__cmp(other) < 0
|
|
1137
|
+
else:
|
|
1138
|
+
_cmperror(self, other)
|
|
1139
|
+
|
|
1140
|
+
def __ge__(self, other):
|
|
1141
|
+
if isinstance(other, time):
|
|
1142
|
+
return self.__cmp(other) >= 0
|
|
1143
|
+
else:
|
|
1144
|
+
_cmperror(self, other)
|
|
1145
|
+
|
|
1146
|
+
def __gt__(self, other):
|
|
1147
|
+
if isinstance(other, time):
|
|
1148
|
+
return self.__cmp(other) > 0
|
|
1149
|
+
else:
|
|
1150
|
+
_cmperror(self, other)
|
|
1151
|
+
|
|
1152
|
+
def __cmp(self, other):
|
|
1153
|
+
assert isinstance(other, time)
|
|
1154
|
+
mytz = self._tzinfo
|
|
1155
|
+
ottz = other._tzinfo
|
|
1156
|
+
myoff = otoff = None
|
|
1157
|
+
|
|
1158
|
+
if mytz is ottz:
|
|
1159
|
+
base_compare = True
|
|
1160
|
+
else:
|
|
1161
|
+
myoff = self._utcoffset()
|
|
1162
|
+
otoff = other._utcoffset()
|
|
1163
|
+
base_compare = myoff == otoff
|
|
1164
|
+
|
|
1165
|
+
if base_compare:
|
|
1166
|
+
return cmp((self.__hour, self.__minute, self.__second,
|
|
1167
|
+
self.__microsecond),
|
|
1168
|
+
(other.__hour, other.__minute, other.__second,
|
|
1169
|
+
other.__microsecond))
|
|
1170
|
+
if myoff is None or otoff is None:
|
|
1171
|
+
# XXX Buggy in 2.2.2.
|
|
1172
|
+
raise TypeError("cannot compare naive and aware times")
|
|
1173
|
+
myhhmm = self.__hour * 60 + self.__minute - myoff
|
|
1174
|
+
othhmm = other.__hour * 60 + other.__minute - otoff
|
|
1175
|
+
return cmp((myhhmm, self.__second, self.__microsecond),
|
|
1176
|
+
(othhmm, other.__second, other.__microsecond))
|
|
1177
|
+
|
|
1178
|
+
def __hash__(self):
|
|
1179
|
+
"""Hash."""
|
|
1180
|
+
tzoff = self._utcoffset()
|
|
1181
|
+
if not tzoff: # zero or None
|
|
1182
|
+
return hash(self.__getstate()[0])
|
|
1183
|
+
h, m = divmod(self.hour * 60 + self.minute - tzoff, 60)
|
|
1184
|
+
if 0 <= h < 24:
|
|
1185
|
+
return hash(time(h, m, self.second, self.microsecond))
|
|
1186
|
+
return hash((h, m, self.second, self.microsecond))
|
|
1187
|
+
|
|
1188
|
+
# Conversion to string
|
|
1189
|
+
|
|
1190
|
+
def _tzstr(self, sep=":"):
|
|
1191
|
+
"""Return formatted timezone offset (+xx:xx) or None."""
|
|
1192
|
+
off = self._utcoffset()
|
|
1193
|
+
if off is not None:
|
|
1194
|
+
if off < 0:
|
|
1195
|
+
sign = "-"
|
|
1196
|
+
off = -off
|
|
1197
|
+
else:
|
|
1198
|
+
sign = "+"
|
|
1199
|
+
hh, mm = divmod(off, 60)
|
|
1200
|
+
assert 0 <= hh < 24
|
|
1201
|
+
off = "%s%02d%s%02d" % (sign, hh, sep, mm)
|
|
1202
|
+
return off
|
|
1203
|
+
|
|
1204
|
+
def __repr__(self):
|
|
1205
|
+
"""Convert to formal string, for repr()."""
|
|
1206
|
+
if self.__microsecond != 0:
|
|
1207
|
+
s = ", %d, %d" % (self.__second, self.__microsecond)
|
|
1208
|
+
elif self.__second != 0:
|
|
1209
|
+
s = ", %d" % self.__second
|
|
1210
|
+
else:
|
|
1211
|
+
s = ""
|
|
1212
|
+
s= "%s(%d, %d%s)" % ('datetime.' + self.__class__.__name__,
|
|
1213
|
+
self.__hour, self.__minute, s)
|
|
1214
|
+
if self._tzinfo is not None:
|
|
1215
|
+
assert s[-1:] == ")"
|
|
1216
|
+
s = s[:-1] + ", tzinfo=%r" % self._tzinfo + ")"
|
|
1217
|
+
return s
|
|
1218
|
+
|
|
1219
|
+
def isoformat(self):
|
|
1220
|
+
"""Return the time formatted according to ISO.
|
|
1221
|
+
|
|
1222
|
+
This is 'HH:MM:SS.mmmmmm+zz:zz', or 'HH:MM:SS+zz:zz' if
|
|
1223
|
+
self.microsecond == 0.
|
|
1224
|
+
"""
|
|
1225
|
+
s = _format_time(self.__hour, self.__minute, self.__second,
|
|
1226
|
+
self.__microsecond)
|
|
1227
|
+
tz = self._tzstr()
|
|
1228
|
+
if tz:
|
|
1229
|
+
s += tz
|
|
1230
|
+
return s
|
|
1231
|
+
|
|
1232
|
+
__str__ = isoformat
|
|
1233
|
+
|
|
1234
|
+
def strftime(self, fmt):
|
|
1235
|
+
"""Format using strftime(). The date part of the timestamp passed
|
|
1236
|
+
to underlying strftime should not be used.
|
|
1237
|
+
"""
|
|
1238
|
+
# The year must be >= 1900 else Python's strftime implementation
|
|
1239
|
+
# can raise a bogus exception.
|
|
1240
|
+
timetuple = (1900, 1, 1,
|
|
1241
|
+
self.__hour, self.__minute, self.__second,
|
|
1242
|
+
0, 1, -1)
|
|
1243
|
+
return _wrap_strftime(self, fmt, timetuple)
|
|
1244
|
+
|
|
1245
|
+
# Timezone functions
|
|
1246
|
+
|
|
1247
|
+
def utcoffset(self):
|
|
1248
|
+
"""Return the timezone offset in minutes east of UTC (negative west of
|
|
1249
|
+
UTC)."""
|
|
1250
|
+
offset = _call_tzinfo_method(self._tzinfo, "utcoffset", None)
|
|
1251
|
+
offset = _check_utc_offset("utcoffset", offset)
|
|
1252
|
+
if offset is not None:
|
|
1253
|
+
offset = timedelta(minutes=offset)
|
|
1254
|
+
return offset
|
|
1255
|
+
|
|
1256
|
+
# Return an integer (or None) instead of a timedelta (or None).
|
|
1257
|
+
def _utcoffset(self):
|
|
1258
|
+
offset = _call_tzinfo_method(self._tzinfo, "utcoffset", None)
|
|
1259
|
+
offset = _check_utc_offset("utcoffset", offset)
|
|
1260
|
+
return offset
|
|
1261
|
+
|
|
1262
|
+
def tzname(self):
|
|
1263
|
+
"""Return the timezone name.
|
|
1264
|
+
|
|
1265
|
+
Note that the name is 100% informational -- there's no requirement that
|
|
1266
|
+
it mean anything in particular. For example, "GMT", "UTC", "-500",
|
|
1267
|
+
"-5:00", "EDT", "US/Eastern", "America/New York" are all valid replies.
|
|
1268
|
+
"""
|
|
1269
|
+
name = _call_tzinfo_method(self._tzinfo, "tzname", None)
|
|
1270
|
+
_check_tzname(name)
|
|
1271
|
+
return name
|
|
1272
|
+
|
|
1273
|
+
def dst(self):
|
|
1274
|
+
"""Return 0 if DST is not in effect, or the DST offset (in minutes
|
|
1275
|
+
eastward) if DST is in effect.
|
|
1276
|
+
|
|
1277
|
+
This is purely informational; the DST offset has already been added to
|
|
1278
|
+
the UTC offset returned by utcoffset() if applicable, so there's no
|
|
1279
|
+
need to consult dst() unless you're interested in displaying the DST
|
|
1280
|
+
info.
|
|
1281
|
+
"""
|
|
1282
|
+
offset = _call_tzinfo_method(self._tzinfo, "dst", None)
|
|
1283
|
+
offset = _check_utc_offset("dst", offset)
|
|
1284
|
+
if offset is not None:
|
|
1285
|
+
offset = timedelta(minutes=offset)
|
|
1286
|
+
return offset
|
|
1287
|
+
|
|
1288
|
+
def replace(self, hour=None, minute=None, second=None, microsecond=None,
|
|
1289
|
+
tzinfo=True):
|
|
1290
|
+
"""Return a new time with new values for the specified fields."""
|
|
1291
|
+
if hour is None:
|
|
1292
|
+
hour = self.hour
|
|
1293
|
+
if minute is None:
|
|
1294
|
+
minute = self.minute
|
|
1295
|
+
if second is None:
|
|
1296
|
+
second = self.second
|
|
1297
|
+
if microsecond is None:
|
|
1298
|
+
microsecond = self.microsecond
|
|
1299
|
+
if tzinfo is True:
|
|
1300
|
+
tzinfo = self.tzinfo
|
|
1301
|
+
_check_time_fields(hour, minute, second, microsecond)
|
|
1302
|
+
_check_tzinfo_arg(tzinfo)
|
|
1303
|
+
return time(hour, minute, second, microsecond, tzinfo)
|
|
1304
|
+
|
|
1305
|
+
# Return an integer (or None) instead of a timedelta (or None).
|
|
1306
|
+
def _dst(self):
|
|
1307
|
+
offset = _call_tzinfo_method(self._tzinfo, "dst", None)
|
|
1308
|
+
offset = _check_utc_offset("dst", offset)
|
|
1309
|
+
return offset
|
|
1310
|
+
|
|
1311
|
+
def __nonzero__(self):
|
|
1312
|
+
if self.second or self.microsecond:
|
|
1313
|
+
return 1
|
|
1314
|
+
offset = self._utcoffset() or 0
|
|
1315
|
+
return self.hour * 60 + self.minute - offset != 0
|
|
1316
|
+
|
|
1317
|
+
# Pickle support.
|
|
1318
|
+
|
|
1319
|
+
__safe_for_unpickling__ = True # For Python 2.2
|
|
1320
|
+
|
|
1321
|
+
def __getstate(self):
|
|
1322
|
+
us2, us3 = divmod(self.__microsecond, 256)
|
|
1323
|
+
us1, us2 = divmod(us2, 256)
|
|
1324
|
+
basestate = ("%c" * 6) % (self.__hour, self.__minute, self.__second,
|
|
1325
|
+
us1, us2, us3)
|
|
1326
|
+
if self._tzinfo is None:
|
|
1327
|
+
return (basestate,)
|
|
1328
|
+
else:
|
|
1329
|
+
return (basestate, self._tzinfo)
|
|
1330
|
+
|
|
1331
|
+
def __setstate(self, state):
|
|
1332
|
+
assert isinstance(state, tuple)
|
|
1333
|
+
assert 1 <= len(state) <= 2
|
|
1334
|
+
string = state[0]
|
|
1335
|
+
assert len(string) == 6
|
|
1336
|
+
self.__hour, self.__minute, self.__second, us1, us2, us3 = \
|
|
1337
|
+
map(ord, string)
|
|
1338
|
+
self.__microsecond = (((us1 << 8) | us2) << 8) | us3
|
|
1339
|
+
if len(state) == 1:
|
|
1340
|
+
self._tzinfo = None
|
|
1341
|
+
else:
|
|
1342
|
+
self._tzinfo = state[1]
|
|
1343
|
+
|
|
1344
|
+
def __reduce__(self):
|
|
1345
|
+
return (self.__class__, self.__getstate())
|
|
1346
|
+
|
|
1347
|
+
_time_class = time # so functions w/ args named "time" can get at the class
|
|
1348
|
+
|
|
1349
|
+
time.min = time(0, 0, 0)
|
|
1350
|
+
time.max = time(23, 59, 59, 999999)
|
|
1351
|
+
time.resolution = timedelta(microseconds=1)
|
|
1352
|
+
|
|
1353
|
+
class datetime(date):
|
|
1354
|
+
|
|
1355
|
+
# XXX needs docstrings
|
|
1356
|
+
# See http://www.zope.org/Members/fdrake/DateTimeWiki/TimeZoneInfo
|
|
1357
|
+
|
|
1358
|
+
def __new__(cls, year, month=None, day=None, hour=0, minute=0, second=0,
|
|
1359
|
+
microsecond=0, tzinfo=None):
|
|
1360
|
+
if isinstance(year, str):
|
|
1361
|
+
# Pickle support
|
|
1362
|
+
self = date.__new__(cls, year[:4])
|
|
1363
|
+
self.__setstate((year, month))
|
|
1364
|
+
return self
|
|
1365
|
+
_check_tzinfo_arg(tzinfo)
|
|
1366
|
+
_check_time_fields(hour, minute, second, microsecond)
|
|
1367
|
+
self = date.__new__(cls, year, month, day)
|
|
1368
|
+
# XXX This duplicates __year, __month, __day for convenience :-(
|
|
1369
|
+
self.__year = year
|
|
1370
|
+
self.__month = month
|
|
1371
|
+
self.__day = day
|
|
1372
|
+
self.__hour = hour
|
|
1373
|
+
self.__minute = minute
|
|
1374
|
+
self.__second = second
|
|
1375
|
+
self.__microsecond = microsecond
|
|
1376
|
+
self._tzinfo = tzinfo
|
|
1377
|
+
return self
|
|
1378
|
+
|
|
1379
|
+
# Read-only field accessors
|
|
1380
|
+
hour = property(lambda self: self.__hour, doc="hour (0-23)")
|
|
1381
|
+
minute = property(lambda self: self.__minute, doc="minute (0-59)")
|
|
1382
|
+
second = property(lambda self: self.__second, doc="second (0-59)")
|
|
1383
|
+
microsecond = property(lambda self: self.__microsecond,
|
|
1384
|
+
doc="microsecond (0-999999)")
|
|
1385
|
+
tzinfo = property(lambda self: self._tzinfo, doc="timezone info object")
|
|
1386
|
+
|
|
1387
|
+
def fromtimestamp(cls, t, tz=None):
|
|
1388
|
+
"""Construct a datetime from a POSIX timestamp (like time.time()).
|
|
1389
|
+
|
|
1390
|
+
A timezone info object may be passed in as well.
|
|
1391
|
+
"""
|
|
1392
|
+
|
|
1393
|
+
_check_tzinfo_arg(tz)
|
|
1394
|
+
if tz is None:
|
|
1395
|
+
converter = _time.localtime
|
|
1396
|
+
else:
|
|
1397
|
+
converter = _time.gmtime
|
|
1398
|
+
y, m, d, hh, mm, ss, weekday, jday, dst = converter(t)
|
|
1399
|
+
us = int((t % 1.0) * 1000000)
|
|
1400
|
+
ss = min(ss, 59) # clamp out leap seconds if the platform has them
|
|
1401
|
+
result = cls(y, m, d, hh, mm, ss, us, tz)
|
|
1402
|
+
if tz is not None:
|
|
1403
|
+
result = tz.fromutc(result)
|
|
1404
|
+
return result
|
|
1405
|
+
fromtimestamp = classmethod(fromtimestamp)
|
|
1406
|
+
|
|
1407
|
+
def utcfromtimestamp(cls, t):
|
|
1408
|
+
"Construct a UTC datetime from a POSIX timestamp (like time.time())."
|
|
1409
|
+
y, m, d, hh, mm, ss, weekday, jday, dst = _time.gmtime(t)
|
|
1410
|
+
us = int((t % 1.0) * 1000000)
|
|
1411
|
+
ss = min(ss, 59) # clamp out leap seconds if the platform has them
|
|
1412
|
+
return cls(y, m, d, hh, mm, ss, us)
|
|
1413
|
+
utcfromtimestamp = classmethod(utcfromtimestamp)
|
|
1414
|
+
|
|
1415
|
+
# XXX This is supposed to do better than we *can* do by using time.time(),
|
|
1416
|
+
# XXX if the platform supports a more accurate way. The C implementation
|
|
1417
|
+
# XXX uses gettimeofday on platforms that have it, but that isn't
|
|
1418
|
+
# XXX available from Python. So now() may return different results
|
|
1419
|
+
# XXX across the implementations.
|
|
1420
|
+
def now(cls, tz=None):
|
|
1421
|
+
"Construct a datetime from time.time() and optional time zone info."
|
|
1422
|
+
t = _time.time()
|
|
1423
|
+
return cls.fromtimestamp(t, tz)
|
|
1424
|
+
now = classmethod(now)
|
|
1425
|
+
|
|
1426
|
+
def utcnow(cls):
|
|
1427
|
+
"Construct a UTC datetime from time.time()."
|
|
1428
|
+
t = _time.time()
|
|
1429
|
+
return cls.utcfromtimestamp(t)
|
|
1430
|
+
utcnow = classmethod(utcnow)
|
|
1431
|
+
|
|
1432
|
+
def combine(cls, date, time):
|
|
1433
|
+
"Construct a datetime from a given date and a given time."
|
|
1434
|
+
if not isinstance(date, _date_class):
|
|
1435
|
+
raise TypeError("date argument must be a date instance")
|
|
1436
|
+
if not isinstance(time, _time_class):
|
|
1437
|
+
raise TypeError("time argument must be a time instance")
|
|
1438
|
+
return cls(date.year, date.month, date.day,
|
|
1439
|
+
time.hour, time.minute, time.second, time.microsecond,
|
|
1440
|
+
time.tzinfo)
|
|
1441
|
+
combine = classmethod(combine)
|
|
1442
|
+
|
|
1443
|
+
def timetuple(self):
|
|
1444
|
+
"Return local time tuple compatible with time.localtime()."
|
|
1445
|
+
dst = self._dst()
|
|
1446
|
+
if dst is None:
|
|
1447
|
+
dst = -1
|
|
1448
|
+
elif dst:
|
|
1449
|
+
dst = 1
|
|
1450
|
+
return _build_struct_time(self.year, self.month, self.day,
|
|
1451
|
+
self.hour, self.minute, self.second,
|
|
1452
|
+
dst)
|
|
1453
|
+
|
|
1454
|
+
def utctimetuple(self):
|
|
1455
|
+
"Return UTC time tuple compatible with time.gmtime()."
|
|
1456
|
+
y, m, d = self.year, self.month, self.day
|
|
1457
|
+
hh, mm, ss = self.hour, self.minute, self.second
|
|
1458
|
+
offset = self._utcoffset()
|
|
1459
|
+
if offset: # neither None nor 0
|
|
1460
|
+
tm = tmxxx(y, m, d, hh, mm - offset)
|
|
1461
|
+
y, m, d = tm.year, tm.month, tm.day
|
|
1462
|
+
hh, mm = tm.hour, tm.minute
|
|
1463
|
+
return _build_struct_time(y, m, d, hh, mm, ss, 0)
|
|
1464
|
+
|
|
1465
|
+
def date(self):
|
|
1466
|
+
"Return the date part."
|
|
1467
|
+
return date(self.__year, self.__month, self.__day)
|
|
1468
|
+
|
|
1469
|
+
def time(self):
|
|
1470
|
+
"Return the time part, with tzinfo None."
|
|
1471
|
+
return time(self.hour, self.minute, self.second, self.microsecond)
|
|
1472
|
+
|
|
1473
|
+
def timetz(self):
|
|
1474
|
+
"Return the time part, with same tzinfo."
|
|
1475
|
+
return time(self.hour, self.minute, self.second, self.microsecond,
|
|
1476
|
+
self._tzinfo)
|
|
1477
|
+
|
|
1478
|
+
def replace(self, year=None, month=None, day=None, hour=None,
|
|
1479
|
+
minute=None, second=None, microsecond=None, tzinfo=True):
|
|
1480
|
+
"""Return a new datetime with new values for the specified fields."""
|
|
1481
|
+
if year is None:
|
|
1482
|
+
year = self.year
|
|
1483
|
+
if month is None:
|
|
1484
|
+
month = self.month
|
|
1485
|
+
if day is None:
|
|
1486
|
+
day = self.day
|
|
1487
|
+
if hour is None:
|
|
1488
|
+
hour = self.hour
|
|
1489
|
+
if minute is None:
|
|
1490
|
+
minute = self.minute
|
|
1491
|
+
if second is None:
|
|
1492
|
+
second = self.second
|
|
1493
|
+
if microsecond is None:
|
|
1494
|
+
microsecond = self.microsecond
|
|
1495
|
+
if tzinfo is True:
|
|
1496
|
+
tzinfo = self.tzinfo
|
|
1497
|
+
_check_date_fields(year, month, day)
|
|
1498
|
+
_check_time_fields(hour, minute, second, microsecond)
|
|
1499
|
+
_check_tzinfo_arg(tzinfo)
|
|
1500
|
+
return datetime(year, month, day, hour, minute, second,
|
|
1501
|
+
microsecond, tzinfo)
|
|
1502
|
+
|
|
1503
|
+
def astimezone(self, tz):
|
|
1504
|
+
if not isinstance(tz, tzinfo):
|
|
1505
|
+
raise TypeError("tz argument must be an instance of tzinfo")
|
|
1506
|
+
|
|
1507
|
+
mytz = self.tzinfo
|
|
1508
|
+
if mytz is None:
|
|
1509
|
+
raise ValueError("astimezone() requires an aware datetime")
|
|
1510
|
+
|
|
1511
|
+
if tz is mytz:
|
|
1512
|
+
return self
|
|
1513
|
+
|
|
1514
|
+
# Convert self to UTC, and attach the new time zone object.
|
|
1515
|
+
myoffset = self.utcoffset()
|
|
1516
|
+
if myoffset is None:
|
|
1517
|
+
raise ValuError("astimezone() requires an aware datetime")
|
|
1518
|
+
utc = (self - myoffset).replace(tzinfo=tz)
|
|
1519
|
+
|
|
1520
|
+
# Convert from UTC to tz's local time.
|
|
1521
|
+
return tz.fromutc(utc)
|
|
1522
|
+
|
|
1523
|
+
# Ways to produce a string.
|
|
1524
|
+
|
|
1525
|
+
def ctime(self):
|
|
1526
|
+
"Format a la ctime()."
|
|
1527
|
+
t = tmxxx(self.__year, self.__month, self.__day, self.__hour,
|
|
1528
|
+
self.__minute, self.__second)
|
|
1529
|
+
return t.ctime()
|
|
1530
|
+
|
|
1531
|
+
def isoformat(self, sep='T'):
|
|
1532
|
+
"""Return the time formatted according to ISO.
|
|
1533
|
+
|
|
1534
|
+
This is 'YYYY-MM-DD HH:MM:SS.mmmmmm', or 'YYYY-MM-DD HH:MM:SS' if
|
|
1535
|
+
self.microsecond == 0.
|
|
1536
|
+
|
|
1537
|
+
If self.tzinfo is not None, the UTC offset is also attached, giving
|
|
1538
|
+
'YYYY-MM-DD HH:MM:SS.mmmmmm+HH:MM' or 'YYYY-MM-DD HH:MM:SS+HH:MM'.
|
|
1539
|
+
|
|
1540
|
+
Optional argument sep specifies the separator between date and
|
|
1541
|
+
time, default 'T'.
|
|
1542
|
+
"""
|
|
1543
|
+
s = ("%04d-%02d-%02d%c" % (self.__year, self.__month, self.__day,
|
|
1544
|
+
sep) +
|
|
1545
|
+
_format_time(self.__hour, self.__minute, self.__second,
|
|
1546
|
+
self.__microsecond))
|
|
1547
|
+
off = self._utcoffset()
|
|
1548
|
+
if off is not None:
|
|
1549
|
+
if off < 0:
|
|
1550
|
+
sign = "-"
|
|
1551
|
+
off = -off
|
|
1552
|
+
else:
|
|
1553
|
+
sign = "+"
|
|
1554
|
+
hh, mm = divmod(off, 60)
|
|
1555
|
+
s += "%s%02d:%02d" % (sign, hh, mm)
|
|
1556
|
+
return s
|
|
1557
|
+
|
|
1558
|
+
def __repr__(self):
|
|
1559
|
+
"Convert to formal string, for repr()."
|
|
1560
|
+
L = [self.__year, self.__month, self.__day, # These are never zero
|
|
1561
|
+
self.__hour, self.__minute, self.__second, self.__microsecond]
|
|
1562
|
+
while L[-1] == 0:
|
|
1563
|
+
del L[-1]
|
|
1564
|
+
s = ", ".join(map(str, L))
|
|
1565
|
+
s = "%s(%s)" % ('datetime.' + self.__class__.__name__, s)
|
|
1566
|
+
if self._tzinfo is not None:
|
|
1567
|
+
assert s[-1:] == ")"
|
|
1568
|
+
s = s[:-1] + ", tzinfo=%r" % self._tzinfo + ")"
|
|
1569
|
+
return s
|
|
1570
|
+
|
|
1571
|
+
def __str__(self):
|
|
1572
|
+
"Convert to string, for str()."
|
|
1573
|
+
return self.isoformat(sep=' ')
|
|
1574
|
+
|
|
1575
|
+
def utcoffset(self):
|
|
1576
|
+
"""Return the timezone offset in minutes east of UTC (negative west of
|
|
1577
|
+
UTC)."""
|
|
1578
|
+
offset = _call_tzinfo_method(self._tzinfo, "utcoffset", self)
|
|
1579
|
+
offset = _check_utc_offset("utcoffset", offset)
|
|
1580
|
+
if offset is not None:
|
|
1581
|
+
offset = timedelta(minutes=offset)
|
|
1582
|
+
return offset
|
|
1583
|
+
|
|
1584
|
+
# Return an integer (or None) instead of a timedelta (or None).
|
|
1585
|
+
def _utcoffset(self):
|
|
1586
|
+
offset = _call_tzinfo_method(self._tzinfo, "utcoffset", self)
|
|
1587
|
+
offset = _check_utc_offset("utcoffset", offset)
|
|
1588
|
+
return offset
|
|
1589
|
+
|
|
1590
|
+
def tzname(self):
|
|
1591
|
+
"""Return the timezone name.
|
|
1592
|
+
|
|
1593
|
+
Note that the name is 100% informational -- there's no requirement that
|
|
1594
|
+
it mean anything in particular. For example, "GMT", "UTC", "-500",
|
|
1595
|
+
"-5:00", "EDT", "US/Eastern", "America/New York" are all valid replies.
|
|
1596
|
+
"""
|
|
1597
|
+
name = _call_tzinfo_method(self._tzinfo, "tzname", self)
|
|
1598
|
+
_check_tzname(name)
|
|
1599
|
+
return name
|
|
1600
|
+
|
|
1601
|
+
def dst(self):
|
|
1602
|
+
"""Return 0 if DST is not in effect, or the DST offset (in minutes
|
|
1603
|
+
eastward) if DST is in effect.
|
|
1604
|
+
|
|
1605
|
+
This is purely informational; the DST offset has already been added to
|
|
1606
|
+
the UTC offset returned by utcoffset() if applicable, so there's no
|
|
1607
|
+
need to consult dst() unless you're interested in displaying the DST
|
|
1608
|
+
info.
|
|
1609
|
+
"""
|
|
1610
|
+
offset = _call_tzinfo_method(self._tzinfo, "dst", self)
|
|
1611
|
+
offset = _check_utc_offset("dst", offset)
|
|
1612
|
+
if offset is not None:
|
|
1613
|
+
offset = timedelta(minutes=offset)
|
|
1614
|
+
return offset
|
|
1615
|
+
|
|
1616
|
+
# Return an integer (or None) instead of a timedelta (or None).1573
|
|
1617
|
+
def _dst(self):
|
|
1618
|
+
offset = _call_tzinfo_method(self._tzinfo, "dst", self)
|
|
1619
|
+
offset = _check_utc_offset("dst", offset)
|
|
1620
|
+
return offset
|
|
1621
|
+
|
|
1622
|
+
# Comparisons.
|
|
1623
|
+
|
|
1624
|
+
def __eq__(self, other):
|
|
1625
|
+
if isinstance(other, datetime):
|
|
1626
|
+
return self.__cmp(other) == 0
|
|
1627
|
+
elif hasattr(other, "timetuple"):
|
|
1628
|
+
return NotImplemented
|
|
1629
|
+
else:
|
|
1630
|
+
return False
|
|
1631
|
+
|
|
1632
|
+
def __ne__(self, other):
|
|
1633
|
+
if isinstance(other, datetime):
|
|
1634
|
+
return self.__cmp(other) != 0
|
|
1635
|
+
elif hasattr(other, "timetuple"):
|
|
1636
|
+
return NotImplemented
|
|
1637
|
+
else:
|
|
1638
|
+
return True
|
|
1639
|
+
|
|
1640
|
+
def __le__(self, other):
|
|
1641
|
+
if isinstance(other, datetime):
|
|
1642
|
+
return self.__cmp(other) <= 0
|
|
1643
|
+
elif hasattr(other, "timetuple"):
|
|
1644
|
+
return NotImplemented
|
|
1645
|
+
else:
|
|
1646
|
+
_cmperror(self, other)
|
|
1647
|
+
|
|
1648
|
+
def __lt__(self, other):
|
|
1649
|
+
if isinstance(other, datetime):
|
|
1650
|
+
return self.__cmp(other) < 0
|
|
1651
|
+
elif hasattr(other, "timetuple"):
|
|
1652
|
+
return NotImplemented
|
|
1653
|
+
else:
|
|
1654
|
+
_cmperror(self, other)
|
|
1655
|
+
|
|
1656
|
+
def __ge__(self, other):
|
|
1657
|
+
if isinstance(other, datetime):
|
|
1658
|
+
return self.__cmp(other) >= 0
|
|
1659
|
+
elif hasattr(other, "timetuple"):
|
|
1660
|
+
return NotImplemented
|
|
1661
|
+
else:
|
|
1662
|
+
_cmperror(self, other)
|
|
1663
|
+
|
|
1664
|
+
def __gt__(self, other):
|
|
1665
|
+
if isinstance(other, datetime):
|
|
1666
|
+
return self.__cmp(other) > 0
|
|
1667
|
+
elif hasattr(other, "timetuple"):
|
|
1668
|
+
return NotImplemented
|
|
1669
|
+
else:
|
|
1670
|
+
_cmperror(self, other)
|
|
1671
|
+
|
|
1672
|
+
def __cmp(self, other):
|
|
1673
|
+
assert isinstance(other, datetime)
|
|
1674
|
+
mytz = self._tzinfo
|
|
1675
|
+
ottz = other._tzinfo
|
|
1676
|
+
myoff = otoff = None
|
|
1677
|
+
|
|
1678
|
+
if mytz is ottz:
|
|
1679
|
+
base_compare = True
|
|
1680
|
+
else:
|
|
1681
|
+
if mytz is not None:
|
|
1682
|
+
myoff = self._utcoffset()
|
|
1683
|
+
if ottz is not None:
|
|
1684
|
+
otoff = other._utcoffset()
|
|
1685
|
+
base_compare = myoff == otoff
|
|
1686
|
+
|
|
1687
|
+
if base_compare:
|
|
1688
|
+
return cmp((self.__year, self.__month, self.__day,
|
|
1689
|
+
self.__hour, self.__minute, self.__second,
|
|
1690
|
+
self.__microsecond),
|
|
1691
|
+
(other.__year, other.__month, other.__day,
|
|
1692
|
+
other.__hour, other.__minute, other.__second,
|
|
1693
|
+
other.__microsecond))
|
|
1694
|
+
if myoff is None or otoff is None:
|
|
1695
|
+
# XXX Buggy in 2.2.2.
|
|
1696
|
+
raise TypeError("cannot compare naive and aware datetimes")
|
|
1697
|
+
# XXX What follows could be done more efficiently...
|
|
1698
|
+
diff = self - other # this will take offsets into account
|
|
1699
|
+
if diff.days < 0:
|
|
1700
|
+
return -1
|
|
1701
|
+
return diff and 1 or 0
|
|
1702
|
+
|
|
1703
|
+
def __add__(self, other):
|
|
1704
|
+
"Add a datetime and a timedelta."
|
|
1705
|
+
if not isinstance(other, timedelta):
|
|
1706
|
+
return NotImplemented
|
|
1707
|
+
t = tmxxx(self.__year,
|
|
1708
|
+
self.__month,
|
|
1709
|
+
self.__day + other.days,
|
|
1710
|
+
self.__hour,
|
|
1711
|
+
self.__minute,
|
|
1712
|
+
self.__second + other.seconds,
|
|
1713
|
+
self.__microsecond + other.microseconds)
|
|
1714
|
+
self._checkOverflow(t.year)
|
|
1715
|
+
result = self.__class__(t.year, t.month, t.day,
|
|
1716
|
+
t.hour, t.minute, t.second,
|
|
1717
|
+
t.microsecond, tzinfo=self._tzinfo)
|
|
1718
|
+
return result
|
|
1719
|
+
|
|
1720
|
+
__radd__ = __add__
|
|
1721
|
+
|
|
1722
|
+
def __sub__(self, other):
|
|
1723
|
+
"Subtract two datetimes, or a datetime and a timedelta."
|
|
1724
|
+
if not isinstance(other, datetime):
|
|
1725
|
+
if isinstance(other, timedelta):
|
|
1726
|
+
return self + -other
|
|
1727
|
+
return NotImplemented
|
|
1728
|
+
|
|
1729
|
+
days1 = self.toordinal()
|
|
1730
|
+
days2 = other.toordinal()
|
|
1731
|
+
secs1 = self.__second + self.__minute * 60 + self.__hour * 3600
|
|
1732
|
+
secs2 = other.__second + other.__minute * 60 + other.__hour * 3600
|
|
1733
|
+
base = timedelta(days1 - days2,
|
|
1734
|
+
secs1 - secs2,
|
|
1735
|
+
self.__microsecond - other.__microsecond)
|
|
1736
|
+
if self._tzinfo is other._tzinfo:
|
|
1737
|
+
return base
|
|
1738
|
+
myoff = self._utcoffset()
|
|
1739
|
+
otoff = other._utcoffset()
|
|
1740
|
+
if myoff == otoff:
|
|
1741
|
+
return base
|
|
1742
|
+
if myoff is None or otoff is None:
|
|
1743
|
+
raise TypeError, "cannot mix naive and timezone-aware time"
|
|
1744
|
+
return base + timedelta(minutes = otoff-myoff)
|
|
1745
|
+
|
|
1746
|
+
def __hash__(self):
|
|
1747
|
+
tzoff = self._utcoffset()
|
|
1748
|
+
if tzoff is None:
|
|
1749
|
+
return hash(self.__getstate()[0])
|
|
1750
|
+
days = _ymd2ord(self.year, self.month, self.day)
|
|
1751
|
+
seconds = self.hour * 3600 + (self.minute - tzoff) * 60 + self.second
|
|
1752
|
+
return hash(timedelta(days, seconds, self.microsecond))
|
|
1753
|
+
|
|
1754
|
+
# Pickle support.
|
|
1755
|
+
|
|
1756
|
+
__safe_for_unpickling__ = True # For Python 2.2
|
|
1757
|
+
|
|
1758
|
+
def __getstate(self):
|
|
1759
|
+
yhi, ylo = divmod(self.__year, 256)
|
|
1760
|
+
us2, us3 = divmod(self.__microsecond, 256)
|
|
1761
|
+
us1, us2 = divmod(us2, 256)
|
|
1762
|
+
basestate = ("%c" * 10) % (yhi, ylo, self.__month, self.__day,
|
|
1763
|
+
self.__hour, self.__minute, self.__second,
|
|
1764
|
+
us1, us2, us3)
|
|
1765
|
+
if self._tzinfo is None:
|
|
1766
|
+
return (basestate,)
|
|
1767
|
+
else:
|
|
1768
|
+
return (basestate, self._tzinfo)
|
|
1769
|
+
|
|
1770
|
+
def __setstate(self, state):
|
|
1771
|
+
assert isinstance(state, tuple)
|
|
1772
|
+
assert 1 <= len(state) <= 2
|
|
1773
|
+
string = state[0]
|
|
1774
|
+
assert len(string) == 10
|
|
1775
|
+
(yhi, ylo, self.__month, self.__day, self.__hour,
|
|
1776
|
+
self.__minute, self.__second, us1, us2, us3) = map(ord, string)
|
|
1777
|
+
self.__year = yhi * 256 + ylo
|
|
1778
|
+
self.__microsecond = (((us1 << 8) | us2) << 8) | us3
|
|
1779
|
+
if len(state) == 1:
|
|
1780
|
+
self._tzinfo = None
|
|
1781
|
+
else:
|
|
1782
|
+
self._tzinfo = state[1]
|
|
1783
|
+
|
|
1784
|
+
def __reduce__(self):
|
|
1785
|
+
return (self.__class__, self.__getstate())
|
|
1786
|
+
|
|
1787
|
+
|
|
1788
|
+
datetime.min = datetime(1, 1, 1)
|
|
1789
|
+
datetime.max = datetime(9999, 12, 31, 23, 59, 59, 999999)
|
|
1790
|
+
datetime.resolution = timedelta(microseconds=1)
|
|
1791
|
+
|
|
1792
|
+
|
|
1793
|
+
def _isoweek1monday(year):
|
|
1794
|
+
# Helper to calculate the day number of the Monday starting week 1
|
|
1795
|
+
# XXX This could be done more efficiently
|
|
1796
|
+
THURSDAY = 3
|
|
1797
|
+
firstday = _ymd2ord(year, 1, 1)
|
|
1798
|
+
firstweekday = (firstday + 6) % 7 # See weekday() above
|
|
1799
|
+
week1monday = firstday - firstweekday
|
|
1800
|
+
if firstweekday > THURSDAY:
|
|
1801
|
+
week1monday += 7
|
|
1802
|
+
return week1monday
|
|
1803
|
+
|
|
1804
|
+
"""
|
|
1805
|
+
Some time zone algebra. For a datetime x, let
|
|
1806
|
+
x.n = x stripped of its timezone -- its naive time.
|
|
1807
|
+
x.o = x.utcoffset(), and assuming that doesn't raise an exception or
|
|
1808
|
+
return None
|
|
1809
|
+
x.d = x.dst(), and assuming that doesn't raise an exception or
|
|
1810
|
+
return None
|
|
1811
|
+
x.s = x's standard offset, x.o - x.d
|
|
1812
|
+
|
|
1813
|
+
Now some derived rules, where k is a duration (timedelta).
|
|
1814
|
+
|
|
1815
|
+
1. x.o = x.s + x.d
|
|
1816
|
+
This follows from the definition of x.s.
|
|
1817
|
+
|
|
1818
|
+
2. If x and y have the same tzinfo member, x.s = y.s.
|
|
1819
|
+
This is actually a requirement, an assumption we need to make about
|
|
1820
|
+
sane tzinfo classes.
|
|
1821
|
+
|
|
1822
|
+
3. The naive UTC time corresponding to x is x.n - x.o.
|
|
1823
|
+
This is again a requirement for a sane tzinfo class.
|
|
1824
|
+
|
|
1825
|
+
4. (x+k).s = x.s
|
|
1826
|
+
This follows from #2, and that datimetimetz+timedelta preserves tzinfo.
|
|
1827
|
+
|
|
1828
|
+
5. (x+k).n = x.n + k
|
|
1829
|
+
Again follows from how arithmetic is defined.
|
|
1830
|
+
|
|
1831
|
+
Now we can explain tz.fromutc(x). Let's assume it's an interesting case
|
|
1832
|
+
(meaning that the various tzinfo methods exist, and don't blow up or return
|
|
1833
|
+
None when called).
|
|
1834
|
+
|
|
1835
|
+
The function wants to return a datetime y with timezone tz, equivalent to x.
|
|
1836
|
+
x is already in UTC.
|
|
1837
|
+
|
|
1838
|
+
By #3, we want
|
|
1839
|
+
|
|
1840
|
+
y.n - y.o = x.n [1]
|
|
1841
|
+
|
|
1842
|
+
The algorithm starts by attaching tz to x.n, and calling that y. So
|
|
1843
|
+
x.n = y.n at the start. Then it wants to add a duration k to y, so that [1]
|
|
1844
|
+
becomes true; in effect, we want to solve [2] for k:
|
|
1845
|
+
|
|
1846
|
+
(y+k).n - (y+k).o = x.n [2]
|
|
1847
|
+
|
|
1848
|
+
By #1, this is the same as
|
|
1849
|
+
|
|
1850
|
+
(y+k).n - ((y+k).s + (y+k).d) = x.n [3]
|
|
1851
|
+
|
|
1852
|
+
By #5, (y+k).n = y.n + k, which equals x.n + k because x.n=y.n at the start.
|
|
1853
|
+
Substituting that into [3],
|
|
1854
|
+
|
|
1855
|
+
x.n + k - (y+k).s - (y+k).d = x.n; the x.n terms cancel, leaving
|
|
1856
|
+
k - (y+k).s - (y+k).d = 0; rearranging,
|
|
1857
|
+
k = (y+k).s - (y+k).d; by #4, (y+k).s == y.s, so
|
|
1858
|
+
k = y.s - (y+k).d
|
|
1859
|
+
|
|
1860
|
+
On the RHS, (y+k).d can't be computed directly, but y.s can be, and we
|
|
1861
|
+
approximate k by ignoring the (y+k).d term at first. Note that k can't be
|
|
1862
|
+
very large, since all offset-returning methods return a duration of magnitude
|
|
1863
|
+
less than 24 hours. For that reason, if y is firmly in std time, (y+k).d must
|
|
1864
|
+
be 0, so ignoring it has no consequence then.
|
|
1865
|
+
|
|
1866
|
+
In any case, the new value is
|
|
1867
|
+
|
|
1868
|
+
z = y + y.s [4]
|
|
1869
|
+
|
|
1870
|
+
It's helpful to step back at look at [4] from a higher level: it's simply
|
|
1871
|
+
mapping from UTC to tz's standard time.
|
|
1872
|
+
|
|
1873
|
+
At this point, if
|
|
1874
|
+
|
|
1875
|
+
z.n - z.o = x.n [5]
|
|
1876
|
+
|
|
1877
|
+
we have an equivalent time, and are almost done. The insecurity here is
|
|
1878
|
+
at the start of daylight time. Picture US Eastern for concreteness. The wall
|
|
1879
|
+
time jumps from 1:59 to 3:00, and wall hours of the form 2:MM don't make good
|
|
1880
|
+
sense then. The docs ask that an Eastern tzinfo class consider such a time to
|
|
1881
|
+
be EDT (because it's "after 2"), which is a redundant spelling of 1:MM EST
|
|
1882
|
+
on the day DST starts. We want to return the 1:MM EST spelling because that's
|
|
1883
|
+
the only spelling that makes sense on the local wall clock.
|
|
1884
|
+
|
|
1885
|
+
In fact, if [5] holds at this point, we do have the standard-time spelling,
|
|
1886
|
+
but that takes a bit of proof. We first prove a stronger result. What's the
|
|
1887
|
+
difference between the LHS and RHS of [5]? Let
|
|
1888
|
+
|
|
1889
|
+
diff = x.n - (z.n - z.o) [6]
|
|
1890
|
+
|
|
1891
|
+
Now
|
|
1892
|
+
z.n = by [4]
|
|
1893
|
+
(y + y.s).n = by #5
|
|
1894
|
+
y.n + y.s = since y.n = x.n
|
|
1895
|
+
x.n + y.s = since z and y are have the same tzinfo member,
|
|
1896
|
+
y.s = z.s by #2
|
|
1897
|
+
x.n + z.s
|
|
1898
|
+
|
|
1899
|
+
Plugging that back into [6] gives
|
|
1900
|
+
|
|
1901
|
+
diff =
|
|
1902
|
+
x.n - ((x.n + z.s) - z.o) = expanding
|
|
1903
|
+
x.n - x.n - z.s + z.o = cancelling
|
|
1904
|
+
- z.s + z.o = by #2
|
|
1905
|
+
z.d
|
|
1906
|
+
|
|
1907
|
+
So diff = z.d.
|
|
1908
|
+
|
|
1909
|
+
If [5] is true now, diff = 0, so z.d = 0 too, and we have the standard-time
|
|
1910
|
+
spelling we wanted in the endcase described above. We're done. Contrarily,
|
|
1911
|
+
if z.d = 0, then we have a UTC equivalent, and are also done.
|
|
1912
|
+
|
|
1913
|
+
If [5] is not true now, diff = z.d != 0, and z.d is the offset we need to
|
|
1914
|
+
add to z (in effect, z is in tz's standard time, and we need to shift the
|
|
1915
|
+
local clock into tz's daylight time).
|
|
1916
|
+
|
|
1917
|
+
Let
|
|
1918
|
+
|
|
1919
|
+
z' = z + z.d = z + diff [7]
|
|
1920
|
+
|
|
1921
|
+
and we can again ask whether
|
|
1922
|
+
|
|
1923
|
+
z'.n - z'.o = x.n [8]
|
|
1924
|
+
|
|
1925
|
+
If so, we're done. If not, the tzinfo class is insane, according to the
|
|
1926
|
+
assumptions we've made. This also requires a bit of proof. As before, let's
|
|
1927
|
+
compute the difference between the LHS and RHS of [8] (and skipping some of
|
|
1928
|
+
the justifications for the kinds of substitutions we've done several times
|
|
1929
|
+
already):
|
|
1930
|
+
|
|
1931
|
+
diff' = x.n - (z'.n - z'.o) = replacing z'.n via [7]
|
|
1932
|
+
x.n - (z.n + diff - z'.o) = replacing diff via [6]
|
|
1933
|
+
x.n - (z.n + x.n - (z.n - z.o) - z'.o) =
|
|
1934
|
+
x.n - z.n - x.n + z.n - z.o + z'.o = cancel x.n
|
|
1935
|
+
- z.n + z.n - z.o + z'.o = cancel z.n
|
|
1936
|
+
- z.o + z'.o = #1 twice
|
|
1937
|
+
-z.s - z.d + z'.s + z'.d = z and z' have same tzinfo
|
|
1938
|
+
z'.d - z.d
|
|
1939
|
+
|
|
1940
|
+
So z' is UTC-equivalent to x iff z'.d = z.d at this point. If they are equal,
|
|
1941
|
+
we've found the UTC-equivalent so are done. In fact, we stop with [7] and
|
|
1942
|
+
return z', not bothering to compute z'.d.
|
|
1943
|
+
|
|
1944
|
+
How could z.d and z'd differ? z' = z + z.d [7], so merely moving z' by
|
|
1945
|
+
a dst() offset, and starting *from* a time already in DST (we know z.d != 0),
|
|
1946
|
+
would have to change the result dst() returns: we start in DST, and moving
|
|
1947
|
+
a little further into it takes us out of DST.
|
|
1948
|
+
|
|
1949
|
+
There isn't a sane case where this can happen. The closest it gets is at
|
|
1950
|
+
the end of DST, where there's an hour in UTC with no spelling in a hybrid
|
|
1951
|
+
tzinfo class. In US Eastern, that's 5:MM UTC = 0:MM EST = 1:MM EDT. During
|
|
1952
|
+
that hour, on an Eastern clock 1:MM is taken as being in standard time (6:MM
|
|
1953
|
+
UTC) because the docs insist on that, but 0:MM is taken as being in daylight
|
|
1954
|
+
time (4:MM UTC). There is no local time mapping to 5:MM UTC. The local
|
|
1955
|
+
clock jumps from 1:59 back to 1:00 again, and repeats the 1:MM hour in
|
|
1956
|
+
standard time. Since that's what the local clock *does*, we want to map both
|
|
1957
|
+
UTC hours 5:MM and 6:MM to 1:MM Eastern. The result is ambiguous
|
|
1958
|
+
in local time, but so it goes -- it's the way the local clock works.
|
|
1959
|
+
|
|
1960
|
+
When x = 5:MM UTC is the input to this algorithm, x.o=0, y.o=-5 and y.d=0,
|
|
1961
|
+
so z=0:MM. z.d=60 (minutes) then, so [5] doesn't hold and we keep going.
|
|
1962
|
+
z' = z + z.d = 1:MM then, and z'.d=0, and z'.d - z.d = -60 != 0 so [8]
|
|
1963
|
+
(correctly) concludes that z' is not UTC-equivalent to x.
|
|
1964
|
+
|
|
1965
|
+
Because we know z.d said z was in daylight time (else [5] would have held and
|
|
1966
|
+
we would have stopped then), and we know z.d != z'.d (else [8] would have held
|
|
1967
|
+
and we we have stopped then), and there are only 2 possible values dst() can
|
|
1968
|
+
return in Eastern, it follows that z'.d must be 0 (which it is in the example,
|
|
1969
|
+
but the reasoning doesn't depend on the example -- it depends on there being
|
|
1970
|
+
two possible dst() outcomes, one zero and the other non-zero). Therefore
|
|
1971
|
+
z' must be in standard time, and is the spelling we want in this case.
|
|
1972
|
+
|
|
1973
|
+
Note again that z' is not UTC-equivalent as far as the hybrid tzinfo class is
|
|
1974
|
+
concerned (because it takes z' as being in standard time rather than the
|
|
1975
|
+
daylight time we intend here), but returning it gives the real-life "local
|
|
1976
|
+
clock repeats an hour" behavior when mapping the "unspellable" UTC hour into
|
|
1977
|
+
tz.
|
|
1978
|
+
|
|
1979
|
+
When the input is 6:MM, z=1:MM and z.d=0, and we stop at once, again with
|
|
1980
|
+
the 1:MM standard time spelling we want.
|
|
1981
|
+
|
|
1982
|
+
So how can this break? One of the assumptions must be violated. Two
|
|
1983
|
+
possibilities:
|
|
1984
|
+
|
|
1985
|
+
1) [2] effectively says that y.s is invariant across all y belong to a given
|
|
1986
|
+
time zone. This isn't true if, for political reasons or continental drift,
|
|
1987
|
+
a region decides to change its base offset from UTC.
|
|
1988
|
+
|
|
1989
|
+
2) There may be versions of "double daylight" time where the tail end of
|
|
1990
|
+
the analysis gives up a step too early. I haven't thought about that
|
|
1991
|
+
enough to say.
|
|
1992
|
+
|
|
1993
|
+
In any case, it's clear that the default fromutc() is strong enough to handle
|
|
1994
|
+
"almost all" time zones: so long as the standard offset is invariant, it
|
|
1995
|
+
doesn't matter if daylight time transition points change from year to year, or
|
|
1996
|
+
if daylight time is skipped in some years; it doesn't matter how large or
|
|
1997
|
+
small dst() may get within its bounds; and it doesn't even matter if some
|
|
1998
|
+
perverse time zone returns a negative dst()). So a breaking case must be
|
|
1999
|
+
pretty bizarre, and a tzinfo subclass can override fromutc() if it is.
|
|
2000
|
+
"""
|
|
2001
|
+
|
|
2002
|
+
def _test():
|
|
2003
|
+
import test_datetime
|
|
2004
|
+
test_datetime.test_main()
|
|
2005
|
+
|
|
2006
|
+
if __name__ == "__main__":
|
|
2007
|
+
_test()
|