I have the following code to get a NATO date-time group for a DateTime. I usually need Zulu-Time or from a specific time zone. Is it clear what those methods are providing? If want to parse a NATO dtg string would those be extension methods for string or DateTime?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Collections.ObjectModel;
using System.Globalization;
namespace scratchpad
{
/// <summary>
/// Create NATO date-time group from DateTime
/// </summary>
static class NatoDtg
{
/// <summary>
/// Get NATO date-time group for UTC/Zulu timezone
/// </summary>
/// <param name="dt">this</param>
/// <returns>NATO date-time group</returns>
public static string ToZuluDtg(this DateTime dt)
{
DateTime utc = dt.ToUniversalTime();
CultureInfo ci = new CultureInfo("en-GB");
StringBuilder builder = new StringBuilder();
builder.Append(utc.ToString("ddHHmm", ci)); // day, hours, minutes
builder.Append("Z"); // time zone
builder.Append(utc.ToString("MMMyy", ci).ToLower()); // month, year
return builder.ToString();
}
/// <summary>
///
/// </summary>
/// <param name="dt">this</param>
/// <param name="tz">Time zone for the </param>
/// <returns></returns>
public static string ToDtg(this DateTime dt, TimeZoneInfo tz)
{
if (tz == null) throw new ArgumentNullException("TimeZoneInfo is null");
CultureInfo ci = new CultureInfo("en-GB");
StringBuilder builder = new StringBuilder();
builder.Append(dt.ToString("ddHHmm", ci));
TimeSpan ts = tz.GetUtcOffset(dt);
char letter = '#';
if(ts.Hours == 0)
{
letter = 'Z';
}
else if(ts.Hours >= 1 && ts.Hours <= 9) // A-I
{
letter = 'A';
letter += (char)(ts.Hours-1);
}
else if(ts.Hours >= 10 && ts.Hours <= 12) // K-M TRICKY: skip J (Juliet)
{
letter = 'A';
letter += (char)ts.Hours;
}
else if(ts.Hours >= -12 && ts.Hours <= -1) // N-Y
{
letter = 'Z';
letter += (char)ts.Hours;
}
else
{
throw new InvalidOperationException("Unknown UTC offset for timezone");
}
builder.Append(letter);
builder.Append(dt.ToString("MMMyy", ci).ToLower());
return builder.ToString();
}
}
class Program
{
static void Main(string[] args)
{
DateTime now = DateTime.Now;
Console.WriteLine("Zulu DTG {0}", now.ToZuluDtg());
Console.WriteLine("Berlin DTG {0}", now.ToDtg(TimeZoneInfo.GetSystemTimeZones().Where(i => i.DisplayName.Contains("Berlin")).FirstOrDefault()));
Console.WriteLine("Local DTG {0}", now.ToDtg(TimeZoneInfo.Local));
Console.ReadLine();
}
}
}
DateTimeOffset
instead ofDateTime
. It contains an additional offset, TimeSpan, which is perfect for mapping to your DTG codes. Consider using an enum for your DTG codes. \$\endgroup\$