diff --git a/apiserver/plane/api/serializers/cycle.py b/apiserver/plane/api/serializers/cycle.py index d394dc9bd6d..f7aef438494 100644 --- a/apiserver/plane/api/serializers/cycle.py +++ b/apiserver/plane/api/serializers/cycle.py @@ -6,6 +6,7 @@ from plane.db.models import Cycle, CycleIssue from plane.utils.timezone_converter import convert_to_utc + class CycleSerializer(BaseSerializer): total_issues = serializers.IntegerField(read_only=True) cancelled_issues = serializers.IntegerField(read_only=True) @@ -30,11 +31,18 @@ def validate(self, data): and data.get("end_date", None) is not None ): project_id = self.initial_data.get("project_id") or self.instance.project_id + is_start_date_end_date_equal = ( + True if data.get("start_date") == data.get("end_date") else False + ) data["start_date"] = convert_to_utc( - str(data.get("start_date").date()), project_id, is_start_date=True + date=str(data.get("start_date").date()), + project_id=project_id, + is_start_date=True, ) data["end_date"] = convert_to_utc( - str(data.get("end_date", None).date()), project_id + date=str(data.get("end_date", None).date()), + project_id=project_id, + is_start_date_end_date_equal=is_start_date_end_date_equal, ) return data diff --git a/apiserver/plane/app/serializers/cycle.py b/apiserver/plane/app/serializers/cycle.py index 28ec62134cf..6e0d31553e7 100644 --- a/apiserver/plane/app/serializers/cycle.py +++ b/apiserver/plane/app/serializers/cycle.py @@ -21,11 +21,18 @@ def validate(self, data): and data.get("end_date", None) is not None ): project_id = self.initial_data.get("project_id") or self.instance.project_id + is_start_date_end_date_equal = ( + True if data.get("start_date") == data.get("end_date") else False + ) data["start_date"] = convert_to_utc( - str(data.get("start_date").date()), project_id, is_start_date=True + date=str(data.get("start_date").date()), + project_id=project_id, + is_start_date=True, ) data["end_date"] = convert_to_utc( - str(data.get("end_date", None).date()), project_id + date=str(data.get("end_date", None).date()), + project_id=project_id, + is_start_date_end_date_equal=is_start_date_end_date_equal, ) return data diff --git a/apiserver/plane/app/views/cycle/base.py b/apiserver/plane/app/views/cycle/base.py index 9bf498886b3..b063a8a2659 100644 --- a/apiserver/plane/app/views/cycle/base.py +++ b/apiserver/plane/app/views/cycle/base.py @@ -143,10 +143,7 @@ def get_queryset(self): & Q(end_date__gte=current_time_in_utc), then=Value("CURRENT"), ), - When( - start_date__gt=current_time_in_utc, - then=Value("UPCOMING"), - ), + When(start_date__gt=current_time_in_utc, then=Value("UPCOMING")), When(end_date__lt=current_time_in_utc, then=Value("COMPLETED")), When( Q(start_date__isnull=True) & Q(end_date__isnull=True), @@ -259,7 +256,9 @@ def list(self, request, slug, project_id): "created_by", ) datetime_fields = ["start_date", "end_date"] - data = user_timezone_converter(data, datetime_fields, request.user.user_timezone) + data = user_timezone_converter( + data, datetime_fields, request.user.user_timezone + ) return Response(data, status=status.HTTP_200_OK) @allow_permission([ROLE.ADMIN, ROLE.MEMBER]) @@ -457,7 +456,9 @@ def retrieve(self, request, slug, project_id, pk): queryset = queryset.first() datetime_fields = ["start_date", "end_date"] - data = user_timezone_converter(data, datetime_fields, request.user.user_timezone) + data = user_timezone_converter( + data, datetime_fields, request.user.user_timezone + ) recent_visited_task.delay( slug=slug, @@ -533,8 +534,17 @@ def post(self, request, slug, project_id): status=status.HTTP_400_BAD_REQUEST, ) - start_date = convert_to_utc(str(start_date), project_id, is_start_date=True) - end_date = convert_to_utc(str(end_date), project_id) + is_start_date_end_date_equal = ( + True if str("start_date") == str("end_date") else False + ) + start_date = convert_to_utc( + date=str(start_date), project_id=project_id, is_start_date=True + ) + end_date = convert_to_utc( + date=str(end_date), + project_id=project_id, + is_start_date_end_date_equal=is_start_date_end_date_equal, + ) # Check if any cycle intersects in the given interval cycles = Cycle.objects.filter( diff --git a/apiserver/plane/utils/timezone_converter.py b/apiserver/plane/utils/timezone_converter.py index 46a864b62dd..3e14d0bf60b 100644 --- a/apiserver/plane/utils/timezone_converter.py +++ b/apiserver/plane/utils/timezone_converter.py @@ -3,6 +3,7 @@ from datetime import datetime, time from datetime import timedelta + def user_timezone_converter(queryset, datetime_fields, user_timezone): # Create a timezone object for the user's timezone user_tz = pytz.timezone(user_timezone) @@ -28,7 +29,9 @@ def user_timezone_converter(queryset, datetime_fields, user_timezone): return queryset_values -def convert_to_utc(date, project_id, is_start_date=False): +def convert_to_utc( + date, project_id, is_start_date=False, is_start_date_end_date_equal=False +): """ Converts a start date string to the project's local timezone at 12:00 AM and then converts it to UTC for storage. @@ -60,7 +63,12 @@ def convert_to_utc(date, project_id, is_start_date=False): # If it's an start date, add one minute if is_start_date: - localized_datetime += timedelta(minutes=1) + localized_datetime += timedelta(minutes=0, seconds=1) + + # If it's start an end date are equal, add 23 hours, 59 minutes, and 59 seconds + # to make it the end of the day + if is_start_date_end_date_equal: + localized_datetime += timedelta(hours=23, minutes=59, seconds=59) # Convert the localized datetime to UTC utc_datetime = localized_datetime.astimezone(pytz.utc)