Home > Back-end >  Why is `DateTime.add(const Duration(days: 1)` adding *Seconds* instead of Days?
Why is `DateTime.add(const Duration(days: 1)` adding *Seconds* instead of Days?

Time:03-30

I have a Text() widget that displays a DateTime as a String. This Text() widget is wrapped with a GestureDetecture() where the onTap should update the DateTime by one day:

GestureDetector(
            child: File2(
              dateTime: date,
              key: Key(date.toString()),
            ),
            onTap: () {
              setState(() {
                // This is adding seconds not days
                date = date.add(const Duration(days: 1));
              });
            },
          ),

However, the date is not updating by one day although I'm doing:

date = date.add(const Duration(days: 1));

It is however updating by a few seconds. Why isn't it updating by 1 day?

What I tried: Using a Key()

Code:

file_1.dart:

import 'package:flutter/material.dart';

import 'file_2.dart';

void main() {
  runApp(File1());
}

class File1 extends StatefulWidget {
  const File1({Key? key}) : super(key: key);

  @override
  State<File1> createState() => _File1State();
}

class _File1State extends State<File1> {
  @override
  Widget build(BuildContext context) {
    DateTime date = DateTime.now();

    return MaterialApp(
      home: Scaffold(
        body: Center(
          child: GestureDetector(
            child: File2(
              dateTime: date,
              key: Key(date.toString()),
            ),
            onTap: () {
              setState(() {
                // This is adding seconds not days
                date = date.add(const Duration(days: 1));
              });
            },
          ),
        ),
      ),
    );
  }
}

file_2.dart:

import 'package:flutter/material.dart';

class File2 extends StatelessWidget {
  DateTime dateTime;
  File2({Key? key, required this.dateTime}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Text(dateTime.toString());
  }
}
  • How can I update the Text() in File2 by 1 day when clicking on the GestureDetector()?

  • Do I need to use a statemanagement other then setState()?

CodePudding user response:

Problem

This error occurs simply because you have this line at the beginning of the build method: DateTime date = DateTime.now();.

This is the workflow of what is happening in your code:

  1. You set the date value to DateTime.now() at the beginning of the build method.
  2. This current date value is rendered in your UI.
  3. You trigger the function to update your date.
  4. 1 day is added to the date.
  5. IMPORTANT: Step 4 triggers the rebuild of your widget, hence Step 1 is executed again.

As a result of Step 5, the date value just gets updated for a moment, but then the DateTime.now() is rendered in UI.

Solution

Initiate the date value in your State class and not in the build method. This way, your date value won't be overwritten by the Widget rebuild:

class _File1State extends State<File1> {
  DateTime date = DateTime.now(); // <-- Initiate the value here
  
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: Center(
          child: GestureDetector(
            child: File2(
              dateTime: date,
              key: Key(date.toString()),
            ),
            onTap: () {
              setState(() {
                // This is adding seconds not days
                date = date.add(const Duration(days: 1));
              });
            },
          ),
        ),
      ),
    );
  }
}
  • Related