Skip to content

Commit d76f69b

Browse files
authored
Merge pull request #4116 from nextcloud/enh/dateTime-handling
Use locale code instead of language code for luxon
2 parents 18995f0 + 485391e commit d76f69b

8 files changed

Lines changed: 35 additions & 47 deletions

File tree

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ All notable changes to this project will be documented in this file.
99
## [8.0.1] - 2025-06-22
1010
### Fix
1111
- Fixed display of the list view mode
12+
- Use locale instead of language for date and time representation
13+
- Fixed representation of time interval when adding a date option with a duration
1214

1315
## [8.0.0] - 2025-06-22
1416
### Changes

lib/Model/UserBase.php

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,7 @@ public function getLanguageCode(): string {
168168
}
169169

170170
public function getLanguageCodeIntl(): string {
171-
return str_replace('_', '-', $this->languageCode);
171+
return str_replace('_', '-', $this->getLanguageCode());
172172
}
173173

174174
public function getLocaleCode(): string {
@@ -179,6 +179,10 @@ public function getLocaleCode(): string {
179179
return $this->localeCode;
180180
}
181181

182+
public function getLocaleCodeIntl(): string {
183+
return str_replace('_', '-', $this->getLocaleCode());
184+
}
185+
182186
public function getTimeZone(): DateTimeZone {
183187
if ($this->timeZoneName) {
184188
return new DateTimeZone($this->timeZoneName);
@@ -329,6 +333,7 @@ public function getRichUserArray(): array {
329333
'languageCode' => $this->getLanguageCode(),
330334
'languageCodeIntl' => $this->getLanguageCodeIntl(),
331335
'localeCode' => $this->getLocaleCode(),
336+
'localeCodeIntl' => $this->getLocaleCodeIntl(),
332337
'organisation' => $this->getOrganisation(),
333338
'subname' => $this->getSubName(),
334339
'subtitle' => $this->getDescription(),

src/Types/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,7 @@ export type User = {
166166
languageCode: string
167167
languageCodeIntl: string
168168
localeCode: string | null
169+
localeCodeIntl: string | null
169170
timeZone: string | null
170171
categories: string[] | null
171172
}

src/components/Base/modules/DateBox.vue

Lines changed: 15 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -6,65 +6,54 @@
66
<script setup lang="ts">
77
import { computed } from 'vue'
88
import { DateTime, Duration, Interval } from 'luxon'
9-
import { useSessionStore } from '../../../stores/session.ts'
109
1110
interface Props {
1211
dateTime: DateTime
1312
duration?: Duration
1413
}
15-
const { dateTime: luxonDate, duration: luxonDuration = Duration.fromMillis(0) } =
16-
defineProps<Props>()
14+
const { dateTime, duration = Duration.fromMillis(0) } = defineProps<Props>()
1715
18-
const from = computed(() =>
19-
luxonDate.setLocale(sessionStore.currentUser.languageCodeIntl),
20-
)
21-
22-
const sessionStore = useSessionStore()
2316
// the dates span one or more entire days
2417
// do not display the time in this case
2518
const allDay = computed(
2619
() =>
27-
from.value.startOf('day').toSeconds() === from.value.toSeconds()
28-
&& luxonDuration.as('seconds') % 86400 === 0,
20+
dateTime.startOf('day').toSeconds() === dateTime.toSeconds()
21+
&& duration.as('seconds') % 86400 === 0,
2922
)
3023
3124
// 'to' is 'from' plus the duration
3225
// subtract a day if allDay is true and luxonDuration is greater than 0 to match the
3326
// end of the day after the duration instead of the beginning of the next day
3427
const to = computed(() =>
35-
from.value
36-
.plus(luxonDuration)
37-
.minus({ day: allDay.value && luxonDuration.as('seconds') > 0 ? 1 : 0 }),
28+
dateTime
29+
.plus(duration)
30+
.minus({ day: allDay.value && duration.as('seconds') > 0 ? 1 : 0 }),
3831
)
3932
4033
// to and from dates have the same month (and year)
4134
// suppress the 'to' month if they are the same
4235
const isSameMonth = computed(
43-
() => from.value.month === to.value.month && from.value.year === to.value.year,
36+
() => dateTime.month === to.value.month && dateTime.year === to.value.year,
4437
)
4538
4639
// to and from dates have the same day (in the same month and year)
4740
// suppress the 'to' day if they are the same
4841
// display the interval as timespan inside the same day
49-
const isSameDay = computed(
50-
() => from.value.day === to.value.day && isSameMonth.value,
51-
)
42+
const isSameDay = computed(() => dateTime.day === to.value.day && isSameMonth.value)
5243
5344
// Shortcut: 'to' and 'from' are identical
5445
// suppress the 'to' time if they are the same
55-
const isSameTime = computed(() => luxonDuration.as('seconds') === 0)
46+
const isSameTime = computed(() => duration.as('seconds') === 0)
5647
57-
const interval = computed(() =>
58-
Interval.fromDateTimes(from.value.toUTC(), to.value.toUTC()),
59-
)
48+
const interval = computed(() => Interval.fromDateTimes(dateTime, to.value))
6049
</script>
6150

6251
<template>
6352
<div :title="interval.toISO()" class="datebox">
6453
<div class="month from" :class="{ span: isSameMonth }">
6554
{{
66-
from.toLocaleString(
67-
DateTime.now().year === from.year
55+
dateTime.toLocaleString(
56+
DateTime.now().year === dateTime.year
6857
? { month: 'short' }
6958
: { month: 'short', year: '2-digit' },
7059
)
@@ -74,15 +63,15 @@ const interval = computed(() =>
7463
<div v-if="!isSameMonth" class="month to">
7564
{{
7665
to.toLocaleString(
77-
DateTime.now().year === from.year
66+
DateTime.now().year === dateTime.year
7867
? { month: 'short' }
7968
: { month: 'short', year: '2-digit' },
8069
)
8170
}}
8271
</div>
8372

8473
<div class="day from" :class="{ span: isSameDay }">
85-
{{ from.toLocaleString({ weekday: 'short', day: 'numeric' }) }}
74+
{{ dateTime.toLocaleString({ weekday: 'short', day: 'numeric' }) }}
8675
</div>
8776

8877
<span v-if="!isSameDay" class="day divider">–</span>
@@ -95,7 +84,7 @@ const interval = computed(() =>
9584
{{
9685
isSameDay && !isSameTime
9786
? interval.toLocaleString(DateTime.TIME_SIMPLE)
98-
: from.toLocaleString(DateTime.TIME_SIMPLE)
87+
: dateTime.toLocaleString(DateTime.TIME_SIMPLE)
9988
}}
10089
</div>
10190

src/components/Export/ExportPoll.vue

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@ import { Answer, AnswerSymbol, useVotesStore } from '../../stores/votes.ts'
2929
import { Option, useOptionsStore } from '../../stores/options.ts'
3030
import { AxiosError } from '@nextcloud/axios'
3131
import { DateTime, Interval } from 'luxon'
32-
import { useSessionStore } from '../../stores/session.ts'
3332
3433
enum ArrayStyle {
3534
Symbols = 'symbols',
@@ -48,7 +47,6 @@ const route = useRoute()
4847
const pollStore = usePollStore()
4948
const votesStore = useVotesStore()
5049
const optionsStore = useOptionsStore()
51-
const sessionStore = useSessionStore()
5250
5351
const regex = /[:\\/?*[\]]/g
5452
@@ -211,9 +209,9 @@ function getIntervalRaw(option: Option): string {
211209
* @param option - option
212210
*/
213211
function getFromFormatted(option: Option): string {
214-
return DateTime.fromSeconds(option.timestamp)
215-
.setLocale(sessionStore.currentUser.languageCodeIntl)
216-
.toLocaleString(DateTime.DATETIME_MED_WITH_WEEKDAY)
212+
return DateTime.fromSeconds(option.timestamp).toLocaleString(
213+
DateTime.DATETIME_MED_WITH_WEEKDAY,
214+
)
217215
}
218216
219217
/**
@@ -222,7 +220,6 @@ function getFromFormatted(option: Option): string {
222220
*/
223221
function getToFormatted(option: Option): string {
224222
return DateTime.fromSeconds(option.timestamp)
225-
.setLocale(sessionStore.currentUser.languageCodeIntl)
226223
.plus({ seconds: option.duration })
227224
.toLocaleString(DateTime.DATETIME_MED_WITH_WEEKDAY)
228225
}

src/components/Options/OptionItemDateBox.vue

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,22 +5,17 @@
55

66
<script setup lang="ts">
77
import { DateTime, Duration } from 'luxon'
8-
import { useSessionStore } from '../../stores/session.ts'
98
import DateBox from '../Base/modules/DateBox.vue'
109
1110
interface Props {
1211
timeStamp: number
1312
durationSeconds?: number
1413
}
1514
16-
const sessionStore = useSessionStore()
17-
1815
const { timeStamp, durationSeconds = 0 } = defineProps<Props>()
1916
2017
// computed from as DateTime from Luxon
21-
const from = DateTime.fromSeconds(timeStamp).setLocale(
22-
sessionStore.currentUser.languageCodeIntl,
23-
)
18+
const from = DateTime.fromSeconds(timeStamp)
2419
2520
const duration = Duration.fromMillis(durationSeconds * 1000)
2621
</script>

src/components/Options/OptionsDateAddDialog.vue

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ import CheckIcon from 'vue-material-design-icons/Check.vue'
1515
1616
import { InputDiv } from '../Base/index.ts'
1717
import DateTimePicker from '../Base/modules/DateTimePicker.vue'
18-
import { useSessionStore } from '../../stores/session'
1918
import { useOptionsStore, Sequence } from '../../stores/options'
2019
import { StatusResults } from '../../Types'
2120
import { DurationType, dateTimeUnitsKeyed } from '../../constants/dateUnits.ts'
@@ -28,7 +27,6 @@ import DateBox from '../Base/modules/DateBox.vue'
2827
2928
const { isBelowWidthOffset } = useResizeObserver('add-date-options-container', 355)
3029
31-
const sessionStore = useSessionStore()
3230
const optionsStore = useOptionsStore()
3331
3432
const timeStepMinutes = 15
@@ -85,14 +83,10 @@ const dateTimeOptionsFiltered = computed(() => {
8583
8684
// computed from as DateTime from Luxon
8785
const from = computed(() => {
88-
const dateFrom = DateTime.fromJSDate(fromInput.value).setLocale(
89-
sessionStore.currentUser.languageCodeIntl,
90-
)
86+
const dateFrom = DateTime.fromJSDate(fromInput.value)
9187
// if the option is an all day option, the time is set to 00:00
9288
if (allDay.value) {
93-
return dateFrom
94-
.startOf('day')
95-
.setLocale(sessionStore.currentUser.languageCodeIntl)
89+
return dateFrom.startOf('day')
9690
}
9791
return dateFrom
9892
})

src/composables/context.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,18 @@ import { RouteLocationNormalized } from 'vue-router'
77
import { useSessionStore } from '../stores/session.ts'
88
import { usePreferencesStore } from '../stores/preferences.ts'
99
import { Logger } from '../helpers/index.ts'
10+
import { Settings } from 'luxon'
1011

1112
async function loadContext(to: RouteLocationNormalized) {
1213
const sessionStore = useSessionStore()
1314
const preferencesStore = usePreferencesStore()
1415

1516
await sessionStore.load(to)
1617

18+
Settings.defaultLocale =
19+
sessionStore.currentUser.localeCodeIntl
20+
|| sessionStore.currentUser.languageCodeIntl
21+
1722
if (sessionStore.userStatus.isLoggedin) {
1823
await preferencesStore.load()
1924
}

0 commit comments

Comments
 (0)