Thursday, September 22, 2011

Getting the current time and displaying in HH:MM:SS.mmm

Task: How to elicit the current time and display it, in 24-hr format HH:MM:SS.mmm.

Answers in Bash, C, C#, Go, Java, JavaScript, Objective-C, PowerShell, Python, Ruby.

Caveat: no failure testing is included in the samples. Things fail. Production code should take account of failure.

Bash:

The solution for bash could hardly be simpler.

date +'%H:%M:%S.%3N'

The only problem is, it doesn't work on OSX. In that case, you might consider the Python or Ruby approach, or compile the C/UNIX option and execute that.

C:

Unfortunately, there is no way of getting milliseconds using standard C. The best we can do is just H+M+S:

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int main()
{
  time_t      now;
  struct tm*  local;

  time(&now, NULL);
  local = localtime(&now);

  printf("%02d:%02d:%02d\n", local->tm_hour, local->tm_min, local->tm_sec);

  return EXIT_SUCCESS;
}

In non-standard ways we have a number of options: UNIX-specific, Windows-specific, APR.

C / UNIX:


UNIX provides the system function gettimeofday(), which obtains the time (equivalent to time()) along with microseconds. Hence:

#include <sys/time.h>

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main()
{
  struct timeval  now;
  struct tm*      local;

  gettimeofday(&now, NULL);
  local = localtime(&now.tv_sec);

  printf("%02d:%02d:%02d.%03d\n", local->tm_hour, local->tm_min, local->tm_sec, now.tv_usec / 1000);

  return EXIT_SUCCESS;
}

C / Windows:


Windows provides the system function GetLocalTime(), which obtains the time in a rich structure SYSTEMTIME) that includes microseconds. Hence:

#include <windows.h>

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main()
{
  SYSTEMTIME  now;

  GetLocalTime(&now);
  
  printf("%02d:%02d:%02d.%03d\n", now.wHour, now.wMinutenow.wSecond, now.wMilliseconds);

  return EXIT_SUCCESS;
}

C / APR:


APR provides the apr_time_exp_t type, which is equivalent to struct tm as well as a tm_usec member from which we can derive the milliseconds. Hence:

#include <apr-1/apr_time.h>

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main()
{
  apr_time_t      now;
  apr_time_exp_t  local;

  now = apr_time_now();

  apr_time_exp_lt(&local, now);

  printf("%02d:%02d:%02d.%03d\n", local.tm_hour, local.tm_min, local.tm_sec, local.tm_usec / 1000);

  return EXIT_SUCCESS;
}


C#:


using System;
class Program
{
  static void Main()
  {
    DateTime dt = DateTime.Now;

    Console.Out.WriteLine(
      "{0:d2}:{1:d2}:{2:d2}.{3:d3}"
    , dt.Hour
    , dt.Minute
    , dt.Second
    , dt.Millisecond
    );
  }
}

Even though System.DateTime.Now is a property, it acts as a method in that it gets a new value every time it is involved. This is an all-too-common gotcha when repeated calls are made in the same region on the assumption that this property is property like in returning the same value.

Go:


package main

import (

    "fmt"
    "time"
)

func main() {

    t := time.Now()

    fmt.Printf(
      "%02d:%02d:%02d.%03d\n"
    , t.Hour()
    , t.Minute()
    , t.Second()
    , t.UnixNano()%1e6/1e3
    )
}


Java:


import java.text.SimpleDateFormat;
import java.util.Date;
class Program
{
  public static void Main(String[] args)
  {
    SimpleDateFormat fmt = new SimpleDateFormat("HH:mm:ss.SSS");
    Date now = new Date();

    System.out.println(fmt.format(now));
  }
}


JavaScript:


The built-in Date type has a method toISOString() that returns a string of the form YYYY-mm-DDTHH:MM:SS.mmmZ, to which a simple regex can extract the H+M+S+ms:

console.log((new Date()).toISOString().match(/(\d\d\:\d\d\:\d\d\.\d\d\d)/)[0]);


Objective-C:


NSDate *now = [NSDate date];
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:@"HH:mm:ss.SSS"];
NSString *s = [formatter stringFromDate:now];
NSLog(s);

Powershell:

Get-Date -format HH:mm:ss.fff 


Python:


import datetime

print datetime.datetime.now().strftime('%H:%M:%S.%f')[:-3]


Python's strftime()'s %f yields microseconds, hence the slicing off of the last three characters.


Ruby:


puts Time.now.strftime('%H:%M:%S.%L')




Swift:


let now = NSDate()
var formatter = NSDateFormatter()
formatter.dateFormat = "HH:mm:ss.SSS"
let s = formatter.stringFromDate(now)
println(s)