mirror of
https://github.com/kennethreitz/maya.git
synced 2026-06-05 23:00:18 +00:00
Compare commits
63 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| b896237cca | |||
| 4e58e6455e | |||
| 42cc61e7a8 | |||
| 9abd618083 | |||
| 2c2a8d03c8 | |||
| bdf2bb332b | |||
| 6522525d7c | |||
| 3a83f10988 | |||
| 05eb0d0051 | |||
| 61eabc54e0 | |||
| 6bb380e7c5 | |||
| cc698817b4 | |||
| 9964e9305e | |||
| d87236a30d | |||
| d44a1dd2f6 | |||
| ed5d72b34c | |||
| 9c1e94f956 | |||
| 6755968f69 | |||
| 3760af2c41 | |||
| df09625e74 | |||
| 2d848bd62a | |||
| a99cddf76f | |||
| 1b432d6626 | |||
| f09d6eec63 | |||
| 62a6283200 | |||
| 9ef43a29d9 | |||
| a2bff42439 | |||
| 5525beda31 | |||
| eeb07d46db | |||
| 4056d1a9aa | |||
| 7a750a1cff | |||
| bc06315abd | |||
| 7cc767781a | |||
| 8468dd2ead | |||
| 046f005ca7 | |||
| cd0b2300d7 | |||
| d3ddb39d9d | |||
| 3c8fe4478c | |||
| a0983132bb | |||
| 9612d70707 | |||
| 363fae1aaf | |||
| be2cd96132 | |||
| 771a2b6ce2 | |||
| 8e644f655a | |||
| 6903f6eb63 | |||
| ca076ff625 | |||
| e0e33cc29f | |||
| bd34915f96 | |||
| 16690cfceb | |||
| 97af369f05 | |||
| 367dac4e62 | |||
| 59ec275ef6 | |||
| 76f99bc781 | |||
| bf56321545 | |||
| ee602ea56b | |||
| df3bdf231d | |||
| 1a58d4f710 | |||
| d0d5a8f75d | |||
| 00a0ceb3c8 | |||
| ee0fe3b810 | |||
| 0e0815c45a | |||
| e9592a3146 | |||
| b05ca8707c |
@@ -24,6 +24,7 @@ wheels/
|
|||||||
*.egg-info/
|
*.egg-info/
|
||||||
.installed.cfg
|
.installed.cfg
|
||||||
*.egg
|
*.egg
|
||||||
|
Pipfile.lock
|
||||||
|
|
||||||
# PyInstaller
|
# PyInstaller
|
||||||
# Usually these files are written by a python script from a template
|
# Usually these files are written by a python script from a template
|
||||||
|
|||||||
+4
-1
@@ -9,7 +9,10 @@ matrix:
|
|||||||
- python: "3.7-dev"
|
- python: "3.7-dev"
|
||||||
|
|
||||||
# command to install dependencies
|
# command to install dependencies
|
||||||
install: pip install pipenv; pipenv lock; pipenv install --dev
|
install:
|
||||||
|
- pip install pipenv
|
||||||
|
- pipenv install '-e .' --skip-lock --ignore-pipfile
|
||||||
|
- pipenv install --dev --skip-lock
|
||||||
|
|
||||||
# command to run tests
|
# command to run tests
|
||||||
script: pipenv run pytest tests/
|
script: pipenv run pytest tests/
|
||||||
|
|||||||
@@ -24,3 +24,5 @@ In chronological order:
|
|||||||
- Evan Mattiza <emattiza@gmail.com> (`@emattiza <https://github.com/emattiza>`_)
|
- Evan Mattiza <emattiza@gmail.com> (`@emattiza <https://github.com/emattiza>`_)
|
||||||
- Dima Spivak <dima@spivak.ch> (`@dimaspivak <https://github.com/dimaspivak>`_)
|
- Dima Spivak <dima@spivak.ch> (`@dimaspivak <https://github.com/dimaspivak>`_)
|
||||||
- Tom Barron <tusculum@gmail.com> (`@dtbarron <https://github.com/tbarron>`_)
|
- Tom Barron <tusculum@gmail.com> (`@dtbarron <https://github.com/tbarron>`_)
|
||||||
|
- Alex Ward <alxwrd@gmail.com> (`@alxwrd <https://github.com/alxwrd>`_)
|
||||||
|
- Frank Tobia <frank.tobia@gmail.com> (`@ftobia <https://github.com/ftobia>`_)
|
||||||
|
|||||||
@@ -1,15 +1,9 @@
|
|||||||
[dev-packages]
|
[[source]]
|
||||||
|
name = "pypi"
|
||||||
|
url = "https://pypi.org/simple"
|
||||||
|
verify_ssl = true
|
||||||
|
|
||||||
|
[dev-packages]
|
||||||
|
freezegun = "*"
|
||||||
pytest = "*"
|
pytest = "*"
|
||||||
sphinx = "*"
|
sphinx = "*"
|
||||||
|
|
||||||
|
|
||||||
[packages]
|
|
||||||
|
|
||||||
humanize = "*"
|
|
||||||
pytz = "*"
|
|
||||||
dateparser = "*"
|
|
||||||
"ruamel.yaml" = "*"
|
|
||||||
tzlocal = "*"
|
|
||||||
pendulum = ">=1.0"
|
|
||||||
snaptime = "*"
|
|
||||||
|
|||||||
Generated
-317
@@ -1,317 +0,0 @@
|
|||||||
{
|
|
||||||
"_meta": {
|
|
||||||
"hash": {
|
|
||||||
"sha256": "3abd33d2f9beea083faca673fa3864252623b284fa24f9a8b939aed12428318c"
|
|
||||||
},
|
|
||||||
"pipfile-spec": 6,
|
|
||||||
"requires": {},
|
|
||||||
"sources": [
|
|
||||||
{
|
|
||||||
"name": "pypi",
|
|
||||||
"url": "https://pypi.python.org/simple",
|
|
||||||
"verify_ssl": true
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"default": {
|
|
||||||
"dateparser": {
|
|
||||||
"hashes": [
|
|
||||||
"sha256:940828183c937bcec530753211b70f673c0a9aab831e43273489b310538dff86",
|
|
||||||
"sha256:b452ef8b36cd78ae86a50721794bc674aa3994e19b570f7ba92810f4e0a2ae03"
|
|
||||||
],
|
|
||||||
"index": "pypi",
|
|
||||||
"version": "==0.7.0"
|
|
||||||
},
|
|
||||||
"humanize": {
|
|
||||||
"hashes": [
|
|
||||||
"sha256:a43f57115831ac7c70de098e6ac46ac13be00d69abbf60bdcac251344785bb19"
|
|
||||||
],
|
|
||||||
"index": "pypi",
|
|
||||||
"version": "==0.5.1"
|
|
||||||
},
|
|
||||||
"pendulum": {
|
|
||||||
"hashes": [
|
|
||||||
"sha256:0c14388546db6605a860b8b7112cb69d0b11c9ce5e072210504544e0d4575799",
|
|
||||||
"sha256:39a255776528afe11ea0d57814f9bf3729c1e0b99063af2e5c6cfd750c3e1f7f",
|
|
||||||
"sha256:3c85e8cbc91f45e1cc916cc9180b34153cd6aaaaacfb51a48b3156318314fa82",
|
|
||||||
"sha256:8199206c479b13947dcac63c025575d035331bb3819d1783dc1d568a11962906",
|
|
||||||
"sha256:8798aeca58b3dd7ffdc5a4993c9eaafedc4048165429e8f499ddd62c73bf3964",
|
|
||||||
"sha256:881efe37328de0785c0731d462e1485a45712f2cd5cb55907d6c15458460ebeb",
|
|
||||||
"sha256:bcca072f82e84b419efec1320cd3ee5c230d263f3a601b146651ed4db77d89f0",
|
|
||||||
"sha256:ff0c5fa3af4a471a218408c448b804ac6bccb105127727474f4e83c0e4072e97"
|
|
||||||
],
|
|
||||||
"index": "pypi",
|
|
||||||
"version": "==1.4.2"
|
|
||||||
},
|
|
||||||
"python-dateutil": {
|
|
||||||
"hashes": [
|
|
||||||
"sha256:07009062406cffd554a9b4135cd2ff167c9bf6b7aac61fe946c93e69fad1bbd8",
|
|
||||||
"sha256:8f95bb7e6edbb2456a51a1fb58c8dca942024b4f5844cae62c90aa88afe6e300"
|
|
||||||
],
|
|
||||||
"version": "==2.7.0"
|
|
||||||
},
|
|
||||||
"pytz": {
|
|
||||||
"hashes": [
|
|
||||||
"sha256:07edfc3d4d2705a20a6e99d97f0c4b61c800b8232dc1c04d87e8554f130148dd",
|
|
||||||
"sha256:3a47ff71597f821cd84a162e71593004286e5be07a340fd462f0d33a760782b5",
|
|
||||||
"sha256:410bcd1d6409026fbaa65d9ed33bf6dd8b1e94a499e32168acfc7b332e4095c0",
|
|
||||||
"sha256:5bd55c744e6feaa4d599a6cbd8228b4f8f9ba96de2c38d56f08e534b3c9edf0d",
|
|
||||||
"sha256:61242a9abc626379574a166dc0e96a66cd7c3b27fc10868003fa210be4bff1c9",
|
|
||||||
"sha256:887ab5e5b32e4d0c86efddd3d055c1f363cbaa583beb8da5e22d2fa2f64d51ef",
|
|
||||||
"sha256:ba18e6a243b3625513d85239b3e49055a2f0318466e0b8a92b8fb8ca7ccdf55f",
|
|
||||||
"sha256:ed6509d9af298b7995d69a440e2822288f2eca1681b8cce37673dbb10091e5fe",
|
|
||||||
"sha256:f93ddcdd6342f94cea379c73cddb5724e0d6d0a1c91c9bdef364dc0368ba4fda"
|
|
||||||
],
|
|
||||||
"index": "pypi",
|
|
||||||
"version": "==2018.3"
|
|
||||||
},
|
|
||||||
"pytzdata": {
|
|
||||||
"hashes": [
|
|
||||||
"sha256:4e2cceb54335cd6c28caea46b15cd592e2aec5e8b05b0241cbccfb1b23c02ae7",
|
|
||||||
"sha256:7cd949123e2c2060fd12793de3a4a449e36b5dea5e169b810a3ac3f0b9877cfa"
|
|
||||||
],
|
|
||||||
"version": "==2018.3"
|
|
||||||
},
|
|
||||||
"regex": {
|
|
||||||
"hashes": [
|
|
||||||
"sha256:1b428a296531ea1642a7da48562746309c5c06471a97bd0c02dd6a82e9cecee8",
|
|
||||||
"sha256:27d72bb42dffb32516c28d218bb054ce128afd3e18464f30837166346758af67",
|
|
||||||
"sha256:32cf4743debee9ea12d3626ee21eae83052763740e04086304e7a74778bf58c9",
|
|
||||||
"sha256:32f6408dbca35040bc65f9f4ae1444d5546411fde989cb71443a182dd643305e",
|
|
||||||
"sha256:333687d9a44738c486735955993f83bd22061a416c48f5a5f9e765e90cf1b0c9",
|
|
||||||
"sha256:35eeccf17af3b017a54d754e160af597036435c58eceae60f1dd1364ae1250c7",
|
|
||||||
"sha256:361a1fd703a35580a4714ec28d85e29780081a4c399a99bbfb2aee695d72aedb",
|
|
||||||
"sha256:494bed6396a20d3aa6376bdf2d3fbb1005b8f4339558d8ac7b53256755f80303",
|
|
||||||
"sha256:5b9c0ddd5b4afa08c9074170a2ea9b34ea296e32aeea522faaaaeeeb2fe0af2e",
|
|
||||||
"sha256:a50532f61b23d4ab9d216a6214f359dd05c911c1a1ad20986b6738a782926c1a",
|
|
||||||
"sha256:a9243d7b359b72c681a2c32eaa7ace8d346b7e8ce09d172a683acf6853161d9c",
|
|
||||||
"sha256:b44624a38d07d3c954c84ad302c29f7930f4bf01443beef5589e9157b14e2a29",
|
|
||||||
"sha256:be42a601aaaeb7a317f818490a39d153952a97c40c6e9beeb2a1103616405348",
|
|
||||||
"sha256:eee4d94b1a626490fc8170ffd788883f8c641b576e11ba9b4a29c9f6623371e0",
|
|
||||||
"sha256:f69d1201a4750f763971ea8364ed95ee888fc128968b39d38883a72a4d005895"
|
|
||||||
],
|
|
||||||
"version": "==2018.2.21"
|
|
||||||
},
|
|
||||||
"ruamel.yaml": {
|
|
||||||
"hashes": [
|
|
||||||
"sha256:01e30ecb1b1c0ebf9fce814dc20dace402571517277799291202b61b22096c24",
|
|
||||||
"sha256:02babffd019911841ba01b76e23dfec7c9e9b2725503fb2698c4982fa1a6e835",
|
|
||||||
"sha256:072f6364a89972e8dc0afdce3335a709d5464dfeaa4f736d092a54574338b874",
|
|
||||||
"sha256:14d161558e3bf89e87d77c218098be22fa9a0d6d0bea40250fce525b1d0cbee2",
|
|
||||||
"sha256:5504398fc755a2b14c9983b2101161a8591a4b30812590cc1c365e7fcc117dfa",
|
|
||||||
"sha256:68c8f2986bcb91b6db1aea8698941769840c7257e951a9377048f7eff35be773",
|
|
||||||
"sha256:6d05c5a5baf829c70916c226ef3200650846a7227de226bca8a59efaf88bb973",
|
|
||||||
"sha256:6d7929b24e329d662fa43b657fddfee5260e2d35d0a543065cd755d4e17a9b2f",
|
|
||||||
"sha256:8dc74821e4bb6b21fb1ab35964e159391d99ee44981d07d57bf96e2395f3ef75",
|
|
||||||
"sha256:9225c83952d28f302cfc23c3d9a6f8231bfd581476d7aff1e3c7de49eecb4ee9",
|
|
||||||
"sha256:b6c5d5f03ba78e3f27c7188a00c4e09b6a4507fe3154ba40a294e09cb30ee016",
|
|
||||||
"sha256:c0908896e34b617ead40552cab03c1769bdc43d1da02419160dc900c5dfddde2",
|
|
||||||
"sha256:c41e04b526d0153c9246cfab87d7ddefdc9f165cb8886a8ec48ba7a2b73069f6",
|
|
||||||
"sha256:e2d2715bf92156bec5fb42e92e95dac1c4d9904f8a3d4e2d0c438758fe9092d7",
|
|
||||||
"sha256:e3bbfe0d294e08fdbb0cb05485435a2ceb4e168e98b5dc611f051c1864986b4b",
|
|
||||||
"sha256:f2d02a4af5a13b09d0b823cdd0317b54f3e0115e50b5ac4d9840c3a1b566817f",
|
|
||||||
"sha256:fcfc24a21594c071cc4588e84b7657a1f47ebcf6037c6c43fa15c4bbd3989ec2"
|
|
||||||
],
|
|
||||||
"index": "pypi",
|
|
||||||
"version": "==0.15.35"
|
|
||||||
},
|
|
||||||
"six": {
|
|
||||||
"hashes": [
|
|
||||||
"sha256:70e8a77beed4562e7f14fe23a786b54f6296e34344c23bc42f07b15018ff98e9",
|
|
||||||
"sha256:832dc0e10feb1aa2c68dcc57dbb658f1c7e65b9b61af69048abc87a2db00a0eb"
|
|
||||||
],
|
|
||||||
"version": "==1.11.0"
|
|
||||||
},
|
|
||||||
"snaptime": {
|
|
||||||
"hashes": [
|
|
||||||
"sha256:e3f1eb89043d58d30721ab98cb65023f1a4c2740e3b197704298b163c92d508b"
|
|
||||||
],
|
|
||||||
"index": "pypi",
|
|
||||||
"version": "==0.2.4"
|
|
||||||
},
|
|
||||||
"tzlocal": {
|
|
||||||
"hashes": [
|
|
||||||
"sha256:4ebeb848845ac898da6519b9b31879cf13b6626f7184c496037b818e238f2c4e"
|
|
||||||
],
|
|
||||||
"index": "pypi",
|
|
||||||
"version": "==1.5.1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"develop": {
|
|
||||||
"alabaster": {
|
|
||||||
"hashes": [
|
|
||||||
"sha256:2eef172f44e8d301d25aff8068fddd65f767a3f04b5f15b0f4922f113aa1c732",
|
|
||||||
"sha256:37cdcb9e9954ed60912ebc1ca12a9d12178c26637abdf124e3cde2341c257fe0"
|
|
||||||
],
|
|
||||||
"version": "==0.7.10"
|
|
||||||
},
|
|
||||||
"attrs": {
|
|
||||||
"hashes": [
|
|
||||||
"sha256:1c7960ccfd6a005cd9f7ba884e6316b5e430a3f1a6c37c5f87d8b43f83b54ec9",
|
|
||||||
"sha256:a17a9573a6f475c99b551c0e0a812707ddda1ec9653bed04c13841404ed6f450"
|
|
||||||
],
|
|
||||||
"version": "==17.4.0"
|
|
||||||
},
|
|
||||||
"babel": {
|
|
||||||
"hashes": [
|
|
||||||
"sha256:8ce4cb6fdd4393edd323227cba3a077bceb2a6ce5201c902c65e730046f41f14",
|
|
||||||
"sha256:ad209a68d7162c4cff4b29cdebe3dec4cef75492df501b0049a9433c96ce6f80"
|
|
||||||
],
|
|
||||||
"version": "==2.5.3"
|
|
||||||
},
|
|
||||||
"certifi": {
|
|
||||||
"hashes": [
|
|
||||||
"sha256:14131608ad2fd56836d33a71ee60fa1c82bc9d2c8d98b7bdbc631fe1b3cd1296",
|
|
||||||
"sha256:edbc3f203427eef571f79a7692bb160a2b0f7ccaa31953e99bd17e307cf63f7d"
|
|
||||||
],
|
|
||||||
"version": "==2018.1.18"
|
|
||||||
},
|
|
||||||
"chardet": {
|
|
||||||
"hashes": [
|
|
||||||
"sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae",
|
|
||||||
"sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691"
|
|
||||||
],
|
|
||||||
"version": "==3.0.4"
|
|
||||||
},
|
|
||||||
"docutils": {
|
|
||||||
"hashes": [
|
|
||||||
"sha256:02aec4bd92ab067f6ff27a38a38a41173bf01bed8f89157768c1573f53e474a6",
|
|
||||||
"sha256:51e64ef2ebfb29cae1faa133b3710143496eca21c530f3f71424d77687764274",
|
|
||||||
"sha256:7a4bd47eaf6596e1295ecb11361139febe29b084a87bf005bf899f9a42edc3c6"
|
|
||||||
],
|
|
||||||
"version": "==0.14"
|
|
||||||
},
|
|
||||||
"idna": {
|
|
||||||
"hashes": [
|
|
||||||
"sha256:2c6a5de3089009e3da7c5dde64a141dbc8551d5b7f6cf4ed7c2568d0cc520a8f",
|
|
||||||
"sha256:8c7309c718f94b3a625cb648ace320157ad16ff131ae0af362c9f21b80ef6ec4"
|
|
||||||
],
|
|
||||||
"version": "==2.6"
|
|
||||||
},
|
|
||||||
"imagesize": {
|
|
||||||
"hashes": [
|
|
||||||
"sha256:3620cc0cadba3f7475f9940d22431fc4d407269f1be59ec9b8edcca26440cf18",
|
|
||||||
"sha256:5b326e4678b6925158ccc66a9fa3122b6106d7c876ee32d7de6ce59385b96315"
|
|
||||||
],
|
|
||||||
"version": "==1.0.0"
|
|
||||||
},
|
|
||||||
"jinja2": {
|
|
||||||
"hashes": [
|
|
||||||
"sha256:74c935a1b8bb9a3947c50a54766a969d4846290e1e788ea44c1392163723c3bd",
|
|
||||||
"sha256:f84be1bb0040caca4cea721fcbbbbd61f9be9464ca236387158b0feea01914a4"
|
|
||||||
],
|
|
||||||
"version": "==2.10"
|
|
||||||
},
|
|
||||||
"markupsafe": {
|
|
||||||
"hashes": [
|
|
||||||
"sha256:a6be69091dac236ea9c6bc7d012beab42010fa914c459791d627dad4910eb665"
|
|
||||||
],
|
|
||||||
"version": "==1.0"
|
|
||||||
},
|
|
||||||
"packaging": {
|
|
||||||
"hashes": [
|
|
||||||
"sha256:e9215d2d2535d3ae866c3d6efc77d5b24a0192cce0ff20e42896cc0664f889c0",
|
|
||||||
"sha256:f019b770dd64e585a99714f1fd5e01c7a8f11b45635aa953fd41c689a657375b"
|
|
||||||
],
|
|
||||||
"version": "==17.1"
|
|
||||||
},
|
|
||||||
"pluggy": {
|
|
||||||
"hashes": [
|
|
||||||
"sha256:7f8ae7f5bdf75671a718d2daf0a64b7885f74510bcd98b1a0bb420eb9a9d0cff"
|
|
||||||
],
|
|
||||||
"version": "==0.6.0"
|
|
||||||
},
|
|
||||||
"py": {
|
|
||||||
"hashes": [
|
|
||||||
"sha256:8cca5c229d225f8c1e3085be4fcf306090b00850fefad892f9d96c7b6e2f310f",
|
|
||||||
"sha256:ca18943e28235417756316bfada6cd96b23ce60dd532642690dcfdaba988a76d"
|
|
||||||
],
|
|
||||||
"version": "==1.5.2"
|
|
||||||
},
|
|
||||||
"pygments": {
|
|
||||||
"hashes": [
|
|
||||||
"sha256:78f3f434bcc5d6ee09020f92ba487f95ba50f1e3ef83ae96b9d5ffa1bab25c5d",
|
|
||||||
"sha256:dbae1046def0efb574852fab9e90209b23f556367b5a320c0bcb871c77c3e8cc"
|
|
||||||
],
|
|
||||||
"version": "==2.2.0"
|
|
||||||
},
|
|
||||||
"pyparsing": {
|
|
||||||
"hashes": [
|
|
||||||
"sha256:0832bcf47acd283788593e7a0f542407bd9550a55a8a8435214a1960e04bcb04",
|
|
||||||
"sha256:281683241b25fe9b80ec9d66017485f6deff1af5cde372469134b56ca8447a07",
|
|
||||||
"sha256:8f1e18d3fd36c6795bb7e02a39fd05c611ffc2596c1e0d995d34d67630426c18",
|
|
||||||
"sha256:9e8143a3e15c13713506886badd96ca4b579a87fbdf49e550dbfc057d6cb218e",
|
|
||||||
"sha256:b8b3117ed9bdf45e14dcc89345ce638ec7e0e29b2b579fa1ecf32ce45ebac8a5",
|
|
||||||
"sha256:e4d45427c6e20a59bf4f88c639dcc03ce30d193112047f94012102f235853a58",
|
|
||||||
"sha256:fee43f17a9c4087e7ed1605bd6df994c6173c1e977d7ade7b651292fab2bd010"
|
|
||||||
],
|
|
||||||
"version": "==2.2.0"
|
|
||||||
},
|
|
||||||
"pytest": {
|
|
||||||
"hashes": [
|
|
||||||
"sha256:062027955bccbc04d2fcd5d79690947e018ba31abe4c90b2c6721abec734261b",
|
|
||||||
"sha256:117bad36c1a787e1a8a659df35de53ba05f9f3398fb9e4ac17e80ad5903eb8c5"
|
|
||||||
],
|
|
||||||
"index": "pypi",
|
|
||||||
"version": "==3.4.2"
|
|
||||||
},
|
|
||||||
"pytz": {
|
|
||||||
"hashes": [
|
|
||||||
"sha256:07edfc3d4d2705a20a6e99d97f0c4b61c800b8232dc1c04d87e8554f130148dd",
|
|
||||||
"sha256:3a47ff71597f821cd84a162e71593004286e5be07a340fd462f0d33a760782b5",
|
|
||||||
"sha256:410bcd1d6409026fbaa65d9ed33bf6dd8b1e94a499e32168acfc7b332e4095c0",
|
|
||||||
"sha256:5bd55c744e6feaa4d599a6cbd8228b4f8f9ba96de2c38d56f08e534b3c9edf0d",
|
|
||||||
"sha256:61242a9abc626379574a166dc0e96a66cd7c3b27fc10868003fa210be4bff1c9",
|
|
||||||
"sha256:887ab5e5b32e4d0c86efddd3d055c1f363cbaa583beb8da5e22d2fa2f64d51ef",
|
|
||||||
"sha256:ba18e6a243b3625513d85239b3e49055a2f0318466e0b8a92b8fb8ca7ccdf55f",
|
|
||||||
"sha256:ed6509d9af298b7995d69a440e2822288f2eca1681b8cce37673dbb10091e5fe",
|
|
||||||
"sha256:f93ddcdd6342f94cea379c73cddb5724e0d6d0a1c91c9bdef364dc0368ba4fda"
|
|
||||||
],
|
|
||||||
"index": "pypi",
|
|
||||||
"version": "==2018.3"
|
|
||||||
},
|
|
||||||
"requests": {
|
|
||||||
"hashes": [
|
|
||||||
"sha256:6a1b267aa90cac58ac3a765d067950e7dbbf75b1da07e895d1f594193a40a38b",
|
|
||||||
"sha256:9c443e7324ba5b85070c4a818ade28bfabedf16ea10206da1132edaa6dda237e"
|
|
||||||
],
|
|
||||||
"version": "==2.18.4"
|
|
||||||
},
|
|
||||||
"six": {
|
|
||||||
"hashes": [
|
|
||||||
"sha256:70e8a77beed4562e7f14fe23a786b54f6296e34344c23bc42f07b15018ff98e9",
|
|
||||||
"sha256:832dc0e10feb1aa2c68dcc57dbb658f1c7e65b9b61af69048abc87a2db00a0eb"
|
|
||||||
],
|
|
||||||
"version": "==1.11.0"
|
|
||||||
},
|
|
||||||
"snowballstemmer": {
|
|
||||||
"hashes": [
|
|
||||||
"sha256:919f26a68b2c17a7634da993d91339e288964f93c274f1343e3bbbe2096e1128",
|
|
||||||
"sha256:9f3bcd3c401c3e862ec0ebe6d2c069ebc012ce142cce209c098ccb5b09136e89"
|
|
||||||
],
|
|
||||||
"version": "==1.2.1"
|
|
||||||
},
|
|
||||||
"sphinx": {
|
|
||||||
"hashes": [
|
|
||||||
"sha256:41ae26acc6130ccf6ed47e5cca73742b80d55a134f0ab897c479bba8d3640b8e",
|
|
||||||
"sha256:da987de5fcca21a4acc7f67a86a363039e67ac3e8827161e61b91deb131c0ee8"
|
|
||||||
],
|
|
||||||
"index": "pypi",
|
|
||||||
"version": "==1.7.1"
|
|
||||||
},
|
|
||||||
"sphinxcontrib-websupport": {
|
|
||||||
"hashes": [
|
|
||||||
"sha256:7a85961326aa3a400cd4ad3c816d70ed6f7c740acd7ce5d78cd0a67825072eb9",
|
|
||||||
"sha256:f4932e95869599b89bf4f80fc3989132d83c9faa5bf633e7b5e0c25dffb75da2"
|
|
||||||
],
|
|
||||||
"version": "==1.0.1"
|
|
||||||
},
|
|
||||||
"urllib3": {
|
|
||||||
"hashes": [
|
|
||||||
"sha256:06330f386d6e4b195fbfc736b297f58c5a892e4440e54d294d7004e3a9bbea1b",
|
|
||||||
"sha256:cc44da8e1145637334317feebd728bd869a35285b93cbb4cca2577da7e62db4f"
|
|
||||||
],
|
|
||||||
"version": "==1.22"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+10
-1
@@ -22,6 +22,11 @@ Maya is mostly built around the headaches and use-cases around parsing datetime
|
|||||||
|
|
||||||
.. image:: https://farm4.staticflickr.com/3702/33288285996_5b69d2b8f7_k_d.jpg
|
.. image:: https://farm4.staticflickr.com/3702/33288285996_5b69d2b8f7_k_d.jpg
|
||||||
|
|
||||||
|
Art by `Sam Flores
|
||||||
|
<https://www.instagram.com/samagram12/>`_ (Photo by `Kenneth Reitz
|
||||||
|
<https://www.instagram.com/kennethreitz/>`_).
|
||||||
|
|
||||||
|
If you're interested in financially supporting Kenneth Reitz open source, consider `visiting this link <https://cash.me/$KennethReitz>`_. Your support helps tremendously with sustainability of motivation, as Open Source is no longer part of my day job.
|
||||||
|
|
||||||
☤ Basic Usage of Maya
|
☤ Basic Usage of Maya
|
||||||
---------------------
|
---------------------
|
||||||
@@ -73,6 +78,10 @@ Behold, datetimes for humans!
|
|||||||
>>> m = maya.MayaDT.from_struct(time.gmtime())
|
>>> m = maya.MayaDT.from_struct(time.gmtime())
|
||||||
>>> print(m)
|
>>> print(m)
|
||||||
Wed, 20 Sep 2017 17:24:32 GMT
|
Wed, 20 Sep 2017 17:24:32 GMT
|
||||||
|
|
||||||
|
>>> m = maya.MayaDT(time.time())
|
||||||
|
>>> print(m)
|
||||||
|
Wed, 20 Sep 2017 17:24:32 GMT
|
||||||
|
|
||||||
>>> rand_day.day
|
>>> rand_day.day
|
||||||
7
|
7
|
||||||
@@ -129,7 +138,7 @@ From here, there are a number of methods available to you, which you can use to
|
|||||||
☤ What about Delorean, Arrow, & Pendulum?
|
☤ What about Delorean, Arrow, & Pendulum?
|
||||||
-----------------------------------------
|
-----------------------------------------
|
||||||
|
|
||||||
All these project complement each other, and are friends. Pendulum, for example, helps power Maya's parsing.
|
All these projects complement each other, and are friends. Pendulum, for example, helps power Maya's parsing.
|
||||||
|
|
||||||
Arrow, for example, is a fantastic library, but isn't what I wanted in a datetime library. In many ways, it's better than Maya for certain things. In some ways, in my opinion, it's not.
|
Arrow, for example, is a fantastic library, but isn't what I wanted in a datetime library. In many ways, it's better than Maya for certain things. In some ways, in my opinion, it's not.
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -1 +1 @@
|
|||||||
__version__ = '0.3.4'
|
__version__ = '0.6.1'
|
||||||
|
|||||||
+68
-23
@@ -1,12 +1,6 @@
|
|||||||
# ___ __ ___ _ _ ___
|
# ___ __ ___ _ _ ___
|
||||||
# || \/ | ||=|| \\// ||=||
|
# || \/ | ||=|| \\// ||=||
|
||||||
# || | || || // || ||
|
# || | || || // || ||
|
||||||
# Ignore warnings for yaml usage.
|
|
||||||
import warnings
|
|
||||||
import ruamel.yaml
|
|
||||||
|
|
||||||
warnings.simplefilter('ignore', ruamel.yaml.error.UnsafeLoaderWarning)
|
|
||||||
|
|
||||||
import email.utils
|
import email.utils
|
||||||
import time
|
import time
|
||||||
import functools
|
import functools
|
||||||
@@ -20,6 +14,7 @@ import pendulum
|
|||||||
import snaptime
|
import snaptime
|
||||||
from tzlocal import get_localzone
|
from tzlocal import get_localzone
|
||||||
from dateutil.relativedelta import relativedelta
|
from dateutil.relativedelta import relativedelta
|
||||||
|
from dateparser.languages.loader import default_loader
|
||||||
|
|
||||||
from .compat import cmp, comparable
|
from .compat import cmp, comparable
|
||||||
|
|
||||||
@@ -158,7 +153,7 @@ class MayaDT(object):
|
|||||||
|
|
||||||
def subtract_date(self, **kwargs):
|
def subtract_date(self, **kwargs):
|
||||||
"""Returns a timedelta object with the duration between the dates"""
|
"""Returns a timedelta object with the duration between the dates"""
|
||||||
return timedelta(self.epoch - kwargs['dt'].epoch)
|
return timedelta(seconds=self.epoch - kwargs['dt'].epoch)
|
||||||
|
|
||||||
def snap(self, instruction):
|
def snap(self, instruction):
|
||||||
"""
|
"""
|
||||||
@@ -263,6 +258,14 @@ class MayaDT(object):
|
|||||||
dt = dt.replace(tzinfo=self._tz)
|
dt = dt.replace(tzinfo=self._tz)
|
||||||
return dt
|
return dt
|
||||||
|
|
||||||
|
def local_datetime(self):
|
||||||
|
"""Returns a local timezone-aware datetime object
|
||||||
|
|
||||||
|
It's the same as:
|
||||||
|
mayaDt.datetime(to_timezone=mayaDt.local_timezone)
|
||||||
|
"""
|
||||||
|
return self.datetime(to_timezone=self.local_timezone, naive=False)
|
||||||
|
|
||||||
def iso8601(self):
|
def iso8601(self):
|
||||||
"""Returns an ISO 8601 representation of the MayaDT."""
|
"""Returns an ISO 8601 representation of the MayaDT."""
|
||||||
# Get a timezone-naive datetime.
|
# Get a timezone-naive datetime.
|
||||||
@@ -275,7 +278,7 @@ class MayaDT(object):
|
|||||||
|
|
||||||
def rfc3339(self):
|
def rfc3339(self):
|
||||||
"""Returns an RFC 3339 representation of the MayaDT."""
|
"""Returns an RFC 3339 representation of the MayaDT."""
|
||||||
return self.datetime().strftime("%Y-%m-%dT%H:%M:%S.%f")[:-4] + "Z"
|
return self.datetime().strftime("%Y-%m-%dT%H:%M:%S.%f")[:-5] + "Z"
|
||||||
|
|
||||||
# Properties
|
# Properties
|
||||||
# ----------
|
# ----------
|
||||||
@@ -329,15 +332,38 @@ class MayaDT(object):
|
|||||||
|
|
||||||
# Human Slang Extras
|
# Human Slang Extras
|
||||||
# ------------------
|
# ------------------
|
||||||
def slang_date(self):
|
def slang_date(self, locale="en"):
|
||||||
""""Returns human slang representation of date."""
|
""""Returns human slang representation of date.
|
||||||
dt = self.datetime(naive=True, to_timezone=self.local_timezone)
|
|
||||||
return humanize.naturaldate(dt)
|
|
||||||
|
|
||||||
def slang_time(self):
|
Keyword Arguments:
|
||||||
""""Returns human slang representation of time."""
|
locale -- locale to translate to, e.g. 'fr' for french.
|
||||||
dt = self.datetime(naive=True, to_timezone=self.local_timezone)
|
(default: 'en' - English)
|
||||||
return humanize.naturaltime(dt)
|
"""
|
||||||
|
dt = pendulum.instance(self.datetime())
|
||||||
|
|
||||||
|
try:
|
||||||
|
return _translate(dt, locale)
|
||||||
|
except KeyError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
delta = humanize.time.abs_timedelta(
|
||||||
|
timedelta(seconds=(self.epoch - now().epoch)))
|
||||||
|
|
||||||
|
format_string = "DD MMM"
|
||||||
|
if delta.days >= 365:
|
||||||
|
format_string += " YYYY"
|
||||||
|
|
||||||
|
return dt.format(format_string, locale=locale).title()
|
||||||
|
|
||||||
|
def slang_time(self, locale="en"):
|
||||||
|
""""Returns human slang representation of time.
|
||||||
|
|
||||||
|
Keyword Arguments:
|
||||||
|
locale -- locale to translate to, e.g. 'fr' for french.
|
||||||
|
(default: 'en' - English)
|
||||||
|
"""
|
||||||
|
dt = self.datetime()
|
||||||
|
return pendulum.instance(dt).diff_for_humans(locale=locale)
|
||||||
|
|
||||||
|
|
||||||
def utc_offset(time_struct=None):
|
def utc_offset(time_struct=None):
|
||||||
@@ -470,7 +496,7 @@ class MayaInterval(object):
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
end = parse(end)
|
end = parse(end)
|
||||||
except pendulum.parsing.exceptions.ParserError as e:
|
except (pendulum.parsing.exceptions.ParserError, TypeError) as e:
|
||||||
end = cls.parse_iso8601_duration(end, start=start)
|
end = cls.parse_iso8601_duration(end, start=start)
|
||||||
|
|
||||||
return cls(start=start, end=end)
|
return cls(start=start, end=end)
|
||||||
@@ -681,7 +707,7 @@ def now():
|
|||||||
return MayaDT(epoch=epoch)
|
return MayaDT(epoch=epoch)
|
||||||
|
|
||||||
|
|
||||||
def when(string, timezone='UTC', prefer_past=False):
|
def when(string, timezone='UTC', prefer_dates_from='current_period'):
|
||||||
""""Returns a MayaDT instance for the human moment specified.
|
""""Returns a MayaDT instance for the human moment specified.
|
||||||
|
|
||||||
Powered by dateparser. Useful for scraping websites.
|
Powered by dateparser. Useful for scraping websites.
|
||||||
@@ -692,16 +718,20 @@ def when(string, timezone='UTC', prefer_past=False):
|
|||||||
Keyword Arguments:
|
Keyword Arguments:
|
||||||
string -- string to be parsed
|
string -- string to be parsed
|
||||||
timezone -- timezone referenced from (default: 'UTC')
|
timezone -- timezone referenced from (default: 'UTC')
|
||||||
prefer_past -- prefer parsing ambiguous date as in the past
|
prefer_dates_from -- what dates are prefered when `string` is ambigous.
|
||||||
|
options are 'past', 'future', and 'current_period'
|
||||||
|
(default: 'current_period'). see: [1]
|
||||||
|
|
||||||
|
Reference:
|
||||||
|
[1] dateparser.readthedocs.io/en/latest/usage.html#handling-incomplete-dates
|
||||||
"""
|
"""
|
||||||
settings = {
|
settings = {
|
||||||
'TIMEZONE': timezone,
|
'TIMEZONE': timezone,
|
||||||
'RETURN_AS_TIMEZONE_AWARE': True,
|
'RETURN_AS_TIMEZONE_AWARE': True,
|
||||||
'TO_TIMEZONE': 'UTC',
|
'TO_TIMEZONE': 'UTC',
|
||||||
|
'PREFER_DATES_FROM': prefer_dates_from,
|
||||||
}
|
}
|
||||||
if prefer_past:
|
|
||||||
settings['PREFER_DATES_FROM'] = 'past'
|
|
||||||
dt = dateparser.parse(string, settings=settings)
|
dt = dateparser.parse(string, settings=settings)
|
||||||
if dt is None:
|
if dt is None:
|
||||||
raise ValueError('invalid datetime input specified.')
|
raise ValueError('invalid datetime input specified.')
|
||||||
@@ -709,7 +739,7 @@ def when(string, timezone='UTC', prefer_past=False):
|
|||||||
return MayaDT.from_datetime(dt)
|
return MayaDT.from_datetime(dt)
|
||||||
|
|
||||||
|
|
||||||
def parse(string, timezone='UTC', day_first=False, year_first=True):
|
def parse(string, timezone='UTC', day_first=False, year_first=True, strict=False):
|
||||||
""""Returns a MayaDT instance for the machine-produced moment specified.
|
""""Returns a MayaDT instance for the machine-produced moment specified.
|
||||||
|
|
||||||
Powered by pendulum.
|
Powered by pendulum.
|
||||||
@@ -724,11 +754,14 @@ def parse(string, timezone='UTC', day_first=False, year_first=True):
|
|||||||
between YDM and YMD. (default: False)
|
between YDM and YMD. (default: False)
|
||||||
year_first -- if true, the first value (e.g. 2016/05/01)
|
year_first -- if true, the first value (e.g. 2016/05/01)
|
||||||
is parsed as year (default: True)
|
is parsed as year (default: True)
|
||||||
|
strict -- if False, allow pendulum to fall back on datetime parsing
|
||||||
|
if pendulum's own parsing fails
|
||||||
"""
|
"""
|
||||||
options = {}
|
options = {}
|
||||||
options['tz'] = timezone
|
options['tz'] = timezone
|
||||||
options['day_first'] = day_first
|
options['day_first'] = day_first
|
||||||
options['year_first'] = year_first
|
options['year_first'] = year_first
|
||||||
|
options['strict'] = strict
|
||||||
|
|
||||||
dt = pendulum.parse(str(string), **options)
|
dt = pendulum.parse(str(string), **options)
|
||||||
return MayaDT.from_datetime(dt)
|
return MayaDT.from_datetime(dt)
|
||||||
@@ -753,6 +786,16 @@ def _seconds_or_timedelta(duration):
|
|||||||
return dt_timedelta
|
return dt_timedelta
|
||||||
|
|
||||||
|
|
||||||
|
def _translate(dt, target_locale):
|
||||||
|
en = default_loader.get_locale("en")
|
||||||
|
target = default_loader.get_locale(target_locale)
|
||||||
|
naturaldate = humanize.naturaldate(dt)
|
||||||
|
|
||||||
|
base = en.translate(naturaldate, settings=dateparser.conf.settings)
|
||||||
|
|
||||||
|
return target.info["relative-type"][base][-1]
|
||||||
|
|
||||||
|
|
||||||
def intervals(start, end, interval):
|
def intervals(start, end, interval):
|
||||||
"""
|
"""
|
||||||
Yields MayaDT objects between the start and end MayaDTs given,
|
Yields MayaDT objects between the start and end MayaDTs given,
|
||||||
@@ -763,4 +806,6 @@ def intervals(start, end, interval):
|
|||||||
while current_timestamp.epoch < end.epoch:
|
while current_timestamp.epoch < end.epoch:
|
||||||
yield current_timestamp
|
yield current_timestamp
|
||||||
|
|
||||||
current_timestamp = current_timestamp.add(seconds=interval.seconds)
|
current_timestamp = current_timestamp.add(
|
||||||
|
seconds=interval.total_seconds()
|
||||||
|
)
|
||||||
|
|||||||
@@ -23,10 +23,9 @@ if sys.argv[-1] == "publish":
|
|||||||
required = [
|
required = [
|
||||||
'humanize',
|
'humanize',
|
||||||
'pytz',
|
'pytz',
|
||||||
'dateparser',
|
'dateparser>=0.7.0',
|
||||||
'ruamel.yaml',
|
|
||||||
'tzlocal',
|
'tzlocal',
|
||||||
'pendulum',
|
'pendulum>=2.0.2',
|
||||||
'snaptime'
|
'snaptime'
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,24 @@
|
|||||||
|
from freezegun import freeze_time
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture(params=[
|
||||||
|
("2018-03-25T00:00:00", 2),
|
||||||
|
("2018-03-25T01:00:00", 2),
|
||||||
|
("2018-03-25T02:00:00", 2),
|
||||||
|
("2018-03-25T02:30:00", 2),
|
||||||
|
("2018-03-25T03:00:00", 2),
|
||||||
|
("2018-03-25T04:00:00", 2),
|
||||||
|
|
||||||
|
("2018-10-28T00:00:00", 2),
|
||||||
|
("2018-10-28T01:00:00", 2),
|
||||||
|
("2018-10-28T02:00:00", 2),
|
||||||
|
("2018-10-28T02:30:00", 2),
|
||||||
|
("2018-10-28T03:00:00", 2),
|
||||||
|
("2018-10-28T04:00:00", 2),
|
||||||
|
|
||||||
|
], ids=lambda x: x[0] + "_off_" + str(x[1]))
|
||||||
|
def frozen_now(request):
|
||||||
|
now_string, tz_offset = request.param
|
||||||
|
with freeze_time(now_string, tz_offset=tz_offset):
|
||||||
|
yield
|
||||||
+165
-67
@@ -1,5 +1,6 @@
|
|||||||
import copy
|
import copy
|
||||||
import time
|
import time
|
||||||
|
import calendar
|
||||||
from datetime import timedelta, datetime as Datetime
|
from datetime import timedelta, datetime as Datetime
|
||||||
|
|
||||||
import pytz
|
import pytz
|
||||||
@@ -9,51 +10,56 @@ import maya
|
|||||||
from maya.core import _seconds_or_timedelta # import private function
|
from maya.core import _seconds_or_timedelta # import private function
|
||||||
|
|
||||||
|
|
||||||
def test_rfc2822():
|
@pytest.mark.parametrize("string,expected", [
|
||||||
r = maya.parse('February 21, 1994').rfc2822()
|
('February 21, 1994',
|
||||||
|
'Mon, 21 Feb 1994 00:00:00 GMT'),
|
||||||
|
])
|
||||||
|
def test_rfc2822(string, expected):
|
||||||
|
r = maya.parse(string).rfc2822()
|
||||||
d = maya.MayaDT.from_rfc2822(r)
|
d = maya.MayaDT.from_rfc2822(r)
|
||||||
assert r == 'Mon, 21 Feb 1994 00:00:00 GMT'
|
assert r == expected
|
||||||
assert r == d.rfc2822()
|
assert r == d.rfc2822()
|
||||||
|
|
||||||
|
|
||||||
def test_iso8601():
|
@pytest.mark.parametrize("string,expected", [
|
||||||
r = maya.parse('February 21, 1994').iso8601()
|
('February 21, 1994',
|
||||||
|
'1994-02-21T00:00:00Z'),
|
||||||
|
])
|
||||||
|
def test_iso8601(string, expected):
|
||||||
|
r = maya.parse(string).iso8601()
|
||||||
d = maya.MayaDT.from_iso8601(r)
|
d = maya.MayaDT.from_iso8601(r)
|
||||||
assert r == '1994-02-21T00:00:00Z'
|
assert r == expected
|
||||||
assert r == d.iso8601()
|
assert r == d.iso8601()
|
||||||
|
|
||||||
|
|
||||||
def test_parse_iso8601():
|
@pytest.mark.parametrize("string,expected", [
|
||||||
string = '20161001T1430.4+05:30'
|
('20161001T1430.4+05:30',
|
||||||
expected = '2016-10-01T09:00:00.400000Z'
|
'2016-10-01T09:00:00.400000Z'),
|
||||||
d = maya.MayaDT.from_iso8601(string)
|
|
||||||
assert expected == d.iso8601()
|
('2016T14',
|
||||||
string = '2016T14'
|
'2016-01-01T14:00:00Z'),
|
||||||
expected = '2016-01-01T14:00:00Z'
|
|
||||||
d = maya.MayaDT.from_iso8601(string)
|
('2016-10T14',
|
||||||
assert expected == d.iso8601()
|
'2016-10-01T14:00:00Z'),
|
||||||
string = '2016-10T14'
|
|
||||||
expected = '2016-10-01T14:00:00Z'
|
('2012W05',
|
||||||
d = maya.MayaDT.from_iso8601(string)
|
'2012-01-30T00:00:00Z'),
|
||||||
assert expected == d.iso8601()
|
|
||||||
string = '2012W05'
|
('2012W055',
|
||||||
expected = '2012-01-30T00:00:00Z'
|
'2012-02-03T00:00:00Z'),
|
||||||
d = maya.MayaDT.from_iso8601(string)
|
|
||||||
assert expected == d.iso8601()
|
('2012007',
|
||||||
string = '2012W055'
|
'2012-01-07T00:00:00Z'),
|
||||||
expected = '2012-02-03T00:00:00Z'
|
|
||||||
d = maya.MayaDT.from_iso8601(string)
|
('2016-W07T09',
|
||||||
assert expected == d.iso8601()
|
'2016-02-15T09:00:00Z'),
|
||||||
string = '2012007'
|
])
|
||||||
expected = '2012-01-07T00:00:00Z'
|
def test_parse_iso8601(string, expected):
|
||||||
d = maya.MayaDT.from_iso8601(string)
|
|
||||||
assert expected == d.iso8601()
|
|
||||||
string = '2016-W07T09'
|
|
||||||
expected = '2016-02-15T09:00:00Z'
|
|
||||||
d = maya.MayaDT.from_iso8601(string)
|
d = maya.MayaDT.from_iso8601(string)
|
||||||
assert expected == d.iso8601()
|
assert expected == d.iso8601()
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.usefixtures("frozen_now")
|
||||||
def test_struct():
|
def test_struct():
|
||||||
now = round(time.time())
|
now = round(time.time())
|
||||||
ts = time.gmtime(now)
|
ts = time.gmtime(now)
|
||||||
@@ -64,7 +70,7 @@ def test_struct():
|
|||||||
ts = time.localtime(now)
|
ts = time.localtime(now)
|
||||||
m = maya.MayaDT.from_struct(ts)
|
m = maya.MayaDT.from_struct(ts)
|
||||||
dt = Datetime.fromtimestamp(
|
dt = Datetime.fromtimestamp(
|
||||||
time.mktime(ts) - maya.core.utc_offset(), pytz.UTC
|
time.mktime(ts) - maya.core.utc_offset(ts), pytz.UTC
|
||||||
)
|
)
|
||||||
assert m._epoch is not None
|
assert m._epoch is not None
|
||||||
assert m.datetime() == dt
|
assert m.datetime() == dt
|
||||||
@@ -93,12 +99,14 @@ def test_machine_parse():
|
|||||||
assert r2.day == 15
|
assert r2.day == 15
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.usefixtures("frozen_now")
|
||||||
def test_dt_tz_translation():
|
def test_dt_tz_translation():
|
||||||
d1 = maya.now().datetime()
|
d1 = maya.now().datetime()
|
||||||
d2 = maya.now().datetime(to_timezone='EST')
|
d2 = maya.now().datetime(to_timezone='EST')
|
||||||
assert (d1.hour - d2.hour) % 24 == 5
|
assert (d1.hour - d2.hour) % 24 == 5
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.usefixtures("frozen_now")
|
||||||
def test_dt_tz_naive():
|
def test_dt_tz_naive():
|
||||||
d1 = maya.now().datetime(naive=True)
|
d1 = maya.now().datetime(naive=True)
|
||||||
assert d1.tzinfo is None
|
assert d1.tzinfo is None
|
||||||
@@ -150,39 +158,90 @@ def test_slang_date():
|
|||||||
assert d.slang_date() == 'tomorrow'
|
assert d.slang_date() == 'tomorrow'
|
||||||
|
|
||||||
|
|
||||||
|
def test_slang_date_locale():
|
||||||
|
d = maya.when('tomorrow')
|
||||||
|
assert d.slang_date(locale='fr') == 'demain'
|
||||||
|
|
||||||
|
|
||||||
def test_slang_time():
|
def test_slang_time():
|
||||||
d = maya.when('1 hour ago')
|
d = maya.when('1 hour ago')
|
||||||
assert d.slang_time() == 'an hour ago'
|
assert d.slang_time() == '1 hour ago'
|
||||||
|
|
||||||
|
|
||||||
def test_parse():
|
def test_slang_time_locale():
|
||||||
d = maya.parse('February 21, 1994')
|
d = maya.when('1 hour ago')
|
||||||
assert format(d) == '1994-02-21 00:00:00+00:00'
|
assert d.slang_time(locale='de') == 'vor 1 Stunde'
|
||||||
d = maya.parse('01/05/2016')
|
|
||||||
assert format(d) == '2016-01-05 00:00:00+00:00'
|
|
||||||
d = maya.parse('01/05/2016', day_first=True)
|
|
||||||
assert format(d) == '2016-05-01 00:00:00+00:00'
|
|
||||||
d = maya.parse('2016/05/01', year_first=True, day_first=False)
|
|
||||||
assert format(d) == '2016-05-01 00:00:00+00:00'
|
|
||||||
d = maya.parse('2016/01/05', year_first=True, day_first=True)
|
|
||||||
assert format(d) == '2016-05-01 00:00:00+00:00'
|
|
||||||
d = maya.parse('01/05/2016', timezone='UTC')
|
|
||||||
assert format(d) == '2016-01-05 00:00:00+00:00'
|
|
||||||
d = maya.parse('01/05/2016', timezone='US/Central')
|
|
||||||
assert format(d) == '2016-01-05 06:00:00+00:00'
|
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("string,kwds,expected", [
|
||||||
|
('February 21, 1994', {},
|
||||||
|
'1994-02-21 00:00:00+00:00'),
|
||||||
|
|
||||||
|
('01/05/2016', {},
|
||||||
|
'2016-01-05 00:00:00+00:00'),
|
||||||
|
|
||||||
|
('01/05/2016', dict(day_first=True),
|
||||||
|
'2016-05-01 00:00:00+00:00'),
|
||||||
|
|
||||||
|
('2016/05/01', dict(year_first=True, day_first=False),
|
||||||
|
'2016-05-01 00:00:00+00:00'),
|
||||||
|
|
||||||
|
('2016/01/05', dict(year_first=True, day_first=True),
|
||||||
|
'2016-05-01 00:00:00+00:00'),
|
||||||
|
|
||||||
|
('01/05/2016', dict(timezone='UTC'),
|
||||||
|
'2016-01-05 00:00:00+00:00'),
|
||||||
|
|
||||||
|
('01/05/2016', dict(timezone='US/Central'),
|
||||||
|
'2016-01-05 06:00:00+00:00'),
|
||||||
|
])
|
||||||
|
def test_parse(string, kwds, expected):
|
||||||
|
d = maya.parse(string, **kwds)
|
||||||
|
assert format(d) == expected
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.usefixtures("frozen_now")
|
||||||
def test_when_past():
|
def test_when_past():
|
||||||
next_month = str(maya.now().add(months=1).month)
|
two_days_away = maya.now().add(days=2)
|
||||||
this_year = maya.now().year
|
|
||||||
last_year = this_year - 1
|
past_date = maya.when(
|
||||||
future_date = maya.when(next_month)
|
two_days_away.slang_date(),
|
||||||
past_date = maya.when(next_month, prefer_past=True)
|
prefer_dates_from='past')
|
||||||
assert future_date.year == this_year
|
|
||||||
if next_month == '1':
|
assert past_date < maya.now()
|
||||||
assert past_date.year == this_year
|
|
||||||
else:
|
|
||||||
assert past_date.year == last_year
|
@pytest.mark.usefixtures("frozen_now")
|
||||||
|
def test_when_future():
|
||||||
|
two_days_away = maya.now().add(days=2)
|
||||||
|
|
||||||
|
future_date = maya.when(
|
||||||
|
two_days_away.slang_date(),
|
||||||
|
prefer_dates_from='future')
|
||||||
|
|
||||||
|
assert future_date > maya.now()
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.usefixtures("frozen_now")
|
||||||
|
def test_when_past_day_name():
|
||||||
|
two_days_away = maya.now().add(days=2)
|
||||||
|
|
||||||
|
past_date = maya.when(
|
||||||
|
calendar.day_name[two_days_away.weekday],
|
||||||
|
prefer_dates_from='past')
|
||||||
|
|
||||||
|
assert past_date < maya.now()
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.usefixtures("frozen_now")
|
||||||
|
def test_when_future_day_name():
|
||||||
|
two_days_away = maya.now().add(days=2)
|
||||||
|
|
||||||
|
future_date = maya.when(
|
||||||
|
calendar.day_name[two_days_away.weekday],
|
||||||
|
prefer_dates_from='future')
|
||||||
|
|
||||||
|
assert future_date > maya.now()
|
||||||
|
|
||||||
|
|
||||||
def test_datetime_to_timezone():
|
def test_datetime_to_timezone():
|
||||||
@@ -190,13 +249,21 @@ def test_datetime_to_timezone():
|
|||||||
assert dt.tzinfo.zone == 'US/Eastern'
|
assert dt.tzinfo.zone == 'US/Eastern'
|
||||||
|
|
||||||
|
|
||||||
def test_rfc3339():
|
def test_rfc3339_epoch():
|
||||||
mdt = maya.when('2016-01-01')
|
mdt = maya.when('2016-01-01')
|
||||||
out = mdt.rfc3339()
|
out = mdt.rfc3339()
|
||||||
mdt2 = maya.MayaDT.from_rfc3339(out)
|
mdt2 = maya.MayaDT.from_rfc3339(out)
|
||||||
assert mdt.epoch == mdt2.epoch
|
assert mdt.epoch == mdt2.epoch
|
||||||
|
|
||||||
|
|
||||||
|
def test_rfc3339_format():
|
||||||
|
rfc3339 = maya.MayaDT.rfc3339(maya.when('2016-01-01T12:03:03Z'))
|
||||||
|
# it's important that the string has got a "max 1-digit millis" fragment
|
||||||
|
# as per https://tools.ietf.org/html/rfc3339#section-5.6
|
||||||
|
assert rfc3339 == '2016-01-01T12:03:03.0Z'
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.usefixtures("frozen_now")
|
||||||
def test_comparison_operations():
|
def test_comparison_operations():
|
||||||
now = maya.now()
|
now = maya.now()
|
||||||
now_copy = copy.deepcopy(now)
|
now_copy = copy.deepcopy(now)
|
||||||
@@ -238,35 +305,40 @@ def test_seconds_or_timedelta():
|
|||||||
_seconds_or_timedelta('invalid interval')
|
_seconds_or_timedelta('invalid interval')
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.usefixtures("frozen_now")
|
||||||
def test_intervals():
|
def test_intervals():
|
||||||
now = maya.now()
|
now = maya.now()
|
||||||
tomorrow = now.add(days=1)
|
tomorrow = now.add(days=1)
|
||||||
assert len(list(maya.intervals(now, tomorrow, 60 * 60))) == 24
|
assert len(list(maya.intervals(now, tomorrow, 60 * 60))) == 24
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.usefixtures("frozen_now")
|
||||||
def test_dunder_add():
|
def test_dunder_add():
|
||||||
now = maya.now()
|
now = maya.now()
|
||||||
assert now + 1 == now.add(seconds=1)
|
assert now + 1 == now.add(seconds=1)
|
||||||
assert now + timedelta(seconds=1) == now.add(seconds=1)
|
assert now + timedelta(seconds=1) == now.add(seconds=1)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.usefixtures("frozen_now")
|
||||||
def test_dunder_radd():
|
def test_dunder_radd():
|
||||||
now = maya.now()
|
now = maya.now()
|
||||||
assert now.add(seconds=1) == now + 1
|
assert now.add(seconds=1) == now + 1
|
||||||
assert now.add(seconds=1) == now + timedelta(seconds=1)
|
assert now.add(seconds=1) == now + timedelta(seconds=1)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.usefixtures("frozen_now")
|
||||||
def test_dunder_sub():
|
def test_dunder_sub():
|
||||||
now = maya.now()
|
now = maya.now()
|
||||||
assert now - 1 == now.subtract(seconds=1)
|
assert now - 1 == now.subtract(seconds=1)
|
||||||
assert now - timedelta(seconds=1) == now.subtract(seconds=1)
|
assert now - timedelta(seconds=1) == now.subtract(seconds=1)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.usefixtures("frozen_now")
|
||||||
def test_mayaDT_sub():
|
def test_mayaDT_sub():
|
||||||
now = maya.now()
|
now = maya.now()
|
||||||
then = now.add(days=1)
|
then = now.add(days=1)
|
||||||
assert then - now == timedelta(24 * 60 * 60)
|
assert then - now == timedelta(seconds=24 * 60 * 60)
|
||||||
assert now - then == timedelta(-24 * 60 * 60)
|
assert now - then == timedelta(seconds=-24 * 60 * 60)
|
||||||
|
|
||||||
|
|
||||||
def test_core_local_timezone(monkeypatch):
|
def test_core_local_timezone(monkeypatch):
|
||||||
@@ -287,10 +359,36 @@ def test_core_local_timezone(monkeypatch):
|
|||||||
assert mdt.local_timezone == 'UTC'
|
assert mdt.local_timezone == 'UTC'
|
||||||
|
|
||||||
|
|
||||||
def test_snaptime():
|
def test_getting_datetime_for_local_timezone(monkeypatch):
|
||||||
|
|
||||||
|
@property
|
||||||
|
def mock_local_tz(self):
|
||||||
|
class StaticTzInfo(object):
|
||||||
|
zone = 'Europe/Zurich'
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return "<StaticTzInfo 'Europe/Zurich'>"
|
||||||
|
|
||||||
|
return StaticTzInfo()
|
||||||
|
|
||||||
|
monkeypatch.setattr(maya.MayaDT, '_local_tz', mock_local_tz)
|
||||||
|
|
||||||
|
d = maya.parse('1994-02-21T12:00:00+05:30')
|
||||||
|
|
||||||
|
dt = pytz.timezone('Europe/Zurich').localize(
|
||||||
|
Datetime(1994, 2, 21, 7, 30))
|
||||||
|
|
||||||
|
assert d.local_datetime() == dt
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("when_str,snap_str,expected_when", [
|
||||||
|
('Mon, 21 Feb 1994 21:21:42 GMT', '@d',
|
||||||
|
'Mon, 21 Feb 1994 00:00:00 GMT'),
|
||||||
|
])
|
||||||
|
def test_snaptime(when_str, snap_str, expected_when):
|
||||||
# given
|
# given
|
||||||
dt = maya.when('Mon, 21 Feb 1994 21:21:42 GMT')
|
dt = maya.when(when_str)
|
||||||
# when
|
# when
|
||||||
dt = dt.snap('@d')
|
dt = dt.snap(snap_str)
|
||||||
# then
|
# then
|
||||||
assert dt == maya.when('Mon, 21 Feb 1994 00:00:00 GMT')
|
assert dt == maya.when(expected_when)
|
||||||
|
|||||||
@@ -570,3 +570,60 @@ def test_interval_from_iso8601_duration():
|
|||||||
|
|
||||||
assert interval.start == s
|
assert interval.start == s
|
||||||
assert interval.end == e
|
assert interval.end == e
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
"start_string,end_string,interval,expected_count",
|
||||||
|
[
|
||||||
|
("2019-01-03 11:40:00Z", "2019-01-03 11:40:20Z", 2, 10),
|
||||||
|
(
|
||||||
|
"2019-01-03 11:40:00Z",
|
||||||
|
"2019-01-03 11:40:30Z",
|
||||||
|
timedelta(seconds=2),
|
||||||
|
15,
|
||||||
|
),
|
||||||
|
("2019-01-03 11:40:00Z", "2019-01-03 11:45:00Z", 2 * 60, 3),
|
||||||
|
(
|
||||||
|
"2019-01-03 11:40:00Z",
|
||||||
|
"2019-01-03 11:51:00Z",
|
||||||
|
timedelta(minutes=1),
|
||||||
|
11,
|
||||||
|
),
|
||||||
|
("2019-01-03 11:40:00Z", "2019-01-03 21:40:00Z", 3 * 60 * 60, 4),
|
||||||
|
(
|
||||||
|
"2019-01-03 11:40:00Z",
|
||||||
|
"2019-01-03 13:41:00Z",
|
||||||
|
timedelta(hours=1),
|
||||||
|
3,
|
||||||
|
),
|
||||||
|
("2019-01-03 11:40:00Z", "2019-01-09 11:40:00Z", 3 * 60 * 60 * 24, 2),
|
||||||
|
("2019-01-03 11:40:00Z", "2019-01-05 12:00:00Z", timedelta(days=2), 2),
|
||||||
|
],
|
||||||
|
ids=(
|
||||||
|
"seconds",
|
||||||
|
"seconds-timedelta",
|
||||||
|
"minutes",
|
||||||
|
"minutes-timedelta",
|
||||||
|
"hours",
|
||||||
|
"hours-timedelta",
|
||||||
|
"days",
|
||||||
|
"days-timedelta",
|
||||||
|
),
|
||||||
|
)
|
||||||
|
def test_intervals(start_string, end_string, interval, expected_count):
|
||||||
|
start = maya.parse(start_string)
|
||||||
|
end = maya.parse(end_string)
|
||||||
|
assert len(list(maya.intervals(start, end, interval))) == expected_count
|
||||||
|
|
||||||
|
|
||||||
|
def test_issue_168_regression():
|
||||||
|
start = maya.now()
|
||||||
|
end = start.add(weeks=1)
|
||||||
|
gen = maya.intervals(start=start, end=end, interval=60 * 60 * 24)
|
||||||
|
# Since the bug causes the generator to never end, first sanity
|
||||||
|
# check that two results are not the same.
|
||||||
|
assert next(gen) != next(gen)
|
||||||
|
assert (
|
||||||
|
len(list(maya.intervals(start=start, end=end, interval=60 * 60 * 24)))
|
||||||
|
== 7
|
||||||
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user