-
-
Save apgapg/84d855e41c0134a34ff8b2cf034ad249 to your computer and use it in GitHub Desktop.
import 'package:intl/intl.dart'; | |
import 'package:meta/meta.dart'; | |
void main() { | |
print(DateUtils.formatISOTime(DateTime.now())); | |
print(DateUtils.getCurrentISOTimeString()); | |
} | |
class DateUtils { | |
///Converts DateTime to ISO format | |
///Output: 2020-09-16T20:41:09.331+05:30 | |
static String formatISOTime(DateTime date) { | |
var duration = date.timeZoneOffset; | |
if (duration.isNegative) | |
return (date.toIso8601String() + | |
"-${duration.inHours.toString().padLeft(2, '0')}:${(duration.inMinutes - (duration.inHours * 60)).toString().padLeft(2, '0')}"); | |
else | |
return (date.toIso8601String() + | |
"+${duration.inHours.toString().padLeft(2, '0')}:${(duration.inMinutes - (duration.inHours * 60)).toString().padLeft(2, '0')}"); | |
} | |
///get ISO time String from DateTime | |
///Output: 2020-09-16T20:42:38.629+05:30 | |
static String getCurrentISOTimeString({DateTime dateTime}) { | |
var date = dateTime ?? DateTime.now(); | |
//Time zone may be null in dateTime hence get timezone by datetime | |
var duration = DateTime.now().timeZoneOffset; | |
if (duration.isNegative) | |
//TODO: convert duration to abs value instead of below params | |
return (date.toIso8601String() + | |
"-${duration.inHours.abs().toString().padLeft(2, '0')}:${(duration.inMinutes.abs() - (duration.inHours.abs() * 60)).toString().padLeft(2, '0')}"); | |
else | |
return (date.toIso8601String() + | |
"+${duration.inHours.toString().padLeft(2, '0')}:${(duration.inMinutes - (duration.inHours * 60)).toString().padLeft(2, '0')}"); | |
} | |
} | |
Fixed the double offset issue:
static String formatISOTime(DateTime date) {
final iso = date.toIso8601String();
if (iso.endsWith("Z")) {
return iso;
}
var duration = date.timeZoneOffset;
if (duration.isNegative)
return (iso +
"-${duration.inHours.toString().padLeft(2, '0')}:${(duration.inMinutes - (duration.inHours * 60)).toString().padLeft(2, '0')}");
else
return (iso +
"+${duration.inHours.toString().padLeft(2, '0')}:${(duration.inMinutes - (duration.inHours * 60)).toString().padLeft(2, '0')}");
}
@gazialankus thanks for sharing but I wonder if date.toIso8601String
could return a time offset other that Z?
I personally adopted a slightly different approach by building the whole iso string part by part, so that we don't depend on something that could potentially break.
String getIsoDatetime(DateTime date) {
// make date string without offset
final month = date.month.toString().padLeft(2, '0');
final day = date.day.toString().padLeft(2, '0');
final hour = date.hour.toString().padLeft(2, '0');
final minute = date.minute.toString().padLeft(2, '0');
final second = date.second.toString().padLeft(2, '0');
final datetimeString =
'${date.year}-${month}-${day}T${hour}:${minute}:${second}.000';
// make offset string
final duration = date.timeZoneOffset;
final offsetHours = duration.inHours.abs().toString().padLeft(2, '0');
final offsetMinutes =
(duration.inMinutes.abs() - (duration.inHours.abs() * 60))
.toString()
.padLeft(2, '0');
final offsetString = "$offsetHours:$offsetMinutes";
// offset positive/negative
if (duration.isNegative)
return datetimeString + "-" + offsetString;
else
return datetimeString + "+" + offsetString;
;
}
It worked well so far that way,
DateTime says it's either Z or no Z, but yeah maybe it could change one day. https://api.dart.dev/stable/2.10.4/dart-core/DateTime/toIso8601String.html
@gsouf thank you for sharing your solution. It's nice to have an alternative if things fail.
Thank you for sharing.
I did few changes on it:
class DateUtils {
///Converts DateTime to ISO format
///Output: 2020-09-16T20:41:09.331+05:30
static String formatISOTime(DateTime date) {
var duration = date.timeZoneOffset;
return "${date.toIso8601String().replaceAll('Z', '')}${duration.isNegative ? "-" : "+"}${_formatTimeZoneOffsetISO(duration)}";
}
static String _formatTimeZoneOffsetISO(Duration duration) {
duration = duration.abs();
return "${duration.inHours.toString().padLeft(2, '0')}:${(duration.inMinutes - (duration.inHours * 60)).toString().padLeft(2, '0')}";
}
///get ISO time String from DateTime
///Output: 2020-09-16T20:42:38.629+05:30
static String getCurrentISOTimeString({DateTime? dateTime}) {
return formatISOTime(DateTime.now());
}
}
You have a big bug there, please remove the negative logic.
If you are in a timezone that is negative you will have double minus
/// converts [date] into into string format
/// Example:
/// * Positive: (UK) `2020-09-16T11:55:01.802248+00:00`
/// * Negative: (Canada) `2020-09-16T11:55:01.802248-08:00`
static String formatISOTime(DateTime date) {
var duration = date.timeZoneOffset;
/// If the user is in Canada the time zone is GMT-8 then the signal will need to be negative.
/// Because we already get the minus from the hours in the string then we don't need to add it to the string.
/// In the case the timezone is GMT-0 or higher then the sign will need to be positive.
var timezoneSignal = !(duration.isNegative) ? '+' : '';
var dateString = (date.toIso8601String() + "${timezoneSignal}${duration.inHours.toString().padLeft(2, '0')}:${(duration.inMinutes - (duration.inHours * 60)).toString().padLeft(2, '0')}");
return dateString;
}
@loonix, the code will not have a double minus if it's using the absolute value of the duration (.abs()), but your suggestion would also work.
Be aware that it will fail when the given datetime was parsed from an iso string with offset:
That's because now dart will return the date with a trailing
Z
for zero offset.So it will end up with 2 offsets specified in the final string:
That cannot be parsed back: