Skip to content

Commit

Permalink
extract beginning_of_week calculation into OpenProject::I18n
Browse files Browse the repository at this point in the history
  • Loading branch information
ulferts committed Feb 14, 2025
1 parent ff5c9d6 commit c2c143f
Show file tree
Hide file tree
Showing 9 changed files with 278 additions and 33 deletions.
16 changes: 1 addition & 15 deletions app/models/queries/operators/this_week.rb
Original file line number Diff line number Diff line change
Expand Up @@ -33,24 +33,10 @@ class ThisWeek < Base
require_value false

def self.sql_for_field(_values, db_table, db_field)
from = begin_of_week
from = OpenProject::I18n::Date.time_at_beginning_of_week
"#{db_table}.#{db_field} BETWEEN '%s' AND '%s'" % [
connection.quoted_date(from), connection.quoted_date(from + 7.days)
]
end

def self.begin_of_week
if I18n.t(:general_first_day_of_week) == "7"
# week starts on sunday
if Time.zone.today.cwday == 7
Time.current.at_beginning_of_day
else
Time.current.at_beginning_of_week - 1.day
end
else
# week starts on monday (Rails default)
Time.current.at_beginning_of_week
end
end
end
end
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
# frozen_string_literal: true

# -- copyright
# OpenProject is an open source project management software.
# Copyright (C) 2010-2024 the OpenProject GmbH
Expand Down
54 changes: 54 additions & 0 deletions lib/open_project/i18n/date.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
# frozen_string_literal: true

# -- copyright
# OpenProject is an open source project management software.
# Copyright (C) 2010-2025 the OpenProject GmbH
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License version 3.
#
# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
# Copyright (C) 2006-2013 Jean-Philippe Lang
# Copyright (C) 2010-2013 the ChiliProject Team
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# See COPYRIGHT and LICENSE files for more details.
# ++

module OpenProject
module I18n
module Date
module_function

def self.beginning_of_week
case (Setting.start_of_week || ::I18n.t(:general_first_day_of_week)).to_i
when 1
:monday
when 7
:sunday
when 6
:saturday
else
::Date.beginning_of_week
end
end

def time_at_beginning_of_week
Time.current.at_beginning_of_week(beginning_of_week)
end
end
end
end
4 changes: 2 additions & 2 deletions lib/open_project/locale_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,13 @@
module OpenProject
module LocaleHelper
def with_locale_for(user)
previous_locale = I18n.locale
previous_locale = ::I18n.locale
previous_zone = Time.zone
Time.zone = user.time_zone if user.time_zone
SetLocalizationService.new(user).call
yield
ensure
I18n.locale = previous_locale
::I18n.locale = previous_locale
Time.zone = previous_zone
end

Expand Down
16 changes: 3 additions & 13 deletions lib_static/redmine/i18n.rb
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@
# See COPYRIGHT and LICENSE files for more details.
#++

# This file is to be split up into smaller files in the OpenProject namespace.
# A start has been made by splitting off OpenProject::I18n::Date into its own file.

module Redmine
module I18n
include ActionView::Helpers::NumberHelper
Expand All @@ -45,19 +48,6 @@ def self.all_languages
.sort
end

def self.start_of_week
case Setting.start_of_week.to_i
when 1
:monday
when 7
:sunday
when 6
:saturday
else
Date.beginning_of_week
end
end

def self.valid_languages
all_languages & (Setting.available_languages + [Setting.default_language])
end
Expand Down
2 changes: 1 addition & 1 deletion modules/meeting/app/controllers/meetings_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -369,7 +369,7 @@ def load_meetings
end

def group_meetings(all_meetings) # rubocop:disable Metrics/AbcSize
next_week = Time.current.next_occurring(Redmine::I18n.start_of_week)
next_week = Time.current.next_occurring(OpenProject::I18n::Date.start_of_week)
groups = Hash.new { |h, k| h[k] = [] }
groups[:later] = show_more_pagination(all_meetings
.where(start_time: next_week..)
Expand Down
2 changes: 1 addition & 1 deletion modules/meeting/spec/requests/meetings_index_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@
end

describe "with start_of_week on sunday",
with_settings: { start_of_week: 0 } do
with_settings: { start_of_week: 7 } do
it "sorts upcoming meetings into buckets" do
expect(subject).to have_http_status(:ok)

Expand Down
2 changes: 1 addition & 1 deletion modules/meeting/spec/support/pages/meetings/index.rb
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,7 @@ def expect_meeting_listed_in_group(meeting, key: meeting_group_key(meeting))

def meeting_group_key(meeting)
start_date = meeting.start_time.to_date
next_week = Time.current.next_occurring(Redmine::I18n.start_of_week)
next_week = Time.current.next_occurring(OpenProject::I18n::Date.start_of_week)

if start_date == Time.zone.today
:today
Expand Down
213 changes: 213 additions & 0 deletions spec/lib/open_project/i18n/date_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,213 @@
# frozen_string_literal: true

# -- copyright
# OpenProject is an open source project management software.
# Copyright (C) 2025 the OpenProject GmbH
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License version 3.
#
# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
# Copyright (C) 2006-2013 Jean-Philippe Lang
# Copyright (C) 2010-2013 the ChiliProject Team
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# See COPYRIGHT and LICENSE files for more details.
# ++

require "spec_helper"

RSpec.describe OpenProject::I18n::Date do
describe ".beginning_of_week" do
context "when the first day of the week is Sunday", with_settings: { start_of_week: 7 } do
it "returns :sunday" do
expect(described_class.beginning_of_week).to eq(:sunday)
end
end

context "when the first day of the week is Monday", with_settings: { start_of_week: 2 } do
it "returns :monday" do
expect(described_class.beginning_of_week).to eq(:monday)
end
end

context "when the first day of the week is Saturday", with_settings: { start_of_week: 6 } do
it "returns :monday" do
expect(described_class.beginning_of_week).to eq(:saturday)
end
end

context "when the first day of the week is not set and I18n states Monday", with_settings: { start_of_week: nil } do
before do
allow(I18n).to receive(:t).with(:general_first_day_of_week).and_return("1")
end

it "returns :monday" do
expect(described_class.beginning_of_week).to eq(:monday)
end
end

context "when the first day of the week is not set and I18n states Sunday", with_settings: { start_of_week: nil } do
before do
allow(I18n).to receive(:t).with(:general_first_day_of_week).and_return("7")
end

it "returns :sunday" do
expect(described_class.beginning_of_week).to eq(:sunday)
end
end
end

describe ".time_at_beginning_of_week" do
context "when the first day of the week is Sunday", with_settings: { start_of_week: 7 } do
context "when today is Sunday" do
it "returns the beginning of the day" do
Timecop.travel(DateTime.parse("2025-02-16").noon) do
expect(described_class.time_at_beginning_of_week).to eq(Time.zone.parse("2025-02-16").beginning_of_day)
end
end
end

context "when today is Monday" do
it "returns the beginning of Sunday" do
Timecop.travel(DateTime.parse("2025-02-10").noon) do
expect(described_class.time_at_beginning_of_week).to eq(Time.zone.parse("2025-02-09").beginning_of_day)
end
end
end

context "when today is Saturday" do
it "returns the beginning of Sunday" do
Timecop.travel(DateTime.parse("2025-02-15").noon) do
expect(described_class.time_at_beginning_of_week).to eq(Time.zone.parse("2025-02-09").beginning_of_day)
end
end
end
end

context "when the first day of the week is Monday", with_settings: { start_of_week: 1 } do
context "when today is Sunday" do
it "returns the beginning of the Monday" do
Timecop.travel(DateTime.parse("2025-02-16").noon) do
expect(described_class.time_at_beginning_of_week).to eq(Time.zone.parse("2025-02-10").beginning_of_day)
end
end
end

context "when today is Monday" do
it "returns the beginning of the day" do
Timecop.travel(DateTime.parse("2025-02-10").noon) do
expect(described_class.time_at_beginning_of_week).to eq(Time.zone.parse("2025-02-10").beginning_of_day)
end
end
end

context "when today is Saturday" do
it "returns the beginning of Monday" do
Timecop.travel(DateTime.parse("2025-02-15").noon) do
expect(described_class.time_at_beginning_of_week).to eq(Time.zone.parse("2025-02-10").beginning_of_day)
end
end
end
end

context "when the first day of the week is Saturday", with_settings: { start_of_week: 6 } do
context "when today is Sunday" do
it "returns the beginning of the Monday" do
Timecop.travel(DateTime.parse("2025-02-16").noon) do
expect(described_class.time_at_beginning_of_week).to eq(Time.zone.parse("2025-02-15").beginning_of_day)
end
end
end

context "when today is Monday" do
it "returns the beginning of the day" do
Timecop.travel(DateTime.parse("2025-02-10").noon) do
expect(described_class.time_at_beginning_of_week).to eq(Time.zone.parse("2025-02-08").beginning_of_day)
end
end
end

context "when today is Saturday" do
it "returns the beginning of Monday" do
Timecop.travel(DateTime.parse("2025-02-15").noon) do
expect(described_class.time_at_beginning_of_week).to eq(Time.zone.parse("2025-02-15").beginning_of_day)
end
end
end
end

context "when the first day of the week is not set but language states '7'", with_settings: { start_of_week: nil } do
before do
allow(I18n).to receive(:t).with(:general_first_day_of_week).and_return("7")
end

context "when today is Sunday" do
it "returns the beginning of the day" do
Timecop.travel(DateTime.parse("2025-02-16").noon) do
expect(described_class.time_at_beginning_of_week).to eq(Time.zone.parse("2025-02-16").beginning_of_day)
end
end
end

context "when today is Monday" do
it "returns the beginning of Sunday" do
Timecop.travel(DateTime.parse("2025-02-10").noon) do
expect(described_class.time_at_beginning_of_week).to eq(Time.zone.parse("2025-02-09").beginning_of_day)
end
end
end

context "when today is Saturday" do
it "returns the beginning of Sunday" do
Timecop.travel(DateTime.parse("2025-02-15").noon) do
expect(described_class.time_at_beginning_of_week).to eq(Time.zone.parse("2025-02-09").beginning_of_day)
end
end
end
end

context "when the first day of the week is not set but language states '1'", with_settings: { start_of_week: nil } do
before do
allow(I18n).to receive(:t).with(:general_first_day_of_week).and_return("1")
end

context "when today is Sunday" do
it "returns the beginning of the Monday" do
Timecop.travel(DateTime.parse("2025-02-16").noon) do
expect(described_class.time_at_beginning_of_week).to eq(Time.zone.parse("2025-02-10").beginning_of_day)
end
end
end

context "when today is Monday" do
it "returns the beginning of the day" do
Timecop.travel(DateTime.parse("2025-02-10").noon) do
expect(described_class.time_at_beginning_of_week).to eq(Time.zone.parse("2025-02-10").beginning_of_day)
end
end
end

context "when today is Saturday" do
it "returns the beginning of Monday" do
Timecop.travel(DateTime.parse("2025-02-15").noon) do
expect(described_class.time_at_beginning_of_week).to eq(Time.zone.parse("2025-02-10").beginning_of_day)
end
end
end
end
end
end

0 comments on commit c2c143f

Please sign in to comment.