From b74ff48371e9808acc50d3667c560871f2cdc3f0 Mon Sep 17 00:00:00 2001 From: Wei Ji Date: Fri, 14 Aug 2020 15:32:20 +1200 Subject: [PATCH 1/2] Support various datetime inputs to region argument Includes: - Python datetime objects - np.datetime64 - pandas.Timestamp - xarray.DataArray with datetime64 dtype --- pygmt/helpers/decorators.py | 31 ++++++++++++++++++++++++++++--- pygmt/tests/test_plot.py | 11 ++++++++++- 2 files changed, 38 insertions(+), 4 deletions(-) diff --git a/pygmt/helpers/decorators.py b/pygmt/helpers/decorators.py index d6cae793237..612e3f04b15 100644 --- a/pygmt/helpers/decorators.py +++ b/pygmt/helpers/decorators.py @@ -8,6 +8,8 @@ import textwrap import functools +import numpy as np + from .utils import is_nonstr_iter from ..exceptions import GMTInvalidInput @@ -302,6 +304,23 @@ def kwargs_to_strings(convert_bools=True, **conversions): >>> module(123, bla=(1, 2, 3), foo=True, A=False, i=(5, 6)) {'bla': (1, 2, 3), 'foo': '', 'i': '5,6'} args: 123 + >>> import datetime + >>> module( + ... R=[ + ... np.datetime64("2010-01-01T16:00:00"), + ... datetime.datetime(2020, 1, 1, 12, 23, 45), + ... ] + ... ) + {'R': '2010-01-01T16:00:00/2020-01-01T12:23:45.000000'} + >>> import pandas as pd + >>> import xarray as xr + >>> module( + ... R=[ + ... xr.DataArray(data=np.datetime64("2005-01-01T08:00:00")), + ... pd.Timestamp("2015-01-01T12:00:00.123456789"), + ... ] + ... ) + {'R': '2005-01-01T08:00:00.000000000/2015-01-01T12:00:00.123456'} """ valid_conversions = [ @@ -338,9 +357,15 @@ def new_module(*args, **kwargs): value = kwargs[arg] issequence = fmt in separators if issequence and is_nonstr_iter(value): - kwargs[arg] = separators[fmt].join( - "{}".format(item) for item in value - ) + for index, item in enumerate(value): + try: + assert " " not in str(item) + except AssertionError: + # convert datetime-like items to string format + value[index] = np.datetime_as_string( + np.asarray(item, dtype=np.datetime64) + ) + kwargs[arg] = separators[fmt].join(f"{item}" for item in value) # Execute the original function and return its output return module_func(*args, **kwargs) diff --git a/pygmt/tests/test_plot.py b/pygmt/tests/test_plot.py index 1b0d6d80442..561d86fde4a 100644 --- a/pygmt/tests/test_plot.py +++ b/pygmt/tests/test_plot.py @@ -294,7 +294,16 @@ def test_plot_scalar_xy(): def test_plot_datetime(): """Test various datetime input data""" fig = Figure() - fig.basemap(projection="X15c/5c", region="2010-01-01/2020-01-01/0/10", frame=True) + fig.basemap( + projection="X15c/5c", + region=[ + np.array("2010-01-01T00:00:00", dtype=np.datetime64), + pd.Timestamp("2020-01-01"), + 0, + 10, + ], + frame=True, + ) # numpy.datetime64 types x = np.array( From 71b4095f1c8d5b53f979987a8a5b89cba93c1636 Mon Sep 17 00:00:00 2001 From: Wei Ji Date: Mon, 17 Aug 2020 10:28:48 +1200 Subject: [PATCH 2/2] Note how datetime_to_string conversion relies on checking for a space --- pygmt/helpers/decorators.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/pygmt/helpers/decorators.py b/pygmt/helpers/decorators.py index 612e3f04b15..0a11c37277c 100644 --- a/pygmt/helpers/decorators.py +++ b/pygmt/helpers/decorators.py @@ -359,9 +359,13 @@ def new_module(*args, **kwargs): if issequence and is_nonstr_iter(value): for index, item in enumerate(value): try: + # check if there is a space " " when converting + # a pandas.Timestamp/xr.DataArray to a string. + # If so, use np.datetime_as_string instead. assert " " not in str(item) except AssertionError: - # convert datetime-like items to string format + # convert datetime-like item to ISO 8601 + # string format like YYYY-MM-DDThh:mm:ss.ffffff value[index] = np.datetime_as_string( np.asarray(item, dtype=np.datetime64) )