2

I want my millisecond value to always be three characters long, so I'm padding it, where necessary, with "0"s:

private String getPlatypusFileName(String billNum)
{
    const string basePortion = "Platypus_";
    String PlatypusFileName;
    DateTime dt = DateTime.Now;
    int Year = dt.Year;
    int Month = dt.Month;
    int Day = dt.Day;
    int Hour = dt.Hour;
    int Minute = dt.Minute;
    int Second = dt.Second;
    int Millisecond = dt.Millisecond;
    String paddedBillNum = Prepad(6, billNum);
    String mon = Prepad(2, Month.ToString());
    String day = Prepad(2, Day.ToString());
    String hour = Prepad(2, Hour.ToString());
    String min = Prepad(2, Minute.ToString());
    String sec = Prepad(2, Second.ToString());
    String milli = Prepad(3, Millisecond.ToString());
    PlatypusFileName = String.Format("{0}{1}_{2}{3}{4}{5}{6}{7}_{8}.xml", 
        basePortion, paddedBillNum, Year, mon, day, hour, min, sec, milli);
    return PlatypusFileName;
}

private String Prepad(int finalSize, String originalVal)
{
    String paddedVal = originalVal;
    while (paddedVal.Length < finalSize)
    {
        paddedVal = "0" + paddedVal;
    }
    return paddedVal;
}

...but I'm always getting vals with three "0"s for the millisecond portion; the returned values are like so:

Platypus_000003_20141008145606_000.xml

Why would that be?

admdrew
  • 3,790
  • 4
  • 27
  • 39
B. Clay Shannon-B. Crow Raven
  • 8,547
  • 144
  • 472
  • 862
  • 1
    Have you done any debugging? is `Millisecond` zero, or is it something `Prepad` does? – Blorgbeard Oct 08 '14 at 19:15
  • It's various values "2", "907", "362", etc. – B. Clay Shannon-B. Crow Raven Oct 08 '14 at 19:16
  • 2
    This actually works fine for me (the milliseconds portion looks correct, or at least not zero). *Update* here's a fiddle showing it working: https://dotnetfiddle.net/GyNClC – Andrew Whitaker Oct 08 '14 at 19:16
  • 1
    Works fine for me too; on what platform are you running this? – Thomas Levesque Oct 08 '14 at 19:18
  • Just notice that you shouldn't reinvent a bike, you could use built-in string formatting options: `milli.ToString("D3")`. – Dmitry Oct 08 '14 at 19:18
  • 1
    Are you using .NET Compact? "[Milliseconds in DateTime.Now on .NET Compact Framework always zero?](http://stackoverflow.com/questions/2606298/milliseconds-in-datetime-now-on-net-compact-framework-always-zero)" – Jonathan Lonowski Oct 08 '14 at 19:21
  • 1
    DateTime has plenty of formatting options: `string.Format("{0:yyyyMMddHHmmss_fff}", dt)` would let you bypass all of that formatting code. – Joe Enos Oct 08 '14 at 19:21
  • 2
    Are you using the the phone emulator? `System.DateTime.Now.Millisecond.ToString always returns zero on the Windows Phone Emulator.` according to the documentation. – TyCobb Oct 08 '14 at 19:21
  • 2
    btw, @B.ClayShannon, you're reinventing the wheel... there is already a `PadLeft` method on the `String` class – Thomas Levesque Oct 08 '14 at 19:21
  • @Mihai, `Millisecond.ToString().Length` will be 3 only if the value is greater than or equal to 100... – Thomas Levesque Oct 08 '14 at 19:29
  • 1
    Clay, are you running your code on a mobile platform? – mihai Oct 08 '14 at 19:29
  • 1
    What version of .NET are you using. This could explain why some people have this work correctly and you do not. – KSdev Oct 08 '14 at 19:31
  • @KSdev +1 What version of .NET and what current culture in the system? – Jonik Oct 08 '14 at 19:50
  • There are two ways I suppose: or TS shows not all code, or Hi is trying to dupe us. I can't even imagine what kind of culture can cast Int32 to String with 0 result. – Jonik Oct 08 '14 at 20:04
  • @ThomasLevesque: On a handheld device (Windows CE / compact framework); don't tell me DateTime disregards milliseconds on CF...(can't decide whether to append a question- or an exclamation-mark). – B. Clay Shannon-B. Crow Raven Oct 08 '14 at 20:28
  • 1
    @Jonik: The only current culture in my system is the yogurt I had for breakfast. I did listen to J.S. Bach last Sunday. – B. Clay Shannon-B. Crow Raven Oct 08 '14 at 20:38
  • 2
    @B.ClayShannon, I think it depends on the device's clock; check out [this question](http://stackoverflow.com/q/2606298/98713). As for the culture, it's the .NET term for "locale" (i.e. language and regional settings such as number and date format, currency, etc) – Thomas Levesque Oct 08 '14 at 20:51
  • @ThomasLevesque your comment is very intresting, thanks. But OP didn't said that hi used mobile platform, also hi said that `Millisecond` have _various values_. But anyway the link is very intresting. – Jonik Oct 08 '14 at 21:14
  • @Jonik: Yes, this is a Windows CE / Compact Framework app. The Milliseconds as generated there were always "000"; only on a test app (a VS 2013 "sandbox" app) did I get the expected various values. – B. Clay Shannon-B. Crow Raven Oct 08 '14 at 21:54

3 Answers3

4

Your code should work fine, as written, except that you're probably running on Windows Compact Framework. As mentioned here, the CF always returns 0 for DateTime.Millisecond, so some other approach will be necessary if you need to have that accuracy, such as looking at Environment.TickCount.

That being said, you don't need to use Prepad here - just format appropriately:

const string basePortion = "Platypus_";
DateTime dt = DateTime.Now;
int billNum = 3;

string result = string.Format("{0}{1:000000}_{2}{3:00}{4:00}{5:00}{6:00}{7:00}_{8:00}.xml",
    basePortion, 
    billNum, 
    dt.Year,
    dt.Month,
    dt.Day,
    dt.Hour,
    dt.Minute,
    dt.Second,
    dt.Millisecond);

On my system, this prints out a value of: Platypus_000003_20141008121707_894.xml - Though that changes each time it's run, of course.

Community
  • 1
  • 1
Reed Copsey
  • 554,122
  • 78
  • 1,158
  • 1,373
  • 1
    Yes, but it doesn't explain why he's getting "000"; the same code works fine on my machine. – Thomas Levesque Oct 08 '14 at 19:19
  • 1
    How would this help if the OP's value for `dt.Millisecond` is always zero? –  Oct 08 '14 at 19:19
  • @ThomasLevesque I edited and mentioned that, too - I'm not sure there isn't something else going on... – Reed Copsey Oct 08 '14 at 19:19
  • @hvd To be fair, [he said it *isn't* zero](http://stackoverflow.com/questions/26264645/why-is-my-datetime-now-millisecond-value-always-000#comment41204186_26264645). – admdrew Oct 08 '14 at 19:19
1

Why don't you use standard datetime.toString("special_format_string"). Learn methods of the string class, also learn about formats. You don't need even Prepad method.

All you need is one simple method:

    private String getPlatypusFileName(String billNum)
    {
        const string basePortion = "Platypus_";
        String PlatypusFileName;
        DateTime dt = DateTime.Now;
        PlatypusFileName = String.Format("{0}{1}_{2}.xml",
            basePortion, billNum.PadLeft(6,'0'), dt.ToString("yyyyMMddHHmmss_fff"));
        return PlatypusFileName;
    }

More over, don't use const if you don't know what it for. Also I'm sure that the base type of billNum source also is int, so you do not need any special method, you already have method string.Format(), just use it wisely. All your code can be replaced with one statement:

int billNum = 23;
string PlatypusFileName = string.Format("Platypus_{0:D6}_{1:yyyyMMddHHmmss_fff}.xml", billNum, DateTime.Now);
Jonik
  • 1,208
  • 2
  • 12
  • 20
  • Since CF is apparently the culprit, I will use a derivation of your code with a random differentiating val for the "milliseconds" portion. BTW, billNum is a String, not an int. It is usually something like "03", but it can also be "Fumblebutt" (or anything else). – B. Clay Shannon-B. Crow Raven Oct 08 '14 at 20:45
  • There's nothing wrong with using `const` here; it ensures that the variable won't be reassigned accidentally (ReSharper even suggests to use it if the variable is never reassigned). Why do you assume the OP doesn't know what it is for? – Thomas Levesque Oct 08 '14 at 20:53
  • @ThomasLevesque because Hi used it in that place... it's not necessary, it is redundant code. The const variables are not just simply readonly. The c# compiller replace all const variables to their values. So if you refer to const variable from another assembly in your code, but in new version of assembly the const variable changes, so you have to recompile your code too, instead of just replace referenced assembly. In OP's case const variable do not do anything wrong, but it's just not necessary. I was just warning about const. – Jonik Oct 08 '14 at 21:07
  • @ThomasLevesque also Resharper is a very good tool, but it's not cure-all(panacea). Sometimes it gives are not good hints. – Jonik Oct 08 '14 at 21:18
  • 1
    @Jonik, in this case, it can't be referred to by another assembly, since it's a local variable. But anyway, I still think it's good practice; this variable is logically a constant, and the const modifier prevents its accidental reassignment, which is a good thing. I agree that you shouldn't blindly follow ReSharper's suggestions, but in this case I think it's a good suggestion, and I would have followed it. – Thomas Levesque Oct 08 '14 at 22:03
0

Since this is, indeed, a CF project and, as Reed Copsey pointed out, I'm doomed to zilches in that environment for milliseconds (and it seems seconds, too), I (since I don't really need accurate seconds/milliseconds values, just "something") did this:

    . . .
    String pseudoSeconds = GetRandomIntAsStr(10,59);
    String fauxMilliseconds = GetRandomIntAsStr(100, 999);
    return String.Format("{0}-{1}-{2} {3}:{4}:{5}.{6}", year, month, day, hour, minute, pseudoSeconds, fauxMilliseconds);
    . . .

// ad[a,o]pted from http://www.whypad.com/posts/csharp-get-a-random-number-between-x-and-y/412/
internal static String GetRandomIntAsStr(int min, int max)
{
    Random rnd = new Random();
    int val = rnd.Next(min, max);
    return val.ToString();
}

And I get values such as "44.766" for the randomized portions of the string.

B. Clay Shannon-B. Crow Raven
  • 8,547
  • 144
  • 472
  • 862