fix: verify date with TDD

- add tests for the function

Signed-off-by: Ameya Shenoy <shenoy.ameya@gmail.com>
This commit is contained in:
Ameya Shenoy 2021-02-14 16:59:35 +05:30
parent e7b0cdaf0c
commit 04d46d06b0
Signed by: codingcoffee
GPG key ID: F7D58AAC5DACF8D3
3 changed files with 76 additions and 10 deletions

View file

@ -79,6 +79,12 @@ docker-compose exec backend python manage.py makemigrations
docker-compose exec backend python manage.py migrate
```
- To run unit tests
```sh
docker-compose exec backend python manage.py test
```
Similarly all django commands can be run this way.
## Endpoints

View file

@ -1,3 +1,40 @@
from django.test import TestCase
from unittest import mock
from app.utils import verify_date
import datetime
# Create your tests here.
class StubDate(datetime.datetime):
pass
class TestApp(TestCase):
"""Test app utils.
Publish time: datetime.datetime(2021, 2, 14, 12, 30)
"""
@mock.patch('app.utils.datetime.datetime', StubDate)
def test_today_before_publish_time(self):
StubDate.now = classmethod(lambda cls: datetime.datetime(2021, 2, 12, 8, 0, 0))
date, _ = verify_date('2021-02-14', '')
self.assertEqual(date.date(), datetime.datetime(2021, 2, 11).date())
@mock.patch('app.utils.datetime.datetime', StubDate)
def test_today_after_publish_time(self):
StubDate.now = classmethod(lambda cls: datetime.datetime(2021, 2, 12, 13, 0, 0))
date, _ = verify_date('2021-02-14', '')
self.assertEqual(date.date(), datetime.datetime(2021, 2, 12).date())
@mock.patch('app.utils.datetime.datetime', StubDate)
def test_weekend_returns_friday(self):
StubDate.now = classmethod(lambda cls: datetime.datetime(2021, 2, 14, 13, 0, 0))
date, _ = verify_date('2021-02-14', '')
self.assertEqual(date.date(), datetime.datetime(2021, 2, 12).date())
@mock.patch('app.utils.datetime.datetime', StubDate)
def test_a_future_date(self):
StubDate.now = classmethod(lambda cls: datetime.datetime(2021, 2, 15, 13, 0, 0))
date, _ = verify_date('2021-02-20', '')
self.assertEqual(date.date(), datetime.datetime(2021, 2, 15).date())

View file

@ -8,6 +8,7 @@ import csv
import json
import datetime
import logging
from typing import Tuple
from io import BytesIO, TextIOWrapper
from zipfile import ZipFile
@ -114,7 +115,10 @@ def populate_bhav_copy_data_into_postgres(data=None, date=None):
del data[0]
if date is None:
date = datetime.datetime.now().date()
# data = stocks_csv_to_json(data)
for stock in data:
# stock['date'] = date
# BhavCopyEquity.objects.get_or_create(**stock)
BhavCopyEquity.objects.get_or_create(
date=date,
sc_code=int(stock[0]),
@ -156,17 +160,36 @@ def stocks_csv_to_json(data):
return stocks
def verify_date(date, ret_message):
def verify_date(date, ret_message) -> Tuple[datetime.datetime, str]:
"""Verify current date.
Check current date and time and return the appropriate date. Also take care
of the following usecases
- if today before publish time return yesterdays data
- if today after publish time return todays data
- if a future date, return current day's data with time travel message
- if a weekend return Friday's data with custom message
"""
# Verify Date
logger.info('Verifying date %s', date)
req_date = datetime.datetime.strptime(date, '%Y-%m-%d')
# 18:00 IST == 12:30 UTC
today = datetime.datetime.now().replace(hour=12, minute=30, second=0, microsecond=0)
logger.info('Req Date: %s; Today: %s', req_date, today)
if req_date > today:
curr_datetime = datetime.datetime.now() - datetime.timedelta(hours=5, minutes=30)
req_datetime = datetime.datetime.strptime(date, '%Y-%m-%d')
next_publish_time = curr_datetime.replace(hour=6, minute=0, second=0,
microsecond=0)
logger.info('Current IST Datetime: %s; Request Datetime: %s; Next Publish: %s',
curr_datetime, req_datetime, next_publish_time)
# Check for future date
if req_datetime.date() > curr_datetime.date():
ret_message = "Time travel not yet invented! Returning latest available data."
req_date = today
if req_date.date() == today.date() and req_date < today:
req_date = today - datetime.timedelta(days=1)
return req_date, ret_message
req_datetime = curr_datetime
# Check for weekend
day_num = req_datetime.weekday()
if day_num in [5, 6]:
ret_message = "Markets are closed on weekends. Returning data for Friday."
req_datetime -= datetime.timedelta(days=day_num-4) # change req to Friday
# Check for day
if req_datetime.date() == curr_datetime.date() and curr_datetime < next_publish_time:
ret_message = "Today's data not yet published, returning yesterday's data."
req_datetime -= datetime.timedelta(days=1)
return req_datetime, ret_message