0

I wanted to create a readonly struct that represents time in 24-hour format, so it has a method that is supposed to return a string of time (for example: "08:45" if 8 and 45 were passed respectively or "03:40" if 25 hours and 160 minutes were passed)

The problem is in the method, how do I return a string with values from the object inserted into it? I imagined something like return "0{stringtimeobj.hours}:0{stringtimeobj.minutes} but I can't really figure out how to format a string so that it has values from an object in it. Please help out!

using System;

namespace TimeStruct
{
    public readonly struct Time
{
        private readonly int hours2;
        private readonly int minutes2;

        public Time(int minutes)
            : this()
        {
            this.minutes2 = minutes;
        }

        public Time(int hours, int minutes)
        {
            this.hours2 = hours;
            this.minutes2 = minutes;
            }

        public int Hours
        {
            get
            {
                if (this.hours2 < 24)
                {
                    return this.minutes2;
                }
                else if (this.hours2 == 24)
                {
                    return 0;
                }
                else
                {
                    double overflowtohours = ((Math.Truncate((double)this.minutes2 / 60) + 1) * 60) - 60;
                    return Convert.ToInt32(this.hours2 - ((Math.Truncate((double)(Convert.ToInt32(overflowtohours / 60) + this.hours2) / 24) + 1) * 24) - 24);
                }
            }
        }

        public int Minutes
        {
            get
            {
                if (this.minutes2 < 60)
                {
                    return this.minutes2;
                }
                else if (this.minutes2 == 60)
                {
                    return 0;
                }
                else
                {
                    double overflowtohours = ((Math.Truncate((double)this.minutes2 / 60) + 1) * 60) - 60;
                    return Convert.ToInt32(this.minutes2 - overflowtohours); 
                }
            }
        }

        public string ToString(int hours3, int minutes3)
        {
            Time stringtimeobj = new Time(hours3, minutes3);
            return /* string "00:00" with hour and minute values from object stringtimeobj inserted */
        }
    }
}
5
  • 2
    Why is your ToString parameterized? Normally you'd have a parameterless method that uses the data in the object you're calling it on. Commented Jul 17, 2022 at 14:59
  • Tip: look up the % (modulo) operator Commented Jul 17, 2022 at 15:18
  • Tip: someInt. ToString("00") will add leading zero as needed Commented Jul 17, 2022 at 15:19
  • @JonSkeet I thought that method needed to be passed parameters, then these parameters are used in the constructor when new object is created, does that make sense? I can't really think of another way to implement the method Commented Jul 17, 2022 at 17:44
  • No, it's an instance method - it has to be called on an existing object, which means that's the value you should be formatting. So you'd call new Time(5, 10).ToString() for example - and that should format 5 hours and 10 minutes. Commented Jul 18, 2022 at 6:39

5 Answers 5

3

You just need this implementation of your struct:

public readonly struct Time
{
    private readonly int _minutes;

    public Time(int minutes) : this(0, minutes) { }

    public Time(int hours, int minutes)
    {
        _minutes = (hours * 60 + minutes) % (24 * 60);
    }

    public int Hours => _minutes / 60;
    public int Minutes => _minutes % 60;
    public override string ToString() => $"{this.Hours:00}:{this.Minutes:00}";
}

When I run this code:

Console.WriteLine(new Time(8, 45).ToString());
Console.WriteLine(new Time(25, 160).ToString());

I get the following output:

08:45
03:40
Sign up to request clarification or add additional context in comments.

9 Comments

This implementation looks so much better, but I am still unsure on how to inject values from a new object into a string format. Is that even possible? Something like return $"Object value1: {newobj.value1} Object value2: {newobj.value2}" No matter how much I search I can't find examples of code that does something similar to that or any explanations regarding it.
Another thing, how did you use/call the constructor without creating a new object? Was the constructor called automatically when the struct was created?
@Akzhol You seem to have the idea: $"Text: {obj.Value}" is the way to go.
@Akzhol - I don't know what you mean by "call the constructor without creating a new object". I did create a new object.
I thought objects need to be created with new or base, so where or how did you create it there? Sorry if I am annoying.
|
1

You can implement the standard ToString method like this:

public override string ToString()
{
   return $"{this.Hours:00}:{this.Minutes:00}";
}

or equivalent:

public override string ToString()
{
   return String.Format("{0:00}:{1:00}", this.Hours, this.Minutes);
}
  • The override keyword is required because you override the default ToString method
  • It doesn't need parameters, because it reads the local properties (this.Minutes and this.Hours - you can omit the "this."). Plus the standard ToString doesn't take parameters
  • The first one uses an interpolated string, the second example uses String.Format
  • In both cases the :00 means "format as two digits, adding leading 0's as needed" (docs)
  • Bonus: the debugger will use this method to display the value of this type

Comments

0

You can use built-in DateTime.ToString() with custom format. In your case it would look like:

int hour = 2;
int minute = 1;

DateTime time = new DateTime(2000, 1, 1, hour, minute, 0);

Console.WriteLine(time.ToString("HH:mm")); // 02:01

3 Comments

I assume this would make returning the string easier, but I am not sure how to implement this in my method. I think I still need to make use of the constructor to change fields by making a new object of Time class, and then I would need to pass hour and minute values from that object when creating DateTime? So would it look something like DateTime time = new DateTime(2000, 1, 1, stringtimeobj.hour, stringtimeobj.minute, 0); return time.ToString("HH:mm") Would that work? Sorry if it doesn't make sense, I am still figuring it out
This is a dangerous approach as it does not allow for your input of 25 hours and 160 minutes.
@Enigmativity This is just a method to convert already calculated hour and minute to required string.
0

Yep , you can use it like this way below

DateTime time = new DateTime(2000, 1, 1, stringtimeobj.Hours,stringtimeobj.Minutes, 0);  
return time.ToString("HH:mm");

Comments

-2

We need to do some checking. If "stringtimeobj.hours" is greater than 9, which is 10 to 24, then "{stringtimeobj.hours}" can be used.

Also, if "stringTimeobj.minutes" is greater than 9, that is, 10 to 60, then "{stringtimeobj.minutes}" can be used.

Something like that.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.