Skip to content

Instantly share code, notes, and snippets.

@mathause
Last active October 16, 2018 12:39
Show Gist options
  • Save mathause/978183553d17c5c8cbfcadb5f7b8afd1 to your computer and use it in GitHub Desktop.
Save mathause/978183553d17c5c8cbfcadb5f7b8afd1 to your computer and use it in GitHub Desktop.
python date in the middle of the month
def time_middle_of_month(beg, end=None, periods=None):
""" create vector with timestamps in the middle of the month
Parameters
----------
beg : date or date vector
Start date. If end is not given and beg is a vector, uses first
entry a start date and last entry as end date.
end : date
If given used as end date.
periods: integer
If given, uses 'periods' months from the start date. Note
Note: 'beg' must be a scalar.
Examples / Test
---------------
import pytest
expected = pd.to_datetime(['2018-01-16 12:00:00', '2018-02-15 00:00:00',
'2018-03-16 12:00:00', '2018-04-16 00:00:00',
'2018-05-16 12:00:00', '2018-06-16 00:00:00',
'2018-07-16 12:00:00', '2018-08-16 12:00:00',
'2018-09-16 00:00:00', '2018-10-16 12:00:00',
'2018-11-16 00:00:00', '2018-12-16 12:00:00'],)
# -------------------------------------------------------------------------
# two dates as string
result = time_middle_of_month('2018-01-01', '2018-12-01')
assert np.all(expected == result)
# -------------------------------------------------------------------------
# dates from vector
# yields dates at the end of the month
time = pd.date_range('2018-01-01', '2018-12-01', freq='M')
result = time_middle_of_month(time)
assert np.all(expected == expected)
# -------------------------------------------------------------------------
# start date + periods
time_middle_of_month('2018-01-15', periods=12)
assert np.all(expected == expected)
# =======
# The following function calls are wrong
# cannot specify all three arguments
with pytest.raises(AssertionError):
time_middle_of_month('2018-01-01', '2018-12-01', 12)
# beg cannot be a vector if periods is given
with pytest.raises(AssertionError):
time_middle_of_month(time, periods=12)
"""
msg = "Cannot specify 'end' and 'periods'!"
assert (end is None) or (periods is None), msg
# if beg is a time vector
if end is None and periods is None:
beg = np.asarray(beg)
end = beg[-1]
beg = beg[0]
# '2000-01-01' -> Timestamp
beg = pd.to_datetime(beg)
msg = "'beg' cannot be a vector if 'periods' is given"
assert isinstance(beg, pd.Timestamp), msg
# sanitize 'beg'; eg '2000-01-31' -> '2000-01-01'
beg = pd.datetime(beg.year, beg.month, 1)
if periods is None:
end = pd.to_datetime(end)
month_beg = pd.date_range(beg, end, freq='MS')
else:
month_beg = pd.date_range(beg, periods=periods, freq='MS')
month_end = (pd.date_range(beg, freq='M', periods=month_beg.size)
+ pd.Timedelta('1d'))
return month_beg + (month_end - month_beg) / 2
# =================================================
# examples
expected = pd.to_datetime(['2018-01-16 12:00:00', '2018-02-15 00:00:00',
'2018-03-16 12:00:00', '2018-04-16 00:00:00',
'2018-05-16 12:00:00', '2018-06-16 00:00:00',
'2018-07-16 12:00:00', '2018-08-16 12:00:00',
'2018-09-16 00:00:00', '2018-10-16 12:00:00',
'2018-11-16 00:00:00', '2018-12-16 12:00:00'],)
###
import pytest
result = time_middle_of_month('2018-01-01', '2018-12-01')
assert np.all(expected == result)
# yields dates at the end of the month
time = pd.date_range('2018-01-01', '2018-12-01', freq='M')
result = time_middle_of_month(time)
assert np.all(expected == expected)
time_middle_of_month('2018-01-15', periods=12)
assert np.all(expected == expected)
# =======
# ERROR
# cannot specify all three arguments
with pytest.raises(AssertionError):
time_middle_of_month('2018-01-01', '2018-12-01', 12)
with pytest.raises(AssertionError):
time_middle_of_month(time, periods=12)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment