• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

JuliaLang / julia / #38162

06 Aug 2025 08:25PM UTC coverage: 25.688% (-43.6%) from 69.336%
#38162

push

local

web-flow
fix runtime cglobal builtin function implementation (#59210)

This had failed to be updated for the LazyLibrary changes to codegen.

12976 of 50513 relevant lines covered (25.69%)

676965.51 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/stdlib/Dates/src/rounding.jl
1
# This file is a part of Julia. License is MIT: https://julialang.org/license
2

3
# The epochs used for date rounding are based ISO 8601's "year zero" notation
4
const DATEEPOCH = value(Date(0))
5
const DATETIMEEPOCH = value(DateTime(0))
6

7
# According to ISO 8601, the first day of the first week of year 0000 is 0000-01-03
8
const WEEKEPOCH = value(Date(0, 1, 3))
9

10
const ConvertiblePeriod = Union{TimePeriod, Week, Day}
11
const TimeTypeOrPeriod = Union{TimeType, ConvertiblePeriod}
12

13
"""
14
    epochdays2date(days)::Date
15

16
Take the number of days since the rounding epoch (`0000-01-01T00:00:00`) and return the
17
corresponding `Date`.
18
"""
19
epochdays2date(i) = Date(UTD(DATEEPOCH + Int64(i)))
×
20

21
"""
22
    epochms2datetime(milliseconds)::DateTime
23

24
Take the number of milliseconds since the rounding epoch (`0000-01-01T00:00:00`) and
25
return the corresponding `DateTime`.
26
"""
27
epochms2datetime(i) = DateTime(UTM(DATETIMEEPOCH + Int64(i)))
×
28

29
"""
30
    date2epochdays(dt::Date)::Int64
31

32
Take the given `Date` and return the number of days since the rounding epoch
33
(`0000-01-01T00:00:00`) as an [`Int64`](@ref).
34
"""
35
date2epochdays(dt::Date) = value(dt) - DATEEPOCH
×
36

37
"""
38
    datetime2epochms(dt::DateTime)::Int64
39

40
Take the given `DateTime` and return the number of milliseconds since the rounding epoch
41
(`0000-01-01T00:00:00`) as an [`Int64`](@ref).
42
"""
43
datetime2epochms(dt::DateTime) = value(dt) - DATETIMEEPOCH
×
44

45
function Base.floor(dt::Date, p::Year)
×
46
    value(p) < 1 && throw(DomainError(p))
×
47
    years = year(dt)
×
48
    return Date(years - mod(years, value(p)))
×
49
end
50

51
function Base.floor(dt::Date, p::Month)
×
52
    value(p) < 1 && throw(DomainError(p))
×
53
    y, m = yearmonth(dt)
×
54
    months_since_epoch = y * 12 + m - 1
×
55
    month_offset = months_since_epoch - mod(months_since_epoch, value(p))
×
56
    target_month = mod(month_offset, 12) + 1
×
57
    target_year = div(month_offset, 12) - (month_offset < 0 && target_month != 1)
×
58
    return Date(target_year, target_month)
×
59
end
60

61
function Base.floor(dt::Date, p::Quarter)
×
62
    return floor(dt, Month(p))
×
63
end
64

65

66
function Base.floor(dt::Date, p::Week)
×
67
    value(p) < 1 && throw(DomainError(p))
×
68
    days = value(dt) - WEEKEPOCH
×
69
    days = days - mod(days, value(Day(p)))
×
70
    return Date(UTD(WEEKEPOCH + Int64(days)))
×
71
end
72

73
function Base.floor(dt::Date, p::Day)
×
74
    value(p) < 1 && throw(DomainError(p))
×
75
    days = date2epochdays(dt)
×
76
    return epochdays2date(days - mod(days, value(p)))
×
77
end
78

79
Base.floor(dt::DateTime, p::DatePeriod) = DateTime(Base.floor(Date(dt), p))
×
80

81
function Base.floor(dt::DateTime, p::TimePeriod)
×
82
    value(p) < 1 && throw(DomainError(p))
×
83
    milliseconds = datetime2epochms(dt)
×
84
    return epochms2datetime(milliseconds - mod(milliseconds, value(Millisecond(p))))
×
85
end
86

87
function Base.floor(t::Time, p::TimePeriod)
×
88
    value(p) < 1 && throw(DomainError(p))
×
89
    nanoseconds = value(t)
×
90
    return Time(Nanosecond(nanoseconds - mod(nanoseconds, value(Nanosecond(p)))))
×
91
end
92

93
"""
94
    floor(x::Period, precision::T) where T <: Union{TimePeriod, Week, Day} -> T
95

96
Round `x` down to the nearest multiple of `precision`. If `x` and `precision` are different
97
subtypes of `Period`, the return value will have the same type as `precision`.
98

99
For convenience, `precision` may be a type instead of a value: `floor(x, Dates.Hour)` is a
100
shortcut for `floor(x, Dates.Hour(1))`.
101

102
```jldoctest
103
julia> floor(Day(16), Week)
104
2 weeks
105

106
julia> floor(Minute(44), Minute(15))
107
30 minutes
108

109
julia> floor(Hour(36), Day)
110
1 day
111
```
112

113
Rounding to a `precision` of `Month`s or `Year`s is not supported, as these `Period`s are of
114
inconsistent length.
115
"""
116
function Base.floor(x::ConvertiblePeriod, precision::T) where T <: ConvertiblePeriod
×
117
    value(precision) < 1 && throw(DomainError(precision))
×
118
    _x, _precision = promote(x, precision)
×
119
    return T(_x - mod(_x, _precision))
×
120
end
121

122
"""
123
    floor(dt::TimeType, p::Period)::TimeType
124

125
Return the nearest `Date` or `DateTime` less than or equal to `dt` at resolution `p`.
126

127
For convenience, `p` may be a type instead of a value: `floor(dt, Dates.Hour)` is a shortcut
128
for `floor(dt, Dates.Hour(1))`.
129

130
```jldoctest
131
julia> floor(Date(1985, 8, 16), Month)
132
1985-08-01
133

134
julia> floor(DateTime(2013, 2, 13, 0, 31, 20), Minute(15))
135
2013-02-13T00:30:00
136

137
julia> floor(DateTime(2016, 8, 6, 12, 0, 0), Day)
138
2016-08-06T00:00:00
139
```
140
"""
141
Base.floor(::Dates.TimeType, ::Dates.Period)
142

143
"""
144
    ceil(dt::TimeType, p::Period)::TimeType
145

146
Return the nearest `Date` or `DateTime` greater than or equal to `dt` at resolution `p`.
147

148
For convenience, `p` may be a type instead of a value: `ceil(dt, Dates.Hour)` is a shortcut
149
for `ceil(dt, Dates.Hour(1))`.
150

151
```jldoctest
152
julia> ceil(Date(1985, 8, 16), Month)
153
1985-09-01
154

155
julia> ceil(DateTime(2013, 2, 13, 0, 31, 20), Minute(15))
156
2013-02-13T00:45:00
157

158
julia> ceil(DateTime(2016, 8, 6, 12, 0, 0), Day)
159
2016-08-07T00:00:00
160
```
161
"""
162
function Base.ceil(dt::TimeType, p::Period)
×
163
    f = floor(dt, p)
×
164
    return (dt == f) ? f : f + p
×
165
end
166

167
"""
168
    ceil(x::Period, precision::T) where T <: Union{TimePeriod, Week, Day} -> T
169

170
Round `x` up to the nearest multiple of `precision`. If `x` and `precision` are different
171
subtypes of `Period`, the return value will have the same type as `precision`.
172

173
For convenience, `precision` may be a type instead of a value: `ceil(x, Dates.Hour)` is a
174
shortcut for `ceil(x, Dates.Hour(1))`.
175

176
```jldoctest
177
julia> ceil(Day(16), Week)
178
3 weeks
179

180
julia> ceil(Minute(44), Minute(15))
181
45 minutes
182

183
julia> ceil(Hour(36), Day)
184
2 days
185
```
186

187
Rounding to a `precision` of `Month`s or `Year`s is not supported, as these `Period`s are of
188
inconsistent length.
189
"""
190
function Base.ceil(x::ConvertiblePeriod, precision::ConvertiblePeriod)
×
191
    f = floor(x, precision)
×
192
    return (x == f) ? f : f + precision
×
193
end
194

195
"""
196
    floorceil(dt::TimeType, p::Period) -> (TimeType, TimeType)
197

198
Simultaneously return the `floor` and `ceil` of a `Date` or `DateTime` at resolution `p`.
199
More efficient than calling both `floor` and `ceil` individually.
200
"""
201
function floorceil(dt::TimeType, p::Period)
×
202
    f = floor(dt, p)
×
203
    return f, (dt == f) ? f : f + p
×
204
end
205

206
"""
207
    floorceil(x::Period, precision::T) where T <: Union{TimePeriod, Week, Day} -> (T, T)
208

209
Simultaneously return the `floor` and `ceil` of `Period` at resolution `p`.  More efficient
210
than calling both `floor` and `ceil` individually.
211
"""
212
function floorceil(x::ConvertiblePeriod, precision::ConvertiblePeriod)
213
    f = floor(x, precision)
×
214
    return f, (x == f) ? f : f + precision
×
215
end
216

217
"""
218
    round(dt::TimeType, p::Period, [r::RoundingMode]) -> TimeType
219

220
Return the `Date` or `DateTime` nearest to `dt` at resolution `p`. By default
221
(`RoundNearestTiesUp`), ties (e.g., rounding 9:30 to the nearest hour) will be rounded up.
222

223
For convenience, `p` may be a type instead of a value: `round(dt, Dates.Hour)` is a shortcut
224
for `round(dt, Dates.Hour(1))`.
225

226
```jldoctest
227
julia> round(Date(1985, 8, 16), Month)
228
1985-08-01
229

230
julia> round(DateTime(2013, 2, 13, 0, 31, 20), Minute(15))
231
2013-02-13T00:30:00
232

233
julia> round(DateTime(2016, 8, 6, 12, 0, 0), Day)
234
2016-08-07T00:00:00
235
```
236

237
Valid rounding modes for `round(::TimeType, ::Period, ::RoundingMode)` are
238
`RoundNearestTiesUp` (default), `RoundDown` (`floor`), and `RoundUp` (`ceil`).
239
"""
240
function Base.round(dt::TimeType, p::Period, r::RoundingMode{:NearestTiesUp})
×
241
    f, c = floorceil(dt, p)
×
242
    return (dt - f) < (c - dt) ? f : c
×
243
end
244

245
"""
246
    round(x::Period, precision::T, [r::RoundingMode]) where T <: Union{TimePeriod, Week, Day} -> T
247

248
Round `x` to the nearest multiple of `precision`. If `x` and `precision` are different
249
subtypes of `Period`, the return value will have the same type as `precision`. By default
250
(`RoundNearestTiesUp`), ties (e.g., rounding 90 minutes to the nearest hour) will be rounded
251
up.
252

253
For convenience, `precision` may be a type instead of a value: `round(x, Dates.Hour)` is a
254
shortcut for `round(x, Dates.Hour(1))`.
255

256
```jldoctest
257
julia> round(Day(16), Week)
258
2 weeks
259

260
julia> round(Minute(44), Minute(15))
261
45 minutes
262

263
julia> round(Hour(36), Day)
264
2 days
265
```
266

267
Valid rounding modes for `round(::Period, ::T, ::RoundingMode)` are `RoundNearestTiesUp`
268
(default), `RoundDown` (`floor`), and `RoundUp` (`ceil`).
269

270
Rounding to a `precision` of `Month`s or `Year`s is not supported, as these `Period`s are of
271
inconsistent length.
272
"""
273
function Base.round(x::ConvertiblePeriod, precision::ConvertiblePeriod, r::RoundingMode{:NearestTiesUp})
274
    f, c = floorceil(x, precision)
×
275
    _x, _f, _c = promote(x, f, c)
×
276
    return (_x - _f) < (_c - _x) ? f : c
×
277
end
278

279
Base.round(x::TimeTypeOrPeriod, p::Period, r::RoundingMode{:Down}) = Base.floor(x, p)
×
280
Base.round(x::TimeTypeOrPeriod, p::Period, r::RoundingMode{:Up}) = Base.ceil(x, p)
×
281

282
# No implementation of other `RoundingMode`s: rounding to nearest "even" is skipped because
283
# "even" is not defined for Period; rounding toward/away from zero is skipped because ISO
284
# 8601's year 0000 is not really "zero".
285
Base.round(::TimeTypeOrPeriod, p::Period, ::RoundingMode) = throw(DomainError(p))
×
286

287
# Default to RoundNearestTiesUp.
288
Base.round(x::TimeTypeOrPeriod, p::Period) = Base.round(x, p, RoundNearestTiesUp)
×
289

290
# Make rounding functions callable using Period types in addition to values.
291
Base.floor(x::TimeTypeOrPeriod, ::Type{P}) where P <: Period = Base.floor(x, oneunit(P))
×
292
Base.ceil(x::TimeTypeOrPeriod, ::Type{P}) where P <: Period = Base.ceil(x, oneunit(P))
×
293
Base.floor(::Type{Date}, x::TimeTypeOrPeriod, ::Type{P}) where P <: Period = Base.floor(Date(x), oneunit(P))
×
294
Base.ceil(::Type{Date}, x::TimeTypeOrPeriod, ::Type{P}) where P <: Period = Base.ceil(Date(x), oneunit(P))
×
295

296
function Base.round(x::TimeTypeOrPeriod, ::Type{P}, r::RoundingMode=RoundNearestTiesUp) where P <: Period
297
    return Base.round(x, oneunit(P), r)
×
298
end
299

300
function Base.round(::Type{Date}, x::TimeTypeOrPeriod, ::Type{P}, r::RoundingMode=RoundNearestTiesUp) where P <: Period
×
301
    return Base.round(Date(x), oneunit(P), r)
×
302
end
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc