106

I have a value stored in variable of type System.TimeSpan as follows.

System.TimeSpan storedTime = 03:00:00;

Can I re-store it in another variable of type String as follows?

String displayValue = "03:00 AM";

And if storedTime variable has the value of

storedTime = 16:00:00;

then it should be converted to:

String displayValue = "04:00 PM";
Konrad Viltersten
  • 36,151
  • 76
  • 250
  • 438
Amit Kumar
  • 1,367
  • 3
  • 13
  • 24

13 Answers13

226

You can do this by adding your timespan to the date.

TimeSpan timespan = new TimeSpan(03,00,00);
DateTime time = DateTime.Today.Add(timespan);
string displayTime = time.ToString("hh:mm tt"); // It will give "03:00 AM"
JDub
  • 114
  • 1
  • 8
Asif Mushtaq
  • 13,010
  • 3
  • 33
  • 42
  • is it possible to add a default time from [this](http://stackoverflow.com/questions/21104633/how-to-add-date-picker-bootstrap-3-on-mvc-5-project-using-the-razor-engine) bootstrap date picker eg: `datepicker value + TimeofDay` ? – Shaiju T Mar 21 '15 at 15:04
  • 2
    Note that this will *always* give the [12-hour clock](https://en.wikipedia.org/wiki/12-hour_clock) time with an AM/PM prefix. If you want the result to follow a given culture, you can use `ShortTimePattern` instead: `string displayTime = time.ToString("t" [, culture]);` – Sphinxxx Jun 26 '15 at 19:56
  • 3
    Or you can just call `time.ToShortTimeString()` – Mardok Aug 28 '15 at 07:32
  • time.ToShortTimeString() does not maintain the preceding 0 in 03:00 PM. time.ToString("hh:mm tt") takes care of it – Souvik Basu Apr 18 '16 at 07:21
  • I want TimeSpan without any date, maybe doesn't matter but you bind today date and it's not proper, Using like string.Format(@"{0:hh\:mm\:ss}", timespan) is better but I don't know how to add AM/PM to that :( – QMaster Dec 04 '16 at 11:54
  • @QMaster you cannot add AM/PM to a `TimeSpan`. I'm afraid you'll anyway have to associate the `TimaSpan` value with `DateTime`. – Curiosity Oct 18 '17 at 05:37
  • @Curiousity What is the reason of that disability? Time as I know has 24 hours and 1:00 PM is bigger as 12 hours than 1:00 AM, Can you please more describe? – QMaster Oct 18 '17 at 21:18
  • @QMaster I added an answer [here](https://stackoverflow.com/a/46822847/7196681) because it needed a bit of describing. Hope it answers your question. – Curiosity Oct 19 '17 at 04:31
  • Yes... A timespan is an interval of time... defined as hours, minutes, and seconds (or ticks) since midnight. You combine it with a date and get a full datetime. – douglas.kirschman Feb 22 '19 at 16:17
17

Very simple by using the string format

on .ToSTring("") :

  • if you use "hh" ->> The hour, using a 12-hour clock from 01 to 12.

  • if you use "HH" ->> The hour, using a 24-hour clock from 00 to 23.

  • if you add "tt" ->> The Am/Pm designator.

exemple converting from 23:12 to 11:12 Pm :

DateTime d = new DateTime(1, 1, 1, 23, 12, 0);
var res = d.ToString("hh:mm tt");   // this show  11:12 Pm
var res2 = d.ToString("HH:mm");  // this show  23:12

Console.WriteLine(res);
Console.WriteLine(res2);

Console.Read();

wait a second, there is a catch, the system Culture !!, the same code executed on windows set to different language especially with different culture language will generate different result.

for example in windows set to Arabic language the result Will be like this :

// 23:12 م

م means Evening (first letter of مساء) .

in windows set to German language i think it will show // 23:12 du.

you can change between different format on windows control panel under windows regional and language -> current format (combobox) and change... apply it, do a rebuild (execute) of your app and watch what i'm talking about.

so how can you force showing Am and Pm prefix in English event if the culture of the current system isn't set to English ?

easy just by adding two lines ->

the first step add using System.Globalization; on top of your code

and modify the previous code to be like this :

DateTime d = new DateTime(1, 1, 1, 23, 12, 0);
var res = d.ToString("HH:mm tt", CultureInfo.InvariantCulture); // this show  11:12 Pm

InvariantCulture => using default English Format.

another question I want to have the pm to be in Arabic or specific language, even if I use windows set to English (or other language) regional format?

Solution for Arabic Exemple :

DateTime d = new DateTime(1, 1, 1, 23, 12, 0);
var res = d.ToString("HH:mm tt", CultureInfo.CreateSpecificCulture("ar-AE")); 

this will show // 23:12 م

event if my system is set to English region format. you can change "ar-AE" if you want to another language format. there is a list for each language.

exemples : ar ar-SA Arabic ar-BH ar-BH Arabic (Bahrain) ar-DZ ar-DZ Arabic (Algeria) ar-EG ar-EG Arabic (Egypt) .....

Bilal
  • 1,254
  • 13
  • 14
14

You can add the TimeSpan to a DateTime, for example:

TimeSpan span = TimeSpan.FromHours(16);
DateTime time = DateTime.Today + span;
String result = time.ToString("hh:mm tt");

Demo: http://ideone.com/veJ6tT

04:00 PM

Standard Date and Time Format Strings

Tim Schmelter
  • 450,073
  • 74
  • 686
  • 939
  • thank you, after hours i tried for `11:57 pm` and this worked: `TimeSpan time = new TimeSpan(23, 57, 00); DateTime date_with_time = mydate.Add(time);` – Shaiju T Sep 01 '15 at 08:59
12

Doing some piggybacking off existing answers here:

public static string ToShortTimeSafe(this TimeSpan timeSpan)
{
    return new DateTime().Add(timeSpan).ToShortTimeString();
} 

public static string ToShortTimeSafe(this TimeSpan? timeSpan)
{
    return timeSpan == null ? string.Empty : timeSpan.Value.ToShortTimeSafe();
}
Chris Marisic
  • 32,487
  • 24
  • 164
  • 258
11
string displayValue="03:00 AM";

This is a point in time , not a duration (TimeSpan).

So something is wrong with your basic design or assumptions.

If you do want to use it, you'll have to convert it to a DateTime (point in time) first. You can format a DateTime without the date part, that would be your desired string.

TimeSpan t1 = ...;
DateTime d1 = DateTime.Today + t1;               // any date will do
string result = d1.ToString("hh:mm:ss tt");

storeTime variable can have value like
storeTime=16:00:00;

No, it can have a value of 4 o'clock but the representation is binary, a TimeSpan cannot record the difference between 16:00 and 4 pm.

H H
  • 263,252
  • 30
  • 330
  • 514
  • 11
    It's unfortunate that `DateTime.TimeOfDay` returns a `TimeSpan` - Microsoft leads you to this design :( – Jon Skeet Oct 24 '12 at 07:35
  • 2
    @JonSkeet I don't know that it's the worst design (and I know you're a wonk on the matter, respectfully, given your work on Noda), it's a matter of understanding the limitations of the interpretation. There's no concept of a relative `DateTime`, if there was, then this ("03:00 AM") would simply be an instance of that. However, I can see that for the majority of use cases, that design (a relative `DateTime`) would overcomplicate the issues (of course, this is at the expense of making it more complicated for doing very specific work around dates, times, absolute or not, timezones, etc.) – casperOne Oct 24 '12 at 11:43
  • 7
    @casperOne: Fundamentally it's using one type to represent information which would logically be stored in a different type, just because if you squint hard enough they look similar. I wouldn't suggest overloading the meaning of `DateTime` even *further* (it's already bad enough). There should be a type representing a "time of day" - which is, of course, exactly what I've implemented in Noda Time. Whenever you try to stuff lots of different concepts into a small number of types, you're bound to get problems like this. – Jon Skeet Oct 24 '12 at 11:47
  • 1
    This answer is great because it explains *why* TimeSpan behaves the way it does, rather than just how to fix the problem. Really there should be three types: `DateTime`, `TimeOfDay` and `Date`. – thelem Jun 07 '18 at 08:59
  • `03:00 AM` is not a "point in time". It's a "point in a day". – Alex from Jitbit May 23 '19 at 12:11
10

You will need to get a DateTime object from your TimeSpan and then you can format it easily.

One possible solution is adding the timespan to any date with zero time value.

var timespan = new TimeSpan(3, 0, 0);
var output = new DateTime().Add(timespan).ToString("hh:mm tt");

The output value will be "03:00 AM" (for english locale).

Michal Klouda
  • 14,263
  • 7
  • 53
  • 77
6

You cannot add AM / PM to a TimeSpan. You'll anyway have to associate the TimaSpan value with DateTime if you want to display the time in 12-hour clock format.

TimeSpan is not intended to use with a 12-hour clock format, because we are talking about a time interval here.

As it says in the documentation;

A TimeSpan object represents a time interval (duration of time or elapsed time) that is measured as a positive or negative number of days, hours, minutes, seconds, and fractions of a second. The TimeSpan structure can also be used to represent the time of day, but only if the time is unrelated to a particular date. Otherwise, the DateTime or DateTimeOffset structure should be used instead.

Also Microsoft Docs describes as follows;

A TimeSpan value can be represented as [-]d.hh:mm:ss.ff, where the optional minus sign indicates a negative time interval, the d component is days, hh is hours as measured on a 24-hour clock, mm is minutes, ss is seconds, and ff is fractions of a second.

So in this case, you can display using AM/PM as follows.

TimeSpan storedTime = new TimeSpan(03,00,00);
string displayValue = new DateTime().Add(storedTime).ToString("hh:mm tt");


Side note :
Also should note that the TimeOfDay property of DateTime is a TimeSpan, where it represents

a time interval that represents the fraction of the day that has elapsed since midnight.

Curiosity
  • 1,753
  • 3
  • 25
  • 46
5

To avoid timespan format limitations, convert to datetime. Simplest expression would be:

// Where value is a TimeSpan...
(new DateTime() + value).ToString("hh:mm tt");
Thomas Phaneuf
  • 306
  • 4
  • 9
3

Parse timespan to DateTime and then use Format ("hh:mm:tt"). For example.

TimeSpan ts = new TimeSpan(16, 00, 00);
DateTime dtTemp = DateTime.ParseExact(ts.ToString(), "HH:mm:ss", CultureInfo.InvariantCulture);
string str = dtTemp.ToString("hh:mm tt");

str will be:

str = "04:00 PM"
Habib
  • 219,104
  • 29
  • 407
  • 436
2

You can try this:

   string timeexample= string.Format("{0:hh:mm:ss tt}", DateTime.Now);

you can remove hh or mm or ss or tt according your need where hh is hour in 12 hr formate, mm is minutes,ss is seconds,and tt is AM/PM.

Ankit
  • 1,094
  • 11
  • 23
1
Parse timespan to DateTime. For Example.    
//The time will be "8.30 AM" or "10.00 PM" or any time like this format.
    public TimeSpan GetTimeSpanValue(string displayValue) 
        {   
            DateTime dateTime = DateTime.Now;
                if (displayValue.StartsWith("10") || displayValue.StartsWith("11") || displayValue.StartsWith("12"))
                          dateTime = DateTime.ParseExact(displayValue, "hh:mm tt", CultureInfo.InvariantCulture);
                    else
                          dateTime = DateTime.ParseExact(displayValue, "h:mm tt", CultureInfo.InvariantCulture);
                    return dateTime.TimeOfDay;
                }
Nandha kumar
  • 693
  • 7
  • 15
0

At first, you need to convert time span to DateTime structure:

var dt = new DateTime(2000, 12, 1, timeSpan.Hours, timeSpan.Minutes, timeSpan.Seconds)

Then you need to convert the value to string with Short Time format

var result = dt.ToString("t"); // Convert to string using Short Time format
STO
  • 10,390
  • 8
  • 32
  • 32
0

Because this situation is as annoying as it is common... I created a helper class, which I have released in a NuGet package. This could be a private method and can be used in MVC views as well as in back-end C# code.

public static string AsTimeOfDay(TimeSpan timeSpan, TimeSpanFormat timeSpanFormat = TimeSpanFormat.AmPm)
        {
            int hours = timeSpan.Hours;
            int minutes = timeSpan.Minutes;
            string AmOrPm = "AM";
            string returnValue = string.Empty;

            if (timeSpanFormat == TimeSpanFormat.AmPm)
            {
                if (hours >= 12)
                {
                    AmOrPm = "PM";
                }

                if (hours > 12)
                {
                    hours -= 12;
                }

                TimeSpan timeSpanAmPm = new TimeSpan(hours, minutes, 0);

                returnValue = timeSpanAmPm.ToString(@"h\:mm") + " " + AmOrPm;
            }
            else
            {
                returnValue = timeSpan.ToString(@"h\:mm");
            }

            return returnValue;
        }

enter image description here

Corey Jensen
  • 359
  • 2
  • 6