How To Create A World Clock App in Flutter

Introduction

Creating a World Clock app in flutter may seem like a complex task at first. But in this article we will learn how to we can make a world clock app using HTTP GET request, If you’re interested only in the source code it will be linked at the bottom of the post otherwise I recommend you to follow along. Now let us begin.

Features

  • Ability to view the current time for a number of countries.
  • Utilizes the API of WorldTimeAPI to fetch time data according to user input.
  • The background corresponds to the current time it will be a sunny background during day time and a dark background during night time.

Project Setup

From your command line navigate to your code repository folder and type the following command
flutter create world_time_app

Now create the following folders in your “world_time_app” directory.

world_time_app/
├── assets/
│   └── flags/
│       [Flag image files go here]
├── lib/
│   ├── pages/
│   │   ├── choose_location.dart
│   │   ├── home.dart
│   │   └── loading.dart
│   └── utilities/
│       └── world_time.dart

Next go to your pubspec.yaml file and paste the following configuration inside.

name: world_time_app
description: A new Flutter project.

publish_to: 'none'

version: 1.0.0+1

environment:
  sdk: '>=3.1.1 <4.0.0'


dependencies:
  cupertino_icons: ^1.0.2
  flutter:
    sdk: flutter
  flutter_spinkit: ^5.2.0
  http: ^1.1.0
  intl: ^0.18.1

dev_dependencies:
  flutter_lints: ^2.0.0
  flutter_test:
    sdk: flutter


flutter:

  uses-material-design: true
  assets:
  - assets/
  - assets/flags/

Packages Used

PackagePurpose
flutter_spinkit:^5.2.0To add page loading animations
http:^1.1.0For HTTP requests
intl:^0.18.1For Internationalized/Localized messages, Formats etc (In case you need it)

Creating The World Clock App

Now that our project setup is complete, let’s begin the development process.

main.dart

First of all go to your main.dart file and paste the following code.

import 'package:flutter/material.dart';
import 'package:world_time_app/pages/choose_location.dart';
import 'package:world_time_app/pages/home.dart';
import 'package:world_time_app/pages/loading.dart';

void main() {
  runApp(MaterialApp(
    initialRoute: '/',
    routes: {
      '/': (context) => const Loading(),
      '/home': (context) => const Home(),
      '/location': (context) => const ChooseLocation(),
    },
  ));
}

Explanation

  • First we import the required packages and classes (The classes we created in the “pages” folder).
  • Then the runApp method is called and routes are initialized with initial route being the Loading screen.

world_time.dart

Next go to your world_time.dart file and add the following lines of code.

// ignore_for_file: avoid_print
import 'package:http/http.dart';
import 'dart:convert';

class WorldTimeApi {
  // Location Name For The UI
  String location;

  // The Time In The Location
  late String time;

  // Flag Asset Icon URL
  String flag;

  // Location API Endpoint URL
  String url;

  // To Indicate If To Display Sunny Or Dark Background Image
  late bool isDayTime;

  WorldTimeApi({required this.location, required this.flag, required this.url});

  Future<void> getTime() async {
    try {
      // Make The API Request
      Response response =
          await get(Uri.parse('http://worldtimeapi.org/api/timezone/$url'));

      // Map The Data
      Map data = jsonDecode(response.body);

      print(data);

      // Get Properties From Data
      String dateTime = data['datetime'];

      String timeStorage = await extractTime(dateTime);

      // Check For Day / Night
      isDayTime = await checkForTime(timeStorage);

      // Set Time
      time = timeStorage;
    } catch (e, stackTrace) {
      print('[ERROR] $e \nStackTrace: \n\n\n$stackTrace'); 
      time = '[ERROR] Unable To Fetch Time Data';
    }
  }

  Future<String> extractTime(String timeData) async {
    return timeData.substring(11, 16);
  }

  Future<bool> checkForTime(String timeStorage) async {
    int timeNow = int.parse(timeStorage.substring(0, 2));
    print(timeNow);
    return (timeNow > 6 && timeNow < 20 ? true : false);
  }
}

Explanation

  • WorldTimeApi is a model class that contains the properties and methods related to the data that will be fetched from the worldtimeapi.org website.
  • This class is also responsible for fetching and parsing the data returned by the HTTP request and then passed on to the calling function.
  • This class also handles the logic for displaying Day or Night backgrounds and the proper flag associated with the selected region on our frontend.

loading.dart

Now go to your loading.dart file and paste the following code.

// ignore_for_file: use_build_context_synchronously

import 'package:flutter/material.dart';
import 'package:world_time_app/utilities/world_time.dart';
import 'package:flutter_spinkit/flutter_spinkit.dart';

class Loading extends StatefulWidget {
  const Loading({super.key});

  @override
  State<Loading> createState() => _LoadingState();
}

class _LoadingState extends State<Loading> {
  void setupWorldTime() async {
    // Create the WorldTimeApi instance
    WorldTimeApi instance =  WorldTimeApi(location: 'Karachi', flag: 'pakistan.png', url: 'Asia/Karachi');
    await instance.getTime();

    // Redirect To Home Page
    Navigator.pushReplacementNamed(context, '/home',arguments: {
      'location': instance.location,
      'flag': instance.flag,
      'time': instance.time,
      'isDayTime' : instance.isDayTime,
    });
  }

  @override
  void initState() {
    super.initState();
    setupWorldTime();
  }

  // Loading Screen
  @override
  Widget build(BuildContext context) {
    return const Scaffold(
      backgroundColor: Color(0xFF000000),
      body: Center(
        child: SpinKitCubeGrid(color: Colors.white,
        size: 50,
        )
      ),
    );
  }
}

Explanation

  • This is our loading screen and also the point where we create our WorldTimeApi instance to fetch data from the server.
  • We also create our home page here and pass the data to it.

home.dart

Go to your home.dart file and paste the following code

import 'package:flutter/material.dart';

class Home extends StatefulWidget {
  const Home({super.key});

  @override
  State<Home> createState() => _HomeState();
}

class _HomeState extends State<Home> {
  // Data property that will hold information sent by WorldTimeApi request
  Map<dynamic, dynamic> data = {};

  @override
  Widget build(BuildContext context) {

    // If data is not empty use the data otherwise assign the value of passed arguments
    data = data.isNotEmpty ?  data : ModalRoute.of(context)!.settings.arguments as Map;

    //print(data);

    // Set Background
    String bgImage = data["isDayTime"] ? "day.png" : "night.png";
    Color bgColor = data["isDayTime"] ? Colors.blue : Colors.indigo[700]!;


    // Build the UI
    return Scaffold(
      backgroundColor: bgColor,
      body: SafeArea(
          child: Container(
            decoration: BoxDecoration(
              image: DecorationImage(
                image: AssetImage('assets/$bgImage'),
                fit: BoxFit.cover,
                ),
            ),
            child: Padding(
                  padding: const EdgeInsets.fromLTRB(0.0, 120, 0, 0),
                  child: Column(
            children: [
              TextButton.icon(
                onPressed: (() async {
                  dynamic result = await Navigator.pushNamed(context, '/location');

                  setState(() {
                    data = {
                      'location' : result["location"],
                      'flag' : result["flag"],
                      'time' : result["time"],
                      'isDayTime' : result["isDayTime"],
                    };
                  });
                }),
                icon: Icon(
                  Icons.edit_location,
                  color: Colors.grey[300],
                  ),
                label: Text(
                  'Edit Location',
                  style: TextStyle(
                    color: Colors.grey[300],
                  ),
                ),
              ),
              const SizedBox(height: 20.0),
              Image(image:AssetImage('assets/flags/${data['flag']}'),
              ),
              Row(
                mainAxisAlignment: MainAxisAlignment.center,
                children: [
                  Text(
                    data['location'],
                    style: const TextStyle(
                      color: Colors.white,
                      fontSize: 28.0,
                      letterSpacing: 2.0,
                    ),
                  ),
                ],
              ),
              const SizedBox(
                height: 20.0,
              ),
              Text(
                data['time'],
                style: const TextStyle(
                  color: Colors.white,
                  fontSize: 66.0,
                ),
              ),
            ],
                  ),
                ),
          )),
    );
  }
}

Explanation

  • This is the home page for our “World Time Clock App”.
  • This is the class which will build our UI elements.

Output

home.dart output

choose_location.dart

Go to your choose_location.dart file and paste the following lines of code

import 'package:flutter/material.dart';
import 'package:world_time_app/utilities/world_time.dart';

class ChooseLocation extends StatefulWidget {
  const ChooseLocation({super.key});

  @override
  State<ChooseLocation> createState() => _ChooseLocationState();
}

class _ChooseLocationState extends State<ChooseLocation> {
// List of Locations
List<WorldTimeApi> locations = [
  WorldTimeApi(url: 'Europe/London', location: 'London', flag: 'uk.png'),
  WorldTimeApi(url: 'Europe/Athens', location: 'Athens', flag: 'greece.png'),
  WorldTimeApi(url: 'Africa/Cairo', location: 'Cairo', flag: 'egypt.png'),
  WorldTimeApi(url: 'Africa/Nairobi', location: 'Nairobi', flag: 'kenya.png'),
  WorldTimeApi(url: 'America/Chicago', location: 'Chicago', flag: 'us.png'),
  WorldTimeApi(url: 'America/New_York', location: 'New York', flag: 'us.png'),
  WorldTimeApi(url: 'Asia/Seoul', location: 'Seoul', flag: 'sk.png'),
  WorldTimeApi(url: 'Asia/Jakarta', location: 'Jakarta', flag: 'indonesia.png'),
  WorldTimeApi(url: 'Asia/Karachi', location: 'Karachi', flag: 'pakistan.png'),
  WorldTimeApi(url: 'Asia/Baghdad', location: 'Baghdad', flag: 'iraq.png'),
];

  @override
  void initState() {
    super.initState();
  }

  void updateTime(int index) async{
    // Create WorldTimeApi Instance
    WorldTimeApi locationInstance = locations[index];
    await locationInstance.getTime();

    // Close this page and send data back to home page
    Navigator.pop(context, {
      'location': locationInstance.location,
      'flag': locationInstance.flag,
      'time': locationInstance.time,
      'isDayTime' : locationInstance.isDayTime,
    });
  }
    

    // Build UI
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.grey[200],
      appBar: AppBar(
        backgroundColor: Colors.blue[900],
        title: Text('Choose a Location'),
        centerTitle: true,
        elevation: 0,
      ),
      body: ListView.builder(
        itemCount: locations.length,
        itemBuilder: (context,index){
          return Padding(
            padding: const EdgeInsets.symmetric(vertical: 1.0,horizontal: 4.0),
            child: Card(
              child: ListTile(
                onTap: ()=>{
                  updateTime(index),
                },
                title: Text(
                  locations[index].location
                ),
                leading: Image(
                  image: AssetImage('assets/flags/${locations[index].flag}'),
                ),
              )
            ),
          );
        },
        ),
    );
  }
}

Explanation

  • This class is responsible for rendering the time selection menu for different locations around the world.
  • Furthermore when a location is selected the WorldTimeApi instance is created again and the data is fetched from the server according to the location selected by the user.

Output

choose_location,.dart output

World Clock App In Action

Source Code

Visit the Github Repository to download the source code.

Conclusion

In this tutorial we learned how to create a World Clock App in Flutter framework using the worldtimeapi.org API. Utilizing the API we also learned how to build our UI from the data we fetched and we also learned how we can implement a selection menu screen so we can choose between different locations. For more Flutter articles visit the Flutter Archives.