How can I convert only an hour (Not date) in a string from UTC to localtime in flutter?

630

Solution 1

If you know the received time is in UTC and the date are "today" in UTC time, we can do something like this:

void main() {
  print(parseHoursInUtc('3:52:59 PM')); // 2021-01-21 15:52:59.000Z
}

RegExp _timePattern =
    RegExp(r'(?<hour>\d+):(?<minute>\d+):(?<second>\d+) (?<amPm>AM|PM)');

// timeString must be of the format "3:52:59 PM"
DateTime parseHoursInUtc(String timeString) {
  final match = _timePattern.firstMatch(timeString);

  final hour = int.parse(match.namedGroup('hour'));
  final minute = int.parse(match.namedGroup('minute'));
  final second = int.parse(match.namedGroup('second'));
  final isPm = match.namedGroup('amPm') == 'PM';

  final now = DateTime.now().toUtc();
  return DateTime.utc(
      now.year, now.month, now.day, isPm ? hour + 12 : hour, minute, second);
}

The methods returns a DateTime in UTC mode which you can convert to local time with toLocal().

You can then use the intl package to create a DateTimeFormat which prints the time as you want it like this:

import 'package:intl/intl.dart';

void main() {
  print(DateFormat.jms().format(parseHoursInUtc('3:52:59 PM').toLocal())); // 4:52:59 PM
}

RegExp _timePattern =
    RegExp(r'(?<hour>\d+):(?<minute>\d+):(?<second>\d+) (?<amPm>AM|PM)');

// timeString must be of the format "3:52:59 PM"
DateTime parseHoursInUtc(String timeString) {
  final match = _timePattern.firstMatch(timeString);

  final hour = int.parse(match.namedGroup('hour'));
  final minute = int.parse(match.namedGroup('minute'));
  final second = int.parse(match.namedGroup('second'));
  final isPm = match.namedGroup('amPm') == 'PM';

  final now = DateTime.now().toUtc();
  return DateTime.utc(
      now.year, now.month, now.day, isPm ? hour + 12 : hour, minute, second);
}

I am in Denmark which are CET (UTC+1) right now (and with now I mean outside DST).

Solution 2

To get the time of any date in flutter you can use:

DateFormat("hh:mm aaa").format(DateTime.now()))

result: 5:40 p.m

Share:
630
nck
Author by

nck

Android student.

Updated on December 27, 2022

Comments

  • nck
    nck over 1 year

    I am making use of an API which states the following:

    NOTE: All times are in UTC and summer time adjustments are not included in the returned data.

    So I retrieved the data as follows:

    String time = "3:52:59 PM";
    

    I want to get that time as the phone localtime, so according to a similar question for dates it would be as follows:

    final convertedTime = DateTime.parse(time).toLocal();
    print(convertedTime.toString());
    

    But this produces an error:

    Invalid date format

    I guess this issue comes because date time expects a date and not just hours, but I am not able to find anything else for just hours in import 'package:intl/intl.dart';

    How can I make this conversion, for example for GMT+1 taking into account the summertime, or any other timezone of the phone?

    In my example the expected time would be:

    String time = "4:52:59 PM";
    
    • julemand101
      julemand101 about 3 years
      If you don't have any date, what should the time be if the UTC->localtime transformation ends up on a different day? How would you handle the DST? (What I am trying to say... it seems really odd that this API does not give any date. And without any date, the concept of converting from UTC to localtime does not make any sense)
    • Matt Johnson-Pint
      Matt Johnson-Pint about 3 years
      To echo @julemand101 - You'll need a date to do this correctly. Even if you wanted to use "today" there's a chance for off-by-one errors near transitions because the current UTC date might differ from the current local date depending on time zone.
    • Matt Johnson-Pint
      Matt Johnson-Pint about 3 years
      On the string format, you can use DateTimeFormat.parse and pass true for UTC. Though you still need a date or it will default to 1970-01-01.
    • nck
      nck about 3 years
      @julemand101 I just reviewed it and the query is 'today', but is the today of the UTC time, I don't know if I can just use the 'today' of the device.
    • nck
      nck about 3 years
      @MattJohnson-Pint it crashes with the Invalid date format exception
  • Antonin GAVREL
    Antonin GAVREL almost 3 years
    That's a great answer but had some trouble as it seems the regex only works with double quote: final RegExp _timePattern = RegExp(r"(?<hour>\d+):(?<minute>\d+) (?<amPm>AM|PM)") (I didn't keep the seconds).
  • julemand101
    julemand101 almost 3 years
    @AntoninGAVREL Not sure what you are doing but it should not matter if you are using "" or '' for String in Dart unless your String itself contain " or ' (which is not the case in my answer). My guess is therefore your have made a mistake when copying by answer. If not, could you tell what error you are getting? You can read about how to represent a String in Dart here: dart.dev/guides/language/language-tour#strings
  • julemand101
    julemand101 almost 3 years
    @AntoninGAVREL One detail about the solution is that it is made before null-safety was introduced in Dart so it does not have any handling of potential null-value of match, or the result from namedGroup.
  • Antonin GAVREL
    Antonin GAVREL almost 3 years
    I know, just tell you that oddly it was not working with single quote.