[Git][debian-gis-team/cftime][master] 5 commits: New upstream version 1.6.5
Bas Couwenberg (@sebastic)
gitlab at salsa.debian.org
Tue Oct 14 04:36:32 BST 2025
Bas Couwenberg pushed to branch master at Debian GIS Project / cftime
Commits:
3969742f by Bas Couwenberg at 2025-10-14T05:21:47+02:00
New upstream version 1.6.5
- - - - -
ff25f874 by Bas Couwenberg at 2025-10-14T05:21:48+02:00
Update upstream source from tag 'upstream/1.6.5'
Update to upstream version '1.6.5'
with Debian dir eb65021191dedd17d81493548049df35e5ffac6e
- - - - -
9b3026bf by Bas Couwenberg at 2025-10-14T05:22:03+02:00
New upstream release.
- - - - -
491d43fd by Bas Couwenberg at 2025-10-14T05:27:48+02:00
Update lintian overrides.
- - - - -
617cfdfd by Bas Couwenberg at 2025-10-14T05:27:48+02:00
Set distribution to unstable.
- - - - -
19 changed files:
- − .coveragerc
- .github/workflows/cibuildwheel.yml
- .github/workflows/deploy-docs.yml
- − .github/workflows/publish.yml
- .github/workflows/tests_conda.yml
- .github/workflows/tests_latest.yml
- Changelog
- MANIFEST.in
- README.md
- debian/changelog
- debian/lintian-overrides
- pyproject.toml
- − requirements-dev.txt
- − requirements.txt
- − setup.cfg
- setup.py
- src/cftime/__init__.py
- src/cftime/_cftime.pyx
- test/test_cftime.py
Changes:
=====================================
.coveragerc deleted
=====================================
@@ -1,22 +0,0 @@
-#
-# .coveragerc to control coverage.py
-#
-
-[run]
-relative_files = True
-branch = True
-plugins = Cython.Coverage
-include =
- src/cftime/*
-omit =
- setup.py
- docs/*
- ci/*
- test/*
- .eggs
-
-[report]
-exclude_lines =
- pragma: no cover
- def __repr__
- if __name__ == .__main__.:
=====================================
.github/workflows/cibuildwheel.yml
=====================================
@@ -29,7 +29,7 @@ jobs:
arch: x86_64
steps:
- - uses: actions/checkout at v4
+ - uses: actions/checkout at v5
with:
fetch-depth: 0
@@ -42,34 +42,32 @@ jobs:
- name: Build just oldest and newest on PRs, all on tags
shell: bash
- # - Always omit musl 3.8 b/c NumPy does not provide wheels for it
# - Always omit musllinux_aarch64 because it's slow and niche
+ # - Always skip free-threading wheels for now
# - On PPs, omit musllinux for speed
- # - On PRs, run just oldest and newest Python versions (and omit 3.8 aarch64)
+ # - On PRs, run just oldest and newest Python versions
run: |
if [[ "${{ github.event_name }}" == "pull_request" ]]; then
- CIBW_SKIP="pp* cp36-* cp37-* cp38-musllinux* cp39-* cp310-* cp311-* cp38-*_aarch64 *musllinux*"
+ CIBW_SKIP="cp311-* cp312-* cp313-* cp314t-* *musllinux*"
else
- CIBW_SKIP="pp* cp36-* cp37-* cp38-musllinux* *musllinux_aarch64"
+ CIBW_SKIP="cp314t-* *musllinux_aarch64"
fi
echo "CIBW_SKIP=$CIBW_SKIP" >> $GITHUB_ENV
echo "Setting CIBW_SKIP=$CIBW_SKIP"
- name: "Building ${{ matrix.os }} (${{ matrix.arch }}) wheels"
- uses: pypa/cibuildwheel at v2.18.1
+ uses: pypa/cibuildwheel at v3.2.1
env:
- # Skips pypy py36,37
CIBW_SKIP: ${{ env.CIBW_SKIP }}
CIBW_ARCHS: ${{ matrix.arch }}
CIBW_MANYLINUX_X86_64_IMAGE: manylinux2014
CIBW_MANYLINUX_AARCH64_IMAGE: manylinux2014
- # Emulated testing is slow, so trust that the Python 3.12 test is good enough on aarch64
+ # Emulated testing is slow, so trust that the Python 3.14 test is good enough on aarch64
# (takes about 5 minutes per wheel to build, and 5 minutes to test)
- CIBW_TEST_SKIP: "cp38-*_aarch64 cp39-*_aarch64 cp310-*_aarch64 cp311-*_aarch64"
- CIBW_TEST_REQUIRES: pytest
+ CIBW_TEST_SKIP: "cp3{10,11,12,13}-*_aarch64"
+ CIBW_TEST_GROUPS: dev
CIBW_TEST_COMMAND: >
python -c "import cftime; print(f'cftime v{cftime.__version__}')" &&
- python -m pip install check-manifest cython pytest pytest-cov &&
python -m pytest -vv {package}/test
- uses: actions/upload-artifact at v4
@@ -80,9 +78,11 @@ jobs:
build_sdist:
name: Build source distribution
- runs-on: ubuntu-latest
+ runs-on: ubuntu-22.04
steps:
- - uses: actions/checkout at v4
+ - uses: actions/checkout at v5
+ with:
+ fetch-depth: 0
- name: Build sdist
run: >
@@ -91,14 +91,15 @@ jobs:
- uses: actions/upload-artifact at v4
with:
- path: dist/*.tar.gz
+ name: pypi-artifacts
+ path: ${{ github.workspace }}/dist/*.tar.gz
show-artifacts:
needs: [build_bdist, build_sdist]
name: "Show artifacts"
runs-on: ubuntu-22.04
steps:
- - uses: actions/download-artifact at v4
+ - uses: actions/download-artifact at v5
with:
pattern: pypi-artifacts*
path: ${{ github.workspace }}/dist
@@ -116,7 +117,7 @@ jobs:
# upload to PyPI for every tag starting with 'v'
if: github.event_name == 'push' && startsWith(github.event.ref, 'refs/tags/v')
steps:
- - uses: actions/download-artifact at v4
+ - uses: actions/download-artifact at v5
with:
pattern: pypi-artifacts*
path: ${{ github.workspace }}/dist
=====================================
.github/workflows/deploy-docs.yml
=====================================
@@ -11,12 +11,12 @@ jobs:
steps:
- name: checkout
- uses: actions/checkout at v4
+ uses: actions/checkout at v5
with:
fetch-depth: 0
- name: Setup Mamba
- uses: mamba-org/setup-micromamba at v1
+ uses: mamba-org/setup-micromamba at v2
with:
environment-name: TEST
create-args: >-
=====================================
.github/workflows/publish.yml deleted
=====================================
@@ -1,48 +0,0 @@
-name: Publish to PyPI
-
-on: ["push", "pull_request"]
-
-jobs:
- packages:
- runs-on: ubuntu-latest
- steps:
- - uses: actions/checkout at v4
-
- - name: Set up Python
- uses: actions/setup-python at v5
- with:
- python-version: 3.x
-
- - name: Get tags
- run: git fetch --depth=1 origin +refs/tags/*:refs/tags/*
- shell: bash
-
- - name: Install build tools
- run: |
- python -m pip install --upgrade pip wheel setuptools setuptools_scm build twine check-manifest numpy
-
- shell: bash
-
- - name: Build binary wheel
- run: python -m build --sdist --wheel . --outdir dist
-
- - name: CheckFiles
- run: |
- ls dist
- shell: bash
-
- - name: Test wheels and sdist
- run: |
- python setup.py --version
- check-manifest --verbose
- cd dist && python -m pip install cftime*.whl
- python -m twine check *
-
- shell: bash
-
- - name: Publish a Python distribution to PyPI
- if: ${{ github.event_name == 'release' }}
- uses: pypa/gh-action-pypi-publish at master
- with:
- user: __token__
- password: ${{ secrets.PYPI_PASSWORD }}
=====================================
.github/workflows/tests_conda.yml
=====================================
@@ -12,7 +12,7 @@ jobs:
strategy:
fail-fast: false
matrix:
- python-version: [ "3.8", "3.9", "3.10", "3.11", "3.12" ]
+ python-version: [ "3.10", "3.11", "3.12", "3.13", "3.14" ]
os: [windows-latest, ubuntu-latest, macos-latest]
platform: [x64, x32]
experimental: [false]
@@ -25,10 +25,10 @@ jobs:
experimental: true
steps:
- - uses: actions/checkout at v4
+ - uses: actions/checkout at v5
- name: Setup micromamba Env
- uses: mamba-org/setup-micromamba at v1
+ uses: mamba-org/setup-micromamba at v2
with:
environment-name: TEST
create-args: >-
@@ -36,7 +36,7 @@ jobs:
numpy>1.13.3
cython>=0.29.20
pytest
- pytest-cov
+ coverage
- name: Install unstable dependencies
if: matrix.experimental == true
shell: bash -l {0}
@@ -57,4 +57,5 @@ jobs:
- name: Run Tests
shell: bash -l {0}
run: |
- pytest -vv test
+ coverage run -m pytest -vv test
+ coverage report
=====================================
.github/workflows/tests_latest.yml
=====================================
@@ -6,13 +6,13 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
- python-version: ["3.13.0-alpha.1"]
+ python-version: ["3.14.0b.1"]
steps:
- - uses: actions/checkout at v4
+ - uses: actions/checkout at v5
- name: Set up Python ${{ matrix.python-version }}
- uses: actions/setup-python at v5
+ uses: actions/setup-python at v6
with:
python-version: ${{ matrix.python-version }}
@@ -22,7 +22,7 @@ jobs:
- name: Install unstable cftime dependencies via pip
run: |
- python -m pip install --pre -r requirements-dev.txt
+ python -m pip install --pre --group dev
# get nightly wheels for numpy
python -m pip install \
--index-url https://pypi.anaconda.org/scientific-python-nightly-wheels/simple/ \
=====================================
Changelog
=====================================
@@ -1,3 +1,12 @@
+version 1.6.5 (release tag v1.6.5rel)
+=====================================
+* python 3.14 wheels, 3.8/3.9 support dropped.
+* roundtrip not correct when dates are all python datetime
+ instances and calendar not proleptic_gregorian (issue #354).
+* fix cftime.datetime.strftime so it works with two digit year
+ formatting (%y, issue #362).
+* speed up comparisions (using __richcmp___) and update docs. Issue #365.
+
version 1.6.4 (release tag v1.6.4rel)
=====================================
* build aarch64 linux wheels (issue #333).
=====================================
MANIFEST.in
=====================================
@@ -1,6 +1,4 @@
include *.txt
-include README.md
-include LICENSE
include pyproject.toml
include Changelog
exclude *.legacy
=====================================
README.md
=====================================
@@ -12,6 +12,8 @@ Time-handling functionality from netcdf4-python
## News
For details on the latest updates, see the [Changelog](https://github.com/Unidata/cftime/blob/master/Changelog).
+10/13/2025: Version 1.6.5 release. Minor bugfixes/optimizations, wheels for python 3.14, no more wheels for 3.8/3.9.
+
6/7/2024: Version 1.6.4 release. Wheels for muslinux and aarch64, numpy 2.0 compatibility.
10/20/2023: Version 1.6.3 released. Support for python 3.12, cython 3.0, strptime formats without separators.
=====================================
debian/changelog
=====================================
@@ -1,10 +1,11 @@
-cftime (1.6.4-3) UNRELEASED; urgency=medium
+cftime (1.6.5-1) unstable; urgency=medium
+ * New upstream release.
* Bump Standards-Version to 4.7.2, no changes.
* Update lintian overrides.
* Drop Rules-Requires-Root: no, default since dpkg 1.22.13.
- -- Bas Couwenberg <sebastic at debian.org> Thu, 20 Mar 2025 06:03:09 +0100
+ -- Bas Couwenberg <sebastic at debian.org> Tue, 14 Oct 2025 05:22:48 +0200
cftime (1.6.4-2) unstable; urgency=medium
=====================================
debian/lintian-overrides
=====================================
@@ -1,6 +1,3 @@
-# False positive (#1094364)
-missing-dependency-on-numpy-abi *
-
# False positive
package-contains-documentation-outside-usr-share-doc [usr/lib/python3/dist-packages/*-info/*.txt]
=====================================
pyproject.toml
=====================================
@@ -1,9 +1,102 @@
+[project]
+name = "cftime"
+version = "1.6.5"
+description = "Time-handling functionality from netcdf4-python"
+readme = "README.md"
+authors = [
+ { name="Jeff Whitaker", email="whitaker.jeffrey at gmail.com"}
+]
+license = "MIT"
+license-files = ["LICENSE"]
+classifiers = [
+ 'Development Status :: 5 - Production/Stable',
+ 'Operating System :: MacOS :: MacOS X',
+ 'Operating System :: Microsoft :: Windows',
+ 'Operating System :: POSIX :: Linux',
+ 'Programming Language :: Python',
+ 'Programming Language :: Python :: 3',
+ 'Programming Language :: Python :: 3.10',
+ 'Programming Language :: Python :: 3.11',
+ 'Programming Language :: Python :: 3.12',
+ 'Programming Language :: Python :: 3.13',
+ 'Programming Language :: Python :: 3.14',
+ 'Topic :: Scientific/Engineering',
+]
+dependencies = [
+ "numpy>=1.21.2",
+]
+requires-python = ">=3.10"
+
+[dependency-groups]
+dev = [
+ "check-manifest",
+ "coverage>=7.10.0",
+ "coveralls",
+ "cython>=0.29.20",
+ "pytest",
+ "sphinx",
+ "twine",
+]
+
[build-system]
requires = [
- "setuptools>=41.2",
+ "setuptools>=77.0.1",
"cython>=0.29.20",
- "wheel",
- "oldest-supported-numpy ; python_version < '3.9'",
- "numpy>=2.0.0rc1,<3 ; python_version >= '3.9'",
+ "numpy>=2.0.0,<3",
]
build-backend = "setuptools.build_meta"
+
+[tool.setuptools]
+package-dir = {"" = "src"}
+
+[tool.pytest.ini_options]
+testpaths = "test"
+addopts = [
+ "-ra",
+ "-v",
+ "--doctest-modules",
+]
+doctest_optionflags = [
+ "NORMALIZE_WHITESPACE",
+ "ELLIPSIS",
+]
+
+[tool.coverage.run]
+source = ["src"]
+relative_files = true
+branch = true
+plugins = [
+ "Cython.Coverage",
+]
+include = [
+ "src/cftime/*",
+]
+omit = [
+ "setup.py",
+ "docs/*",
+ "ci/*",
+ "test/*",
+ ".eggs",
+]
+
+[tool.coverage.report]
+show_missing = true
+exclude_lines = [
+ "pragma: no cover",
+ "def __repr__",
+ "if __name__ == .__main__.:",
+]
+
+[tool.check-manifest]
+ignore = [
+ "*.yml",
+ ".coveragerc",
+ ".gitignore",
+ "README.release",
+ "ci",
+ "ci/*",
+ "docs",
+ "docs/*",
+ "test",
+ "test/*",
+]
=====================================
requirements-dev.txt deleted
=====================================
@@ -1,9 +0,0 @@
-check-manifest
-coverage
-coveralls
-cython>=0.29.20
-pytest
-pytest-cov
-sphinx
-twine
-wheel
=====================================
requirements.txt deleted
=====================================
@@ -1,2 +0,0 @@
-numpy>1.13.3; python_version<'3.12.0.rc1'
-numpy>=1.26.0b1; python_version>='3.12.0.rc1'
=====================================
setup.cfg deleted
=====================================
@@ -1,23 +0,0 @@
-[tool:pytest]
-testpaths = test
-addopts =
- -ra
- -v
- --doctest-modules
- --cov-config .coveragerc
- --cov=cftime
- --cov-report term-missing
-doctest_optionflags = NORMALIZE_WHITESPACE ELLIPSIS
-
-[check-manifest]
-ignore =
- *.yml
- .coveragerc
- .gitignore
- README.release
- ci
- ci/*
- docs
- docs/*
- test
- test/*
=====================================
setup.py
=====================================
@@ -2,14 +2,9 @@ import os
import sys
import numpy
+from Cython.Build import cythonize
from setuptools import Command, Extension, setup
-# https://github.com/Unidata/cftime/issues/34
-try:
- from Cython.Build import cythonize
-except ImportError:
- cythonize = False
-
BASEDIR = os.path.abspath(os.path.dirname(__file__))
SRCDIR = os.path.join(BASEDIR,'src')
@@ -58,31 +53,6 @@ class CleanCython(Command):
print('clean: skipping file {!r}'.format(artifact))
-def extract_version():
- version = None
- with open(CYTHON_FNAME) as fi:
- for line in fi:
- if (line.startswith('__version__')):
- _, version = line.split('=')
- version = version.strip()[1:-1] # Remove quotation characters.
- break
- return version
-
-
-def load(fname):
- result = []
- with open(fname, 'r') as fi:
- result = [package.strip() for package in fi.readlines()]
- return result
-
-
-def description():
- fname = os.path.join(BASEDIR, 'README.md')
- with open(fname, 'r') as fi:
- result = ''.join(fi.readlines())
- return result
-
-
if ((FLAG_COVERAGE in sys.argv or os.environ.get('CYTHON_COVERAGE', None))
and cythonize):
COMPILER_DIRECTIVES = {
@@ -99,43 +69,17 @@ if any([arg in CMDS_NOCYTHONIZE for arg in sys.argv]):
ext_modules = []
else:
extension = Extension('{}._{}'.format(NAME, NAME),
- sources=[CYTHON_FNAME],
+ sources=[os.path.relpath(CYTHON_FNAME, BASEDIR)],
define_macros=DEFINE_MACROS,
include_dirs=[numpy.get_include(),])
- ext_modules = [extension]
- if cythonize:
- ext_modules = cythonize(extension,
- compiler_directives=COMPILER_DIRECTIVES,
- language_level=3)
+
+ ext_modules = cythonize(
+ extension,
+ compiler_directives=COMPILER_DIRECTIVES,
+ language_level=3,
+ )
setup(
- name=NAME,
- author='Jeff Whitaker',
- author_email='jeffrey.s.whitaker at noaa.gov',
- description='Time-handling functionality from netcdf4-python',
- long_description=description(),
- long_description_content_type='text/markdown',
cmdclass={'clean_cython': CleanCython},
- packages=[NAME],
- package_dir={'':'src'},
- version=extract_version(),
ext_modules=ext_modules,
- install_requires=load('requirements.txt'),
- tests_require=load('requirements-dev.txt'),
- license='License :: OSI Approved :: MIT License',
- python_requires=">=3.8",
- classifiers=[
- 'Development Status :: 5 - Production/Stable',
- 'Operating System :: MacOS :: MacOS X',
- 'Operating System :: Microsoft :: Windows',
- 'Operating System :: POSIX :: Linux',
- 'Programming Language :: Python',
- 'Programming Language :: Python :: 3',
- 'Programming Language :: Python :: 3.8',
- 'Programming Language :: Python :: 3.9',
- 'Programming Language :: Python :: 3.10',
- 'Programming Language :: Python :: 3.11',
- 'Programming Language :: Python :: 3.12',
- 'Topic :: Scientific/Engineering',
- 'License :: OSI Approved :: MIT License'],
- )
+)
=====================================
src/cftime/__init__.py
=====================================
@@ -4,8 +4,16 @@ from ._cftime import num2date, date2num, date2index, time2index, num2pydate, to_
from ._cftime import (microsec_units, millisec_units,
sec_units, hr_units, day_units, min_units,
UNIT_CONVERSION_FACTORS)
-from ._cftime import __version__, CFWarning
+from ._cftime import CFWarning
# these will be removed in a future release
from ._cftime import (DatetimeNoLeap, DatetimeAllLeap, Datetime360Day,
Datetime360Day, DatetimeJulian,
DatetimeGregorian, DatetimeProlepticGregorian)
+
+
+def __getattr__(item: str):
+ if item == "__version__":
+ from importlib.metadata import version
+ return version("cftime")
+
+ raise AttributeError(f"module 'cftime' has no attribute {item!r}")
=====================================
src/cftime/_cftime.pyx
=====================================
@@ -40,8 +40,6 @@ cdef int[12] _dayspermonth_leap = [31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 3
cdef int[13] _cumdayspermonth = [0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365]
cdef int[13] _cumdayspermonth_leap = [0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366]
-__version__ = '1.6.4'
-
# Adapted from http://delete.me.uk/2005/03/iso8601.html
# Note: This regex ensures that all ISO8601 timezone formats are accepted - but, due to legacy support for other timestrings, not all incorrect formats can be rejected.
# For example, the TZ spec "+01:0" will still work even though the minutes value is only one character long.
@@ -261,7 +259,7 @@ def date2num(dates, units, calendar=None, has_year_zero=None, longdouble=False):
if unit in ["months", "month"] and calendar != "360_day":
raise ValueError("Units of months only valid for 360_day calendar.")
unit_timedelta = timedelta(microseconds=UNIT_CONVERSION_FACTORS[unit])
- can_use_python_basedatetime = _can_use_python_datetime(basedate,calendar)
+ can_use_python_basedatetime = calendar=='proleptic_gregorian' and _can_use_python_datetime(basedate,calendar)
if can_use_python_basedatetime and all_python_datetimes:
use_python_datetime = True
@@ -1062,6 +1060,11 @@ Gregorian calendar.
Supports timedelta operations by overloading +/-, and
comparisons with other instances (even if they use different calendars).
+When comparing instances with different calendars, the second instance in the comparison (RHS) is
+converted to the calendar of the LHS instance. When comparing a list or array of instances (all using
+the same calendar) to a single scalar instance,
+it is much faster to convert the single instance to the calendar of the array before doing
+the comparison.
Comparison with native python datetime instances is possible
for cftime.datetime instances using
@@ -1410,7 +1413,7 @@ The default format of the string produced by strftime is controlled by self.form
return hash(self.timetuple())
return hash(d)
- cdef to_tuple(self):
+ def to_tuple(self):
return (self.year, self.month, self.day, self.hour, self.minute,
self.second, self.microsecond)
@@ -1423,19 +1426,12 @@ The default format of the string produced by strftime is controlled by self.form
if dt.calendar == dt_other.calendar and dt.has_year_zero == dt_other.has_year_zero:
return PyObject_RichCompare(dt.to_tuple(), dt_other.to_tuple(), op)
else:
- # convert both to common calendar (ISO 8601), then compare
- try:
- if self.calendar == 'proleptic_gregorian' and self.has_year_zero:
- d1 = self
- else:
- d1 = self.change_calendar('proleptic_gregorian',has_year_zero=True)
- if other.calendar == 'proleptic_gregorian' and other.has_year_zero:
- d2 = other
- else:
- d2 = other.change_calendar('proleptic_gregorian',has_year_zero=True)
- except ValueError: # change_calendar won't work for idealized calendars (ValueError)
- raise TypeError("cannot compare {0!r} and {1!r}".format(dt, dt_other))
- return PyObject_RichCompare(d1.to_tuple(), d2.to_tuple(), op)
+ # raise an error if either is an idealized calendar (comparison not valid)
+ if dt.calendar in _idealized_calendars or other.calendar in _idealized_calendars:
+ raise TypeError("cannot compare {0!r} and {1!r}".format(dt, other))
+ # convert one to match calendar of the other.
+ other2 = other.change_calendar(dt.calendar,has_year_zero=dt.has_year_zero)
+ return PyObject_RichCompare(dt.to_tuple(), other2.to_tuple(), op)
elif isinstance(other, datetime_python):
# comparing datetime and real_datetime
if not dt.datetime_compatible:
@@ -1471,8 +1467,8 @@ The default format of the string produced by strftime is controlled by self.form
def fromordinal(jday,calendar='standard',has_year_zero=None):
"""Create a datetime instance from a julian day ordinal, calendar
and (optionally) year zero convention (inverse of toordinal). The
- Julian day number is the number of days since noon UTC January 1, 4713
- in the proleptic julian calendar with no year zero (November 24, 4713
+ Julian day number is the number of days since noon UTC January 1, -4713
+ in the proleptic julian calendar with no year zero (November 24, -4713
in the proleptic gregorian calendar that includes the year zero). For
idealized calendars, the origin is noon UTC of the year zero."""
calendar = calendar.lower()
@@ -1696,10 +1692,17 @@ cdef _strftime(datetime dt, fmt):
year = year + ((2000 - year) // 28) * 28
timetuple = dt.timetuple()
s1 = time.strftime(fmt1, (year,) + timetuple[1:])
- sites1 = _findall(s1, str(year))
+ twodigityear = 'y' in fmt1
+ if twodigityear:
+ sites1 = _findall(s1, str(year)[-2:])
+ else:
+ sites1 = _findall(s1, str(year))
s2 = time.strftime(fmt1, (year + 28,) + timetuple[1:])
- sites2 = _findall(s2, str(year + 28))
+ if twodigityear:
+ sites2 = _findall(s2, str(year + 28)[-2:])
+ else:
+ sites2 = _findall(s2, str(year + 28))
sites = []
for site in sites1:
@@ -1711,8 +1714,14 @@ cdef _strftime(datetime dt, fmt):
syear = "%05d" % (dt.year,)
else:
syear = "%04d" % (dt.year,)
+ n=4
+ if twodigityear:
+ syear = syear[-2:]
+ if dt.year < 0:
+ syear = '-'+syear
+ n=2
for site in sites:
- s = s[:site] + syear + s[site + 4:]
+ s = s[:site] + syear + s[site + n:]
if ihavems:
s = s + '.{:06d}'.format(dt.microsecond)
return s
=====================================
test/test_cftime.py
=====================================
@@ -64,6 +64,7 @@ est = timezone(timedelta(hours=-5), 'UTC')
dtime = namedtuple('dtime', ('values', 'units', 'calendar'))
dateformat = '%Y-%m-%d %H:%M:%S'
+dateformat2 = '%y-%m-%d %H:%M:%S'
calendars=['standard', 'gregorian', 'proleptic_gregorian', 'noleap', 'julian',\
'all_leap', '365_day', '366_day', '360_day']
@@ -201,6 +202,8 @@ class cftimeTestCase(unittest.TestCase):
# check num2date method.
d2 = self.cdftime_pg.num2date(t1)
self.assertTrue(d.strftime(dateformat) == d2.strftime(dateformat))
+ # make sure two digit years work in strftime (issue #362)
+ self.assertTrue(d.strftime(dateformat2) == d2.strftime(dateformat2))
# check day of year.
ndayr = d.timetuple()[7]
self.assertTrue(ndayr == 125)
@@ -943,6 +946,16 @@ class cftimeTestCase(unittest.TestCase):
times = np.array([1,2,3,np.inf],dtype=np.float64)
result = cftime.num2date(times, 'days since 2000-01-01', 'standard')
np.testing.assert_equal(result, expected)
+ # issue #354: roundtrip not correct when dates are all python datetime
+ # instances and calendar not proleptic_gregorian.
+ datesin = np.array(["0002"],
+ dtype="datetime64[s]").astype("M8[us]").astype(datetime)
+ datein = datesin.item()
+ num = cftime.date2num(datein, "seconds since 2000-01-01", calendar='standard')
+ dateout = cftime.num2date(num, "seconds since 2000-01-01", calendar='standard')
+ dateout2 = cftime.datetime(datein.year, datein.month, datein.day,
+ calendar='standard')
+ assert(dateout==dateout2)
class TestDate2index(unittest.TestCase):
View it on GitLab: https://salsa.debian.org/debian-gis-team/cftime/-/compare/70bf4d10b8640828321e03cafbe84a60d8300f8a...617cfdfdeb3179c242f0e30f868cf784b909a1dc
--
View it on GitLab: https://salsa.debian.org/debian-gis-team/cftime/-/compare/70bf4d10b8640828321e03cafbe84a60d8300f8a...617cfdfdeb3179c242f0e30f868cf784b909a1dc
You're receiving this email because of your account on salsa.debian.org.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://alioth-lists.debian.net/pipermail/pkg-grass-devel/attachments/20251014/b572f04b/attachment-0001.htm>
More information about the Pkg-grass-devel
mailing list