API: timezone support for statistics - fix #11

+ Client fix
This commit is contained in:
Sam 2018-06-11 18:47:04 +02:00
parent 30a16f64b0
commit 859f690ba4
4 changed files with 197 additions and 11 deletions

View File

@ -6,6 +6,7 @@ from flask import Blueprint, jsonify, request
from ..users.models import User
from ..users.utils import authenticate
from .models import Activity, Sport
from .utils import get_datetime_with_tz
from .utils_format import convert_timedelta_to_integer
stats_blueprint = Blueprint('stats', __name__)
@ -23,7 +24,14 @@ def get_activities(user_id, type):
params = request.args.copy()
date_from = params.get('from')
if date_from:
date_from = datetime.strptime(date_from, '%Y-%m-%d')
_, date_from = get_datetime_with_tz(user_id, date_from)
date_to = params.get('to')
if date_to:
date_to = datetime.strptime(f'{date_to} 23:59:59',
'%Y-%m-%d %H:%M:%S')
_, date_to = get_datetime_with_tz(user_id, date_to)
sport_id = params.get('sport_id')
time = params.get('time')
@ -41,11 +49,9 @@ def get_activities(user_id, type):
activities = Activity.query.filter(
Activity.user_id == user_id,
Activity.activity_date >= datetime.strptime(date_from, '%Y-%m-%d')
if date_from else True,
Activity.activity_date < (
datetime.strptime(date_to, '%Y-%m-%d') + timedelta(days=1)
) if date_to else True,
Activity.activity_date >= date_from if date_from else True,
Activity.activity_date < date_to + timedelta(seconds=1)
if date_to else True,
Activity.sport_id == sport_id if sport_id else True,
).order_by(
Activity.activity_date.asc()

View File

@ -207,6 +207,51 @@ def test_get_stats_by_time_all_activities_april_2018(
}
def test_get_stats_by_time_all_activities_april_2018_paris(
app, user_1_paris, sport_1_cycling, sport_2_running,
seven_activities_user_1, activity_running_user_1
):
client = app.test_client()
resp_login = client.post(
'/api/auth/login',
data=json.dumps(dict(
email='test@test.com',
password='12345678'
)),
content_type='application/json'
)
response = client.get(
f'/api/stats/{user_1_paris.id}/by_time?from=2018-04-01&to=2018-04-30',
headers=dict(
Authorization='Bearer ' + json.loads(
resp_login.data.decode()
)['auth_token']
)
)
data = json.loads(response.data.decode())
assert response.status_code == 200
assert 'success' in data['status']
assert data['data']['statistics'] == \
{
'2018':
{
'1':
{
'nb_activities': 1,
'total_distance': 8.0,
'total_duration': 6000
},
'2':
{
'nb_activities': 1,
'total_distance': 12.0,
'total_duration': 6000
}
}
}
def test_get_stats_by_year_all_activities(
app, user_1, sport_1_cycling, sport_2_running,
seven_activities_user_1, activity_running_user_1
@ -306,6 +351,51 @@ def test_get_stats_by_year_all_activities_april_2018(
}
def test_get_stats_by_year_all_activities_april_2018_paris(
app, user_1_paris, sport_1_cycling, sport_2_running,
seven_activities_user_1, activity_running_user_1
):
client = app.test_client()
resp_login = client.post(
'/api/auth/login',
data=json.dumps(dict(
email='test@test.com',
password='12345678'
)),
content_type='application/json'
)
response = client.get(
f'/api/stats/{user_1_paris.id}/by_time?from=2018-04-01&to=2018-04-30&time=year', # noqa
headers=dict(
Authorization='Bearer ' + json.loads(
resp_login.data.decode()
)['auth_token']
)
)
data = json.loads(response.data.decode())
assert response.status_code == 200
assert 'success' in data['status']
assert data['data']['statistics'] == \
{
'2018':
{
'1':
{
'nb_activities': 1,
'total_distance': 8.0,
'total_duration': 6000
},
'2':
{
'nb_activities': 1,
'total_distance': 12.0,
'total_duration': 6000
}
}
}
def test_get_stats_by_month_all_activities(
app, user_1, sport_1_cycling, sport_2_running,
seven_activities_user_1, activity_running_user_1
@ -396,6 +486,96 @@ def test_get_stats_by_month_all_activities(
}
def test_get_stats_by_month_all_activities_new_york(
app, user_1_full, sport_1_cycling, sport_2_running,
seven_activities_user_1, activity_running_user_1
):
client = app.test_client()
resp_login = client.post(
'/api/auth/login',
data=json.dumps(dict(
email='test@test.com',
password='12345678'
)),
content_type='application/json'
)
response = client.get(
f'/api/stats/{user_1_full.id}/by_time?time=month',
headers=dict(
Authorization='Bearer ' + json.loads(
resp_login.data.decode()
)['auth_token']
)
)
data = json.loads(response.data.decode())
assert response.status_code == 200
assert 'success' in data['status']
assert data['data']['statistics'] == \
{
'2017-03':
{
'1':
{
'nb_activities': 1,
'total_distance': 5.0,
'total_duration': 1024
}
},
'2017-06':
{
'1':
{
'nb_activities': 1,
'total_distance': 10.0,
'total_duration': 3456
}
},
'2018-01':
{
'1':
{
'nb_activities': 1,
'total_distance': 10.0,
'total_duration': 1024
}
},
'2018-02':
{
'1':
{
'nb_activities': 2,
'total_distance': 11.0,
'total_duration': 1600
}
},
'2018-04':
{
'1':
{
'nb_activities': 1,
'total_distance': 8.0,
'total_duration': 6000
},
'2':
{
'nb_activities': 1,
'total_distance': 12.0,
'total_duration': 6000
}
},
'2018-05':
{
'1':
{
'nb_activities': 1,
'total_distance': 10.0,
'total_duration': 3000
}
}
}
def test_get_stats_by_month_all_activities_april_2018(
app, user_1, sport_1_cycling, sport_2_running,
seven_activities_user_1, activity_running_user_1
@ -442,7 +622,7 @@ def test_get_stats_by_month_all_activities_april_2018(
def test_get_stats_by_week_all_activities(
app, user_1, sport_1_cycling, sport_2_running,
app, user_1_full, sport_1_cycling, sport_2_running,
seven_activities_user_1, activity_running_user_1
):
client = app.test_client()
@ -455,7 +635,7 @@ def test_get_stats_by_week_all_activities(
content_type='application/json'
)
response = client.get(
f'/api/stats/{user_1.id}/by_time?time=week',
f'/api/stats/{user_1_full.id}/by_time?time=week',
headers=dict(
Authorization='Bearer ' + json.loads(
resp_login.data.decode()

View File

@ -6,7 +6,7 @@ import {
} from 'recharts'
import { getStats } from '../../actions/stats'
import { activityColors, formatStats } from '../../utils'
import { activityColors, formatDuration, formatStats } from '../../utils'
class Statistics extends React.Component {
@ -90,7 +90,7 @@ class Statistics extends React.Component {
tickFormatter={value => displayedData === 'distance'
? `${value} km`
: displayedData === 'duration'
? format(new Date(value * 1000), 'HH:mm')
? format(formatDuration(value), 'HH:mm')
: value
}
/>
@ -100,7 +100,7 @@ class Statistics extends React.Component {
key={s.id}
dataKey={s.label}
formatter={value => displayedData === 'duration'
? format(new Date(value * 1000), 'HH:mm')
? format(formatDuration(value), 'HH:mm')
: value
}
stackId="a"

View File

@ -117,7 +117,7 @@ export const formatRecord = (record, tz) => {
}
}
const formatDuration = seconds => {
export const formatDuration = seconds => {
let newDate = new Date(0)
newDate = subHours(newDate.setSeconds(seconds), 1)
return newDate.getTime()