6

I want to write a simple stopwatch program, I can make it work with the following code

    public Form1()
    {
        InitializeComponent();
    }
    System.Diagnostics.Stopwatch ss = new System.Diagnostics.Stopwatch { };
    private void button1_Click(object sender, EventArgs e)
    {
        if (button1.Text == "Start")
        {
            button1.Text = "Stop";

            ss.Start();
            timer1.Enabled = true;

        }
        else
        {
            button1.Text = "Start";

            ss.Stop();
            timer1.Enabled = false;

        }
    }

    private void timer1_Tick(object sender, EventArgs e)
    {


            int hrs = ss.Elapsed.Hours, mins = ss.Elapsed.Minutes, secs = ss.Elapsed.Seconds;
            label1.Text = hrs + ":";
            if (mins < 10)
                label1.Text += "0" + mins + ":";
            else
                label1.Text += mins + ":";
            if (secs < 10)
                label1.Text += "0" + secs;
            else
                label1.Text += secs;


    }

    private void button2_Click(object sender, EventArgs e)
    {
        ss.Reset();
       button1.Text= "Start";
       timer1.Enabled = true;

    }

Now I want to set a custom start time for this stopwatch, for example I want it not to begin count up from 0:00:00 but to start with 0:45:00 How can I do it, thank you.

Kyle Dam
  • 63
  • 1
  • 1
  • 3

5 Answers5

21

Stopwatch does not have any methods or properties that would allow you to set a custom start time.

You can subclass Stopwatch and override ElapsedMilliseconds and ElapsedTicks to adjust for your start time offset.

    public class MyStopwatch : Stopwatch
    {
        public TimeSpan StartOffset { get; private set; }

        public MyStopwatch(TimeSpan startOffset)
        {
            StartOffset = startOffset;
        }

        public new long ElapsedMilliseconds
        {
            get
            {
                return base.ElapsedMilliseconds + (long)StartOffset.TotalMilliseconds;
            }
        }

        public new long ElapsedTicks
        {
            get
            {
                return base.ElapsedTicks + StartOffset.Ticks;
            }
        }
    }
Eric J.
  • 147,927
  • 63
  • 340
  • 553
  • 1
    Sounds like a lot of code just to be able to offset the timer. I think adding an offset at the time when the value of the stopwatch needs to be displayed is a better approach. If reuse is important add the code as extension method (http://msdn.microsoft.com/en-us/library/bb383977.aspx). – Taras Alenin Jul 27 '12 at 04:59
  • 5
    @BigT: Really? A lot of code? I posted an implementation. It might be slightly longer than your extension method, but it encapsulates the desired behavior. And it's *really* not a lot of code. And it solves the original question. – Eric J. Jul 27 '12 at 05:21
  • 2
    Note that properties are not overridden, but hidden using _new_ keyword. It means that they will only be used only if your variable type is exactly MyStopwatch. E.g. if you decide to store it in List then you will end up end up accessing original Stopwatch type properties and getting value without offset. – Seraphim Jan 30 '18 at 15:58
6

Create a new instance of System.TimeSpan with the initial value of 45 minutes as per you example. Than add the value of the stopwatch to it TimeSpan.Add Method. Conveniently the Stopwatch.Elapsed is of type System.TimeSpan already.

Than use string formatter to print the formatted time into the label. I think one of the other answers already shows how to do that. Otherwise here are some good references on how to format a TimeSpan instance TimeSpan.ToString Method (String) or using a custom formatter.

var offsetTimeSpan = new System.TimeSpan(0,45,0).Add(ss.Elapsed)
Taras Alenin
  • 8,094
  • 4
  • 40
  • 32
1
  • additional SetOffset() method
  • additional initialization with offset;
  • overrides all of needed methods
  • have the same class name, so no need to change your project code

.

using System;

public class Stopwatch : System.Diagnostics.Stopwatch
{
    TimeSpan _offset = new TimeSpan();

    public Stopwatch()
    {
    }

    public Stopwatch(TimeSpan offset)
    {
        _offset = offset;
    }

    public void SetOffset(TimeSpan offsetElapsedTimeSpan)
    {
        _offset = offsetElapsedTimeSpan;
    }

    public TimeSpan Elapsed
    {
        get{ return base.Elapsed + _offset; }
        set{ _offset = value; }
    }

    public long ElapsedMilliseconds
    {
        get { return base.ElapsedMilliseconds + _offset.Milliseconds; }
    }

    public long ElapsedTicks
    {
        get { return base.ElapsedTicks + _offset.Ticks; }
    }
}
Andrew_STOP_RU_WAR_IN_UA
  • 9,318
  • 5
  • 65
  • 101
0

You can't alter the start time, but you can modify it after the Stop() and no one is the wiser.

A quick Google search: http://msdn.microsoft.com/en-us/library/system.diagnostics.stopwatch.start(v=vs.90).aspx

A minor modification:

class Program
{
    static void Main(string[] args)
    {            
        System.Diagnostics.Stopwatch stopWatch = new System.Diagnostics.Stopwatch();
        
        stopWatch.Start();
        Thread.Sleep(10000);
        stopWatch.Stop();
        // Get the elapsed time as a TimeSpan value.
        TimeSpan ts = stopWatch.Elapsed;
        
        // Format and display the TimeSpan value.
        string elapsedTime = String.Format("{0:00}:{1:00}:{2:00}.{3:00}",
            ts.Hours, ts.Minutes + 45 , ts.Seconds,
            ts.Milliseconds / 10);
        Console.WriteLine("RunTime " + elapsedTime);
    }
}

Result:

RunTime 00:45:10.00

Press any key to continue . . .

A little more research on your part will help you immeasurably as a developer.

Community
  • 1
  • 1
GrayFox374
  • 1,742
  • 9
  • 13
  • The math should be done using the Add function built into TimeSpan. This code will fail often. Any time the stopwatch has minutes >= 15 then the time format is invalid. – DAG Mar 05 '21 at 21:35
0

is the offset fixed or variable?

In either case, have it as some member variable or const for the class and just add it.

private TimeSpan offset = TimeSpan.FromSeconds(45);

Then just change your tick to include it:

var combined = ss.Elapsed + offset;
int hrs = combined.Hours, mins = combined.Minutes, secs = combined.Seconds;
James Manning
  • 13,429
  • 2
  • 40
  • 64