C#
time conversion
string formatting
datetime
programming

Convert time span value to format hhmm Am/Pm using C

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

TimeSpan in C# represents a duration (e.g., 14 hours and 30 minutes), not a time of day, so it has no concept of AM/PM. To format a TimeSpan as "hh:mm AM/PM", convert it to a DateTime first by adding the TimeSpan to DateTime.Today (which is midnight). Then use DateTime.ToString("hh:mm tt") where hh is the 12-hour clock and tt is the AM/PM designator.

Basic Conversion

csharp
1TimeSpan timeSpan = new TimeSpan(14, 30, 0);  // 14:30:00 (2:30 PM)
2
3// Add TimeSpan to midnight to get a DateTime
4DateTime dateTime = DateTime.Today.Add(timeSpan);
5
6// Format with AM/PM
7string formatted = dateTime.ToString("hh:mm tt");
8Console.WriteLine(formatted);  // "02:30 PM"

DateTime.Today returns today's date at 00:00:00. Adding a TimeSpan of 14:30 gives a DateTime of today at 14:30, which formats as "02:30 PM".

Format Specifiers

csharp
1TimeSpan ts = new TimeSpan(9, 5, 30);  // 9:05:30 AM
2
3DateTime dt = DateTime.Today.Add(ts);
4
5Console.WriteLine(dt.ToString("hh:mm tt"));      // "09:05 AM"
6Console.WriteLine(dt.ToString("h:mm tt"));        // "9:05 AM" (no leading zero)
7Console.WriteLine(dt.ToString("hh:mm:ss tt"));    // "09:05:30 AM"
8Console.WriteLine(dt.ToString("HH:mm"));          // "09:05" (24-hour, no AM/PM)
9Console.WriteLine(dt.ToString("h:mm:ss tt"));     // "9:05:30 AM"
SpecifierOutputDescription
hh0912-hour with leading zero
h912-hour without leading zero
HH0924-hour with leading zero
mm05Minutes with leading zero
ss30Seconds with leading zero
ttAM/PMAM or PM designator

Helper Method

csharp
1public static string TimeSpanToAmPm(TimeSpan timeSpan)
2{
3    return DateTime.Today.Add(timeSpan).ToString("hh:mm tt");
4}
5
6// Usage
7Console.WriteLine(TimeSpanToAmPm(new TimeSpan(0, 0, 0)));    // "12:00 AM" (midnight)
8Console.WriteLine(TimeSpanToAmPm(new TimeSpan(6, 30, 0)));    // "06:30 AM"
9Console.WriteLine(TimeSpanToAmPm(new TimeSpan(12, 0, 0)));    // "12:00 PM" (noon)
10Console.WriteLine(TimeSpanToAmPm(new TimeSpan(18, 45, 0)));   // "06:45 PM"
11Console.WriteLine(TimeSpanToAmPm(new TimeSpan(23, 59, 0)));   // "11:59 PM"

Working with Database Time Values

Databases often store time-of-day as TimeSpan (SQL Server's TIME type maps to TimeSpan in C#):

csharp
1// From a database query
2TimeSpan openTime = (TimeSpan)reader["OpenTime"];    // e.g., 08:00:00
3TimeSpan closeTime = (TimeSpan)reader["CloseTime"];  // e.g., 17:30:00
4
5string open = DateTime.Today.Add(openTime).ToString("h:mm tt");
6string close = DateTime.Today.Add(closeTime).ToString("h:mm tt");
7
8Console.WriteLine($"Hours: {open} - {close}");
9// "Hours: 8:00 AM - 5:30 PM"

Extension Method

csharp
1public static class TimeSpanExtensions
2{
3    public static string ToAmPmString(this TimeSpan timeSpan, string format = "hh:mm tt")
4    {
5        return DateTime.Today.Add(timeSpan).ToString(format);
6    }
7}
8
9// Usage
10TimeSpan time = new TimeSpan(15, 45, 0);
11Console.WriteLine(time.ToAmPmString());              // "03:45 PM"
12Console.WriteLine(time.ToAmPmString("h:mm tt"));     // "3:45 PM"
13Console.WriteLine(time.ToAmPmString("hh:mm:ss tt")); // "03:45:00 PM"

Culture-Specific Formatting

csharp
1using System.Globalization;
2
3TimeSpan ts = new TimeSpan(14, 30, 0);
4DateTime dt = DateTime.Today.Add(ts);
5
6// US English
7Console.WriteLine(dt.ToString("hh:mm tt", CultureInfo.GetCultureInfo("en-US")));
8// "02:30 PM"
9
10// French (uses 24-hour clock by default)
11Console.WriteLine(dt.ToString("hh:mm tt", CultureInfo.GetCultureInfo("fr-FR")));
12// "02:30 " (no AM/PM in French culture)
13
14// Force invariant culture for consistent output
15Console.WriteLine(dt.ToString("hh:mm tt", CultureInfo.InvariantCulture));
16// "02:30 PM"

Parsing AM/PM String Back to TimeSpan

csharp
1string input = "02:30 PM";
2
3// Parse to DateTime first
4DateTime parsed = DateTime.ParseExact(input, "hh:mm tt", CultureInfo.InvariantCulture);
5
6// Extract the TimeSpan (time of day)
7TimeSpan timeSpan = parsed.TimeOfDay;
8Console.WriteLine(timeSpan);  // 14:30:00

Common Pitfalls

  • Using HH instead of hh for 12-hour format: HH is the 24-hour format specifier (00-23), while hh is the 12-hour format (01-12). Using HH with tt produces "14:30 PM" which is incorrect — 14 is not a valid 12-hour value.
  • TimeSpan values greater than 24 hours: A TimeSpan of 26:30:00 represents 1 day and 2.5 hours. Adding it to DateTime.Today gives tomorrow at 02:30 AM, which formats as "02:30 AM". This may be misleading if the original intent was a duration, not a time of day.
  • Culture-dependent AM/PM designators: Some cultures do not use AM/PM (e.g., French, German). The tt specifier produces empty strings in these cultures. Use CultureInfo.InvariantCulture for consistent AM/PM output regardless of the system locale.
  • Confusing midnight and noon: TimeSpan(0, 0, 0) formats as "12:00 AM" (midnight) and TimeSpan(12, 0, 0) formats as "12:00 PM" (noon). This matches the standard 12-hour convention but can be confusing when reading raw TimeSpan values.
  • Using TimeSpan.ToString() directly: TimeSpan.ToString("hh:mm tt") does not work as expected because TimeSpan format specifiers are different from DateTime. The tt specifier is not valid for TimeSpan. Always convert to DateTime first.

Summary

  • Convert TimeSpan to DateTime by adding it to DateTime.Today
  • Use DateTime.ToString("hh:mm tt") for 12-hour AM/PM format
  • hh = 12-hour padded, h = 12-hour unpadded, tt = AM/PM designator
  • Create an extension method ToAmPmString() for reusable conversion
  • Use CultureInfo.InvariantCulture for consistent AM/PM output across locales
  • Parse AM/PM strings back to TimeSpan via DateTime.ParseExact then .TimeOfDay

Course illustration
Course illustration

All Rights Reserved.