Skip to content

Commit e554e89

Browse files
authored
Merge pull request #1022 from andrewnicols/MDL-81894
[docs] Document \core\clock in more places
2 parents 2cac564 + 740a36c commit e554e89

File tree

1 file changed

+112
-48
lines changed

1 file changed

+112
-48
lines changed

docs/apis/subsystems/time/index.md

Lines changed: 112 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -5,76 +5,131 @@ tags:
55
- Time
66
---
77

8-
Internally Moodle always stores all times in unixtime format (number of seconds since epoch) which is independent of timezones.
8+
Internally Moodle always stores all times in unixtime format, which is a format independent of timezones.
99

10-
The Time API is used to display proper date-time depending on user or site timezones.
10+
The Time API is then used to display the correct date and time depending on user and site timezones.
1111

12-
## Functions
12+
:::tip
1313

14-
There is a class in Moodle to handle most needs of working with times. There are 2 cases to consider when working with time:
14+
The Unix Time format is defined as the number of seconds since the Unix epoch, which began on January 1 1970 at 00:00:00 UTC.
1515

16-
System Time
16+
:::
1717

18-
This is when you are dealing with dates on the server e.g. executing scheduled tasks, performing background tasks - anything which does not depend on the timezone of any specific user.
18+
## Classifications of Time
1919

20-
User Time
20+
In Moodle there are 2 cases to consider when working with time:
2121

22-
This is when you are manipulating dates and times and you need to display them to the user in their current timezone (which may be different for each user).
22+
### System Time
2323

24-
The main API for time is in the class "core_date" which will give you php DateTimeZone objects for either user time or server time as needed. You can then use the php datetime classes to manipulate the time. When finished manipulating the time, get a timestamp with DateTime::getTimestamp().
24+
In Moodle, the term 'System Time' is used to describe dates on the server, for example times when executing scheduled tasks, performing background tasks, and so on. That is, anything which does not depend on the timezone of any specific user.
2525

26-
Example: Get the current server time + 1 day.
26+
### User Time
2727

28-
```php
29-
$tomorrow = new DateTime("1 day", core_date::get_server_timezone_object());
28+
The term 'User Time' is used for times which are user-specific. That is that they are in the user's time zone.
29+
30+
You will see these when displaying dates and times to the user in their current timezone (which may be different for each user).
31+
32+
## The Time APIs
33+
34+
The main APIs for time in Moodle are the `\core\clock` class, which allows you to fetch and manipulate the current time; and the `core_date` class, which handles PHP `DateTimeZone` objects for either user time or server time as needed. You can then use the PHP `DateTime` classes to manipulate the time. You can also fetch a timestamp with `DateTime::getTimestamp()`.
35+
36+
### Fetching and manipulating the current time
37+
38+
<Since issueNumber="MDL-80838" version="4.4" />
39+
40+
The `\core\clock` Interface was added in Moodle 4.4 and is available via [Dependency Injection](../../core/di/index.md). It provides a [clock implementation](../../core/clock/index.md) which is consistent with the [PSR-20: Clock](https://www.php-fig.org/psr/psr-20/) interfaces.
41+
42+
This is the recommended approach for fetching the current time and should be used instead of native implementations such as `time()`, and `new \DateTime();`.
43+
44+
```php title="Fetching the clock"
45+
$clock = \core\di::get(\core\clock::class);
3046
```
3147

32-
Get a timestamp for storing in the database:
48+
:::tip Why use the Clock?
3349

34-
```php
35-
$tomorrowint = $tomorrow->getTimestamp();
50+
By using the clock interface fetched via Dependency Injection, it becomes easier to test different conditions within your code. For example you can inject a custom implementation of the clock which simulates a 5 minute gap between creation of different records, and allows you to test features such as sorting.
51+
52+
You can read more on [Unit testing](../../core/clock/index.md#unit-testing) with the Clock API.
53+
54+
:::
55+
56+
The clock interface's `now()` method returns a `\DateTimeImmutable` object representing the current time:
57+
58+
```php title="Fetching the current DateTime"
59+
$now = \core\di::get(\core\clock::class)->now();
3660
```
3761

38-
Get a timestamp for 3pm tomorrow in the current users timezone.
62+
This can be further modified using the [`add`](https://www.php.net/manual/en/datetimeimmutable.add.php), [`sub`](https://www.php.net/manual/en/datetimeimmutable.sub.php), and [`modify`](https://www.php.net/manual/en/datetimeimmutable.modify.php) methods, for example:
63+
64+
```php title="Fetch the DateTime for 24 hours time"
65+
$tomorrow = \core\di::get(\core\clock::class)
66+
->now()
67+
->modify('+1 day');
68+
```
69+
70+
The Unix Timestamp can be fetched for the DateTime Object using the `getTimestamp()` method:
71+
72+
```php title="Fetching the timestamp"
73+
$tomorrow = \core\di::get(\core\clock::class)
74+
->now()
75+
->modify('+1 day')
76+
->getTimestamp();
77+
```
78+
79+
:::danger Modifying the DateTime object
80+
81+
The object returned from the `\core\clock::now()` method is an instance of `\DateTimeImmutable`.
82+
83+
Calling any of the modifier methods (`add()`, `sub()`, or `modify()`) will not modify the object, but will return a new object with the updated time.
3984

4085
```php
41-
$time = new DateTime("now", core_date::get_user_timezone_object());
42-
$time->add(new DateInterval("P1D"));
43-
$time->setTime(15, 0, 0);
86+
$today = \core\di::get(\core\clock::class)
87+
->now();
88+
89+
$tomorrow = $today->modify('+1 day');
4490

45-
$timestamp = $time->getTimestamp();
91+
$today !== $tomorrow;
4692
```
4793

48-
:::danger
49-
Never add or subtract timestamps for any reason - you will get it wrong (DST is a killer)!
5094
:::
5195

52-
Other functions related to time api can be found in lib/moodlelib.php.
96+
The `\core\time` interface also provides a helper to fetch the current Unix Timestamp in a single operation:
97+
98+
```php title="Fetching the current Unix Timestamp"
99+
$now = \core\di::get(\core\clock::class)->time();
100+
```
101+
102+
### Displaying time
103+
104+
Moodle provides a range of methods to display a Unix Timestamp in the relevant Language and Timezone.
53105

54106
1. Time API's for current user
55-
- **make_timestamp** - Given date-time, it produces a GMT timestamp for current user.
56-
- **userdate** - Gets formatted string that represents a date in user time (note that the format required by this function is the [strftime()](https://www.php.net/manual/en/function.strftime.php) format, not the more common format used by date())
57-
- **usertime** - Given a GMT timestamp (seconds since epoch), offsets it by the timezone. eg 3pm in India is 3pm GMT - 5.5 * 3600 seconds
58-
- **usergetdate** - Given a timestamp in GMT, returns an array that represents the date-time in user time
59-
- **usergetmidnight** - Given a date, return the GMT timestamp of the most recent midnight for the current user.
60-
- **usertimezone** - Returns current user's timezone
107+
- `userdate` - Given a Unix Timestamp, return a formatted string that represents a date in the user's time.
108+
109+
:::note
110+
111+
The format required by this function is the [`strftime()`](https://www.php.net/manual/en/function.strftime.php) format, not the more common format used by `date()`.
112+
113+
:::
114+
115+
- `usergetmidnight` - Given a Unix Timestamp, return the Unix Timestamp of the most recent midnight for the current user.
116+
- `usertimezone` - Return the current user's timezone
117+
- `make_timestamp` - Given date-time, it produces a Unix Timestamp for current user.
61118
1. System Time API
62-
- **format_time** - Format a date/time (seconds) as weeks, days, hours etc as needed
63-
- **dst_offset_on** - Calculates the Daylight Saving Offset for a given date/time (timestamp)
64-
- **find_day_in_month** - Calculates when the day appears in specific month
65-
- **days_in_month** - Calculate number of days in a given month
66-
- **dayofweek** - Calculate the position in the week of a specific calendar day
119+
- `format_time` - Format a date or time period in seconds as weeks, days, hours, and so on, as needed
120+
- `dst_offset_on` - Calculates the Daylight Saving Offset for a given Unix Timestamp
121+
- `find_day_in_month` - Calculates when the day appears in specific month
122+
- `days_in_month` - Calculate number of days in a given month
123+
- `dayofweek` - Calculate the position in the week of a specific calendar day
67124
1. Older legacy date/time functions. Do not use in new code.
68-
- **usertime** - Appends the users timezone offset to an integer timestamp
69-
- **get_timezone_offset** - Systems's timezone difference from GMT in seconds
70-
- **get_user_timezone_offset** - Returns user's timezone difference from GMT in hours
71-
- **dst_changes_for_year** - Calculates the required DST change and returns a Timestamp Array
125+
- `usergetdate` - Given a Unix Timestamp, returns an array that represents the date-time in user time
126+
- `usertime` - Appends the users timezone offset to an integer timestamp
72127

73128
## Glossary
74129

75130
### Timezone
76131

77-
Moodle supports following timezone formats:
132+
Moodle supports the following timezone formats:
78133

79134
1. UTC (specifically UTC−11 to UTC+11)
80135
1. Time offsets from UTC (int +-(0-13) or float +-(0.5-12.5))
@@ -90,7 +145,7 @@ DST is abbreviation of **Daylight Saving Time** (also known as "Day light saving
90145

91146
## Examples
92147

93-
### Create DateTime with date/time from a unixtime (number of seconds)
148+
### Create DateTime with date/time from a Unix Timestamp
94149

95150
```php
96151
$date = new DateTime();
@@ -103,36 +158,45 @@ echo userdate($date->getTimestamp());
103158
Prints the current date and time in the user's timezone:
104159

105160
```php
106-
$now = time();
161+
$now = \core\di::get(\core\clock::class)->time();
107162
echo userdate($now);
108163
```
109164

110165
To manually specify the display format, use one of the formatting strings defined in the <tt>core_langconfig</tt> component of the user's language. For example, to display just the date without the time, use:
111166

112167
```php
113-
echo userdate(time(), get_string('strftimedaydate', 'core_langconfig'));
168+
echo userdate(
169+
\core\di::get(\core\clock::class)->time(),
170+
get_string('strftimedaydate', 'core_langconfig'),
171+
);
114172
```
115173

116174
You can also use the <tt>DateTime</tt> class to obtain the timestamp:
117175

118176
```php
119-
$date = new DateTime("tomorrow", core_date::get_user_timezone_object());
120-
$date->setTime(0, 0, 0);
121-
echo userdate($date->getTimestamp(), get_string('strftimedatefullshort', 'core_langconfig'));
177+
$date = \core\di::get(\core\clock::class)
178+
->now()
179+
->modify('+1 day')
180+
->setTime(0, 0, 0);
181+
182+
echo userdate(
183+
$date->getTimestamp(),
184+
get_string('strftimedatefullshort', 'core_langconfig'),
185+
);
122186
```
123187

124188
### System Time API
125189

126190
Find the day of the week for the first day in this month.
127191

128192
```php
129-
$now = new DateTime("now", core_date::get_server_timezone_object());
193+
$now = \core\di::get(\core\clock::class)->now();
130194

131195
$year = $now->format('Y');
132196
$month = $now->format('m');
133197

134-
$now->setDate($year, $month, 1);
135-
$dayofweek = $now->format('N');
198+
$firstdayofmonth = $now->setDate($year, $month, 1);
199+
$dayofweek = $firstdayofmonth->format('N');
136200
echo $dayofweek;
137201
```
138202

0 commit comments

Comments
 (0)