Repository: wagtail/wagtail
File: wagtail/admin/views/pages/edit.py (Python)

Code before:
        submitted_revision_id = self.request.POST.get(
            "overwrite_revision_id"
        ) or self.request.POST.get("loaded_revision_id")

        return submitted_revision_id and (
            submitted_revision_id != str(self.page.latest_revision_id)
        )

    def post(self, request, *args, **kwargs):
        # Don't allow POST requests if the page is an alias
        if self.page.alias_of_id:
            # Return 405 "Method Not Allowed" response
            return HttpResponse(status=405)

        # For autosave, we only want to save the page if there are no conflicts
        if self.expects_json_response and self.is_out_of_date:
            return self.json_error_response(
                "invalid_revision",
                _("Saving will overwrite a newer version."),
            )

        self.form = self.form_class(
            self.request.POST,
            self.request.FILES,
            instance=self.page,
            subscription=self.subscription,
            parent_page=self.parent,
            for_user=self.request.user,
        )

        if self.action_name == "save":
            self.form.defer_required_fields()

        if self.form.is_valid() and not self.locked_for_user:
            return self.form_valid(self.form)
        else:
            self.form.restore_required_fields()
            return self.form_invalid(self.form)

    def workflow_action_is_valid(self):
        self.workflow_action = self.request.POST["workflow-action-name"]
        available_actions = self.page.current_workflow_task.get_actions(
            self.page, self.request.user
        )
        available_action_names = [
            name for name, verbose_name, modal in available_actions
        ]
        return self.workflow_action in available_action_names

    @cached_property
    def action_name_and_method(self):

Review comment (refactor):
I think using `.isoformat()` and comparing as string *should* be safe even if the user has different timezone settings, but I'm only 80% sure.

Comparing the string also allows us to simplify this instead of having to do `.fromisoformat()` (and handling potentially malformed value for unknown clients...). Of course, that's only a bonus – if it turns out we do need to compare using the `datetime` representation, I'm happy to parse the date. Though I'll have to do further digging on how to properly compare timezone-aware datetime objects...

Code after:
    @cached_property
    def is_out_of_date(self):
        if not self.latest_revision:
            return False

        latest_revision_id = str(self.latest_revision.pk)

        # Two different sessions cannot have the same autosave revision, so if
        # autosave revision is present, it is either the latest or it is not.
        if overwrite_revision_id := self.request.POST.get("overwrite_revision_id"):
            return overwrite_revision_id != latest_revision_id

        # Client has not made an autosave revision, check the loaded revision.
        if loaded_revision_id := self.request.POST.get("loaded_revision_id"):
            # If the loaded revision is not the latest revision, it is outdated.
            if loaded_revision_id != latest_revision_id:
                return True

            # It's pointing to the latest revision, but that revision may have
            # been overwritten by another session (via autosave) since the editor
            # loaded it. The created_at is strictly increasing, so assume the
            # loaded revision outdated if it doesn't match the latest created_at.
            return (
                self.request.POST.get("loaded_revision_created_at", "")
                != self.latest_revision_created_at
            )

        # Not enough information to deduce, assume it's up to date.
        return False

    def post(self, request, *args, **kwargs):
        # Don't allow POST requests if the page is an alias
        if self.page.alias_of_id:
            # Return 405 "Method Not Allowed" response
            return HttpResponse(status=405)

        # For autosave, we only want to save the page if there are no conflicts
        if self.expects_json_response and self.is_out_of_date:
            return self.json_error_response(
                "invalid_revision",
                _("Saving will overwrite a newer version."),
            )

        self.form = self.form_class(
            self.request.POST,
            self.request.FILES,
            instance=self.page,
            subscription=self.subscription,
            parent_page=self.parent,
            for_user=self.request.user,
        )