Skip to content

Instantly share code, notes, and snippets.

@PlugFox
Last active March 20, 2025 15:54
Show Gist options
  • Save PlugFox/a94be8655b2adb91336f03bc77513d76 to your computer and use it in GitHub Desktop.
Save PlugFox/a94be8655b2adb91336f03bc77513d76 to your computer and use it in GitHub Desktop.
DateTime to int, Date and Time extension
// ignore_for_file: avoid_print
/*
* Date <==> Int conversion
* https://gist.github.com/PlugFox/a94be8655b2adb91336f03bc77513d76
* https://dartpad.dev?id=a94be8655b2adb91336f03bc77513d76
* Mike Matiunin <[email protected]>, 20 March 2025
*/
/// Date extension type
extension type const Date._(DateTime _date) implements DateTime {
/// Create Date from [year], [month] and [day]
Date(int year, int month, int day) : _date = DateTime.utc(year, month, day);
/// Get current Date
factory Date.now() => Date.of(DateTime.now());
/// Create Date from [date]
factory Date.of(DateTime date) {
final DateTime(:year, :month, :day) = date.toUtc();
return Date(year, month, day);
}
/// Create Date from [value]
Date.value(int value)
: _date = DateTime.utc(
value >> 9, // year (12 bit)
(value >> 5) & 0xF, // month (4 bit)
value & 0x1F, // day (5 bit)
);
/// Get Date as value
int get value =>
(_date.year << 9) | // YYYYYYYYYYYY (0–4095)
(_date.month << 5) | // MMMM (1–12)
_date.day; // DDDDD (1–31)
/// Get Date as representation YYYY-MM-DD
String get representation =>
'${year.toString().padLeft(4, '0')}-'
'${month.toString().padLeft(2, '0')}-'
'${day.toString().padLeft(2, '0')}';
}
/// Time extension type
extension type const Time._(DateTime _time) implements DateTime {
/// Create Time from [hour], [minute] and [second]
Time(int hour, int minute, int second)
: _time = DateTime.utc(0, 1, 1, hour, minute, second);
/// Get current time
factory Time.now() => Time.of(DateTime.now());
/// Create Time from [time]
factory Time.of(DateTime time) {
final DateTime(:hour, :minute, :second) = time.toUtc();
return Time(second, minute, second);
}
/// Create Date from [value]
Time.value(int value)
: _time = DateTime.utc(
0,
1,
1,
(value >> 12) & 0x1F, // Hours (5 bit)
(value >> 6) & 0x3F, // Minutes (6 bit)
value & 0x3F, // Seconds (6 bit)
);
/// Get Time as value
int get value =>
(_time.hour << 12) | // HHHHH (0–23)
(_time.minute << 6) | // MMMMMM (0–59)
_time.second; // SSSSSS (0–59)
/// Get Date as representation HH:MM:SS
String get representation =>
'${hour.toString().padLeft(2, '0')}:'
'${minute.toString().padLeft(2, '0')}:'
'${second.toString().padLeft(2, '0')}';
}
void main() {
void expect(DateTime a, DateTime b) {
final $a = a.millisecondsSinceEpoch, $b = b.millisecondsSinceEpoch;
if ($a == $b) return;
throw Exception('${a.toUtc()} != ${b.toUtc()}');
}
final dates = [
DateTime.utc(0),
DateTime.utc(2021, 1, 1),
DateTime.utc(2024, 10, 10),
DateTime.utc(5000, 12, 30),
];
for (final dt in dates) {
final date = DateTime.utc(dt.year, dt.month, dt.day);
// Check conversion date to value and back
expect(Date.value(Date.of(date).value), date);
print('$date => ${Date.of(dt).value}');
// Check how compact is the value
final DateTime(:year, :month, :day) = dt;
final text = [
year,
month,
day,
].map((e) => e.toString().padLeft(2, '0')).join('');
if (text.length < Date.of(dt).value.toString().length) {
throw Exception('$text is more compact than ${Date.of(dt).value}');
}
}
// 5 Mar. 2025
print(Date.of(DateTime.utc(2025, 03, 05)).value); // 1036901
print(Date.value(1036901).representation); // 5 Mar. 2025
// 12:34:56
print(Time.of(DateTime.utc(0, 0, 0, 12, 34, 56)).value); // 51384
print(Time.value(51384).representation); // 12:34:56
}
@arxdeus
Copy link

arxdeus commented Mar 19, 2025

problem with years in web
image

@PlugFox
Copy link
Author

PlugFox commented Mar 20, 2025

problem with years in web image

I'll take a look

@PlugFox
Copy link
Author

PlugFox commented Mar 20, 2025

@arxdeus it's unsafe to use conversion to DateTime with seconds at web.
Because its int limited to value 2^53 – 1.
We should not include seconds in that conversion or store time separately from the date.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment