Skip to content

Commit

Permalink
Merge 53c41c4 into 61dc378
Browse files Browse the repository at this point in the history
  • Loading branch information
bradbase committed Nov 21, 2020
2 parents 61dc378 + 53c41c4 commit 3635ee6
Show file tree
Hide file tree
Showing 8 changed files with 106 additions and 0 deletions.
1 change: 1 addition & 0 deletions CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ CHANGES
------------------

- Add functions: ``DAY()``, ``YEAR()``, ``MONTH()``, ``NOW()``, ``WEEKDAY()``
``EDATE()``, ``EOMONTH()``


0.2.10 (2020-10-30)
Expand Down
2 changes: 2 additions & 0 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,8 @@ xlcalculator is a modernization of the
* COUNTIFS
* DATE
* DAY
* EDATE
* EOMONTH
* IF
* IRR
* ISBLANK
Expand Down
Binary file added tests/resources/EDATE.xlsx
Binary file not shown.
Binary file added tests/resources/EOMONTH.xlsx
Binary file not shown.
21 changes: 21 additions & 0 deletions tests/xlfunctions/test_date.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ def test_DATE(self):
self.assertEqual(date.DATE(2024, 1, 1), dt(2024, 1, 1))
self.assertEqual(date.DATE(2025, 1, 1), dt(2025, 1, 1))
self.assertEqual(date.DATE(2026, 1, 1), dt(2026, 1, 1))
self.assertEqual(date.DATE(1911, 1, 15), dt(1911, 1, 15))

def test_DATE_with_short_year(self):
self.assertEqual(date.DATE(99, 1, 1), dt(1999, 1, 1))
Expand Down Expand Up @@ -60,6 +61,26 @@ def test_DAY(self):

self.assertEqual(date.DAY(serial_number), 15)

def test_EDATE(self):
the_date = date.DATE(2011, 1, 15)
target_serial_number = utils.datetime_to_number(dt(2011, 2, 15))
self.assertEqual(date.EDATE(the_date, 1), target_serial_number)

def test_EDATE_must_be_greater_than_epoch(self):
the_date = date.DATE(1901, 1, 15)
self.assertIsInstance(date.EDATE(the_date, -24),
xlerrors.NumExcelError)

def test_EOMONTH(self):
the_date = date.DATE(2011, 1, 1)
target_serial_number = utils.datetime_to_number(dt(2011, 2, 28))
self.assertEqual(date.EOMONTH(the_date, 1), target_serial_number)

def test_EOMONTH_must_be_greater_than_epoch(self):
the_date = date.DATE(1901, 1, 1)
self.assertIsInstance(date.EOMONTH(the_date, -24),
xlerrors.NumExcelError)

def test_MONTH(self):
sample_date = date.DATE(1911, 4, 15)
serial_number = int(sample_date)
Expand Down
20 changes: 20 additions & 0 deletions tests/xlfunctions_vs_excel/edate_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
from .. import testing


class EDateTest(testing.FunctionalTestCase):
filename = "EDATE.xlsx"

def test_counta_evaluation_A1(self):
excel_value = self.evaluator.get_cell_value('Sheet1!A1')
value = self.evaluator.evaluate('Sheet1!A1')
self.assertEqual(excel_value, value)

def test_evaluation_B1(self):
excel_value = self.evaluator.get_cell_value('Sheet1!B1')
value = self.evaluator.evaluate('Sheet1!B1')
self.assertEqual(excel_value, value)

def test_evaluation_C1(self):
excel_value = self.evaluator.get_cell_value('Sheet1!C1')
value = self.evaluator.evaluate('Sheet1!C1')
self.assertEqual(excel_value, value)
15 changes: 15 additions & 0 deletions tests/xlfunctions_vs_excel/eomonth_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
from .. import testing


class EDateTest(testing.FunctionalTestCase):
filename = "EOMONTH.xlsx"

def test_counta_evaluation_A1(self):
excel_value = self.evaluator.get_cell_value('Sheet1!A1')
value = self.evaluator.evaluate('Sheet1!A1')
self.assertEqual(excel_value, value)

def test_evaluation_B1(self):
excel_value = self.evaluator.get_cell_value('Sheet1!B1')
value = self.evaluator.evaluate('Sheet1!B1')
self.assertEqual(excel_value, value)
47 changes: 47 additions & 0 deletions xlcalculator/xlfunctions/date.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,53 @@ def DAY(
return int(date.strftime("%d"))


@xl.register()
@xl.validate_args
def EDATE(
start_date: func_xltypes.XlDateTime,
months: func_xltypes.XlNumber
) -> func_xltypes.XlDateTime:
"""Returns the serial number that represents the date that is the
indicated number of months before or after a specified date
(the start_date)
https://support.office.com/en-us/article/
edate-function-3c920eb2-6e66-44e7-a1f5-753ae47ee4f5
"""
delta = relativedelta(months=int(months))
edate = utils.number_to_datetime(int(start_date)) + delta

if edate <= utils.EXCEL_EPOCH:
raise xlerrors.NumExcelError(
f"Date result before {utils.EXCEL_EPOCH}")

return utils.datetime_to_number(edate)


@xl.register()
@xl.validate_args
def EOMONTH(
start_date: func_xltypes.XlDateTime,
months: func_xltypes.XlNumber
) -> func_xltypes.XlNumber:
"""Returns the serial number for the last day of the month that is the
indicated number of months before or after start_date.
https://support.office.com/en-us/article/
eomonth-function-7314ffa1-2bc9-4005-9d66-f49db127d628
"""
delta = relativedelta(months=int(months))
edate = utils.number_to_datetime(int(start_date)) + delta

if edate <= utils.EXCEL_EPOCH:
raise xlerrors.NumExcelError(
f"Date result before {utils.EXCEL_EPOCH}")

eomonth = edate + relativedelta(day=31)

return utils.datetime_to_number(eomonth)


@xl.register()
@xl.validate_args
def MONTH(
Expand Down

0 comments on commit 3635ee6

Please sign in to comment.