1 // SPDX-License-Identifier: LGPL-2.0+
2 /* Copyright (C) 1993, 1994, 1995, 1996, 1997 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
4 Contributed by Paul Eggert (eggert@twinsun.com). */
7 * dgb 10/02/98: ripped this from glibc source to help convert timestamps
9 * 10/04/98: added new table-based lookup after seeing how ugly
11 * blf 09/27/99: ripped out all the old code and inserted new table from
12 * John Brockmeyer (without leap second corrections)
13 * rewrote udf_stamp_to_time and fixed timezone accounting in
18 * We don't take into account leap seconds. This may be correct or incorrect.
19 * For more NIST information (especially dealing with leap seconds), see:
20 * http://www.boulder.nist.gov/timefreq/pubs/bulletin/leapsecond.htm
25 #include <linux/types.h>
26 #include <linux/kernel.h>
27 #include <linux/time.h>
30 udf_disk_stamp_to_time(struct timespec64
*dest
, struct timestamp src
)
32 u16 typeAndTimezone
= le16_to_cpu(src
.typeAndTimezone
);
33 u16 year
= le16_to_cpu(src
.year
);
34 uint8_t type
= typeAndTimezone
>> 12;
38 offset
= typeAndTimezone
<< 4;
39 /* sign extent offset */
40 offset
= (offset
>> 4);
41 if (offset
== -2047) /* unspecified offset */
46 dest
->tv_sec
= mktime64(year
, src
.month
, src
.day
, src
.hour
, src
.minute
,
48 dest
->tv_sec
-= offset
* 60;
51 * Sanitize nanosecond field since reportedly some filesystems are
52 * recorded with bogus sub-second values.
54 if (src
.centiseconds
< 100 && src
.hundredsOfMicroseconds
< 100 &&
55 src
.microseconds
< 100) {
56 dest
->tv_nsec
= 1000 * (src
.centiseconds
* 10000 +
57 src
.hundredsOfMicroseconds
* 100 + src
.microseconds
);
64 udf_time_to_disk_stamp(struct timestamp
*dest
, struct timespec64 ts
)
70 offset
= -sys_tz
.tz_minuteswest
;
72 dest
->typeAndTimezone
= cpu_to_le16(0x1000 | (offset
& 0x0FFF));
74 seconds
= ts
.tv_sec
+ offset
* 60;
75 time64_to_tm(seconds
, 0, &tm
);
76 dest
->year
= cpu_to_le16(tm
.tm_year
+ 1900);
77 dest
->month
= tm
.tm_mon
+ 1;
78 dest
->day
= tm
.tm_mday
;
79 dest
->hour
= tm
.tm_hour
;
80 dest
->minute
= tm
.tm_min
;
81 dest
->second
= tm
.tm_sec
;
82 dest
->centiseconds
= ts
.tv_nsec
/ 10000000;
83 dest
->hundredsOfMicroseconds
= (ts
.tv_nsec
/ 1000 -
84 dest
->centiseconds
* 10000) / 100;
85 dest
->microseconds
= (ts
.tv_nsec
/ 1000 - dest
->centiseconds
* 10000 -
86 dest
->hundredsOfMicroseconds
* 100);