Click here to Skip to main content
15,913,152 members

Welcome to the Lounge

   

For discussing anything related to a software developer's life but is not for programming questions. Got a programming question?

The Lounge is rated Safe For Work. If you're about to post something inappropriate for a shared office environment, then don't post it. No ads, no abuse, and no programming questions. Trolling, (political, climate, religious or whatever) will result in your account being removed.

 
GeneralRe: Regular Expression - Achievement unlocked Pin
SoMad5-Feb-14 11:12
professionalSoMad5-Feb-14 11:12 
GeneralRe: Regular Expression - Achievement unlocked Pin
Marco Bertschi5-Feb-14 20:17
protectorMarco Bertschi5-Feb-14 20:17 
GeneralRe: Regular Expression - Achievement unlocked Pin
JimmyRopes5-Feb-14 16:29
professionalJimmyRopes5-Feb-14 16:29 
GeneralRe: Regular Expression - Achievement unlocked Pin
BillWoodruff5-Feb-14 17:38
professionalBillWoodruff5-Feb-14 17:38 
GeneralRe: Regular Expression - Achievement unlocked Pin
JimmyRopes5-Feb-14 18:14
professionalJimmyRopes5-Feb-14 18:14 
GeneralRe: Regular Expression - Achievement unlocked Pin
BillWoodruff5-Feb-14 19:46
professionalBillWoodruff5-Feb-14 19:46 
GeneralRe: Regular Expression - Achievement unlocked Pin
JimmyRopes6-Feb-14 2:12
professionalJimmyRopes6-Feb-14 2:12 
GeneralRe: Regular Expression - Achievement unlocked Pin
Marco Bertschi5-Feb-14 20:14
protectorMarco Bertschi5-Feb-14 20:14 
BillWoodruff wrote:
I believe learning, and mastering, something new is one of the very best things in life !

Learning is often strapped to pain, and effort.
Mastering the learnt stuff is joy!

BillWoodruff wrote:
Of course the question of "constraints" immediately arises: what makes parsing the range of inputs you show more difficult is:

 

1. possible ambiguity of the "-" glyph: it is a separator for the Date component, and a sign-indicator for the time-offset.

 

2. possible ambiguity of the "." glyph: it is a presence/absence indicator for milliseconds, and a decimal-point for the time-offset.

It's all specified like that. [-->]


BillWoodruff wrote:
If, you, the creator, have control over all possible inputs, and can ensure there will always something like ".0Z" indicating no milliseconds, and there will always be some other character than "-" separating year, month, day, then, obviously parsing becomes so much more simple.

I don't have any control over the formatting, I only know the constraints of the allowed values.
By the way, I wrote some unit tests to compare the performance between split and RegEx: A split does not providea measeruable performance improvement, compared to the Regular Expression. What I really like about the RegEx solutions that the parsing method becomes a lot shorter, and is therefore more readable (see the method public bool FromString(string dateTime) in the code sample below:

I wrote the following code so far:
C#
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;

namespace Springlog.Com.Messaging
{
    /// <summary>
    /// Represents the Timestamp of a <see cref="SyslogMessageHeader"/>
    /// Author: Marco Bertschi, (C) 2014 Marco Bertschi
    /// </summary>
    public class SyslogTimestamp
    {
        #region Properties
        /// <summary>
        /// Returns the count of the days for a specific month in a specific year.
        /// </summary>
        /// <param name="month">month  </param>
        /// <param name="year">year</param>
        /// <returns></returns>
        static short GetDayMaxDaysOfMonth(int month, int year)
        {
            if (month != 2)
            {
                //  January       March         May           July          August        October        December        
                if (month == 1 || month == 3 || month == 5 || month == 7 || month == 8 || month == 10 || month == 12)
                {
                    return 31;
                }
                else // April, June, September, November
                {
                    return 30;
                }
            }
            else //February
            {
                if (IsLeapYear(year))
                {
                    return 29;
                }
                return 28;
            }
        }
        /// <summary>
        /// Returns true if the argument is a leap year
        /// </summary>
        /// <param name="year">The year number to check</param>
        /// <returns></returns>
        private static bool IsLeapYear(int year)
        {
            if (year % 4 == 0)
            {
                if (year % 100 == 0)
                {
                    if (year % 400 == 0)
                    {
                        return true;
                    }
                    return false;
                }
                return true;
            }
            return false;
        }

        /// <summary>
        /// The part of the Timestamp which represents the year.
        /// </summary>
        int year;
        /// <summary>
        /// Gets the year part of the Timestamp.
        /// </summary>
        public int Year
        {
            get { return year; }
        }
        /// <summary>
        /// The part of the Timestamp which represents the month.
        /// </summary>
        int month;
        /// <summary>
        /// Gets the month part of the Timestamp.
        /// </summary>
        public int Month
        {
            get { return month; }
        }
        /// <summary>
        /// The part of the Timestamp which represents the day of the month.
        /// </summary>
        int dayOfMonth;
        /// <summary>
        /// Gets the days part of the Timestamp.
        /// </summary>
        public int DayOfMonth
        {
            get { return dayOfMonth; }
        }
        /// <summary>
        /// The part of the Timestamp which represents the hours.
        /// </summary>
        int hours;
        /// <summary>
        /// Gets the hours part of the Timestamp.
        /// </summary>
        public int Hours
        {
            get { return hours; }
        }
        /// <summary>
        /// The part of the Timestamp which represents the minutes.
        /// </summary>
        int minutes;
        /// <summary>
        /// Gets the minutes part of the Timestamp.
        /// </summary>
        public int Minutes
        {
            get { return minutes; }
        }
        /// <summary>
        /// The part of the Timestamp which represents the seconds.
        /// </summary>
        int seconds;
        /// <summary>
        /// Gets the seconds part of the Timestamp.
        /// </summary>
        public int Seconds
        {
            get { return seconds; }
        }
        /// <summary>
        /// The part of the Timestamp which represents the year.
        /// </summary>
        int miliseconds;
        /// <summary>
        /// Gets the milliseconds part of the Timestamp.
        /// </summary>
        public int Miliseconds
        {
            get { return miliseconds; }
        }
        /// <summary>
        /// The offset from the UTC timezone
        /// </summary>
        double utcOffset;
        /// <summary>
        /// Gets or sets the offset from the UTC timezone.
        /// </summary>
        public double UtcOffset
        {
            get { return utcOffset; }
            set { utcOffset = value; }
        }
        #endregion

        public SyslogTimestamp()
        {
            Reset();
        }

        public SyslogTimestamp(string timestamp)
        {
            Reset();
            FromString(timestamp);
        }

        public SyslogTimestamp(DateTime timestamp)
        {
            Reset();
            FromDateTime(timestamp);
        }

        /// <summary>
        /// Resets all fields to their default values;
        /// </summary>
        private void Reset()
        {
            miliseconds = 0;
            seconds = 0;
            minutes = 0;
            hours = 0;
            dayOfMonth = 0;
            month = 0;
            year = 0;
            utcOffset = 0;
        }

        /// <summary>
        /// Parses a string into a Syslog timestamp.
        /// </summary>
        /// <param name="dateTime">string which is going to be parsed</param>
        /// <returns>true = success | false = invalid string</returns>
        public bool FromString(string dateTime)
        {
            Reset();// All fields must be resetted - Otherwise the parsing will give a wrong value!
            Regex splitRegex = new Regex(@"([0-9]{4})-([1-9]|[1][0-2])-([0-2]?[0-9]|[3][0-1])[T]([0-1]?[0-9]|[2][0-3])[:]([0-5]?[0-9])[:]([0-5]?[0-9])?.?([0-9]{1,6})[Z]([+-][0-9][\.|,]?[0-9]?|[0-9]{2}?|[+-]?[0][1][0-2][\.]?[0-9]?|[0-9]{2}?)", RegexOptions.IgnoreCase);
            Match timestamp = splitRegex.Match(dateTime);

            if (timestamp.Groups.Count > 1)
            {
                AddYears(Int32.Parse(timestamp.Groups[1].Value));
                AddMonths(Int32.Parse(timestamp.Groups[2].Value));
                AddDays(Int32.Parse(timestamp.Groups[3].Value));
                AddHours(Int32.Parse(timestamp.Groups[4].Value));
                AddMinutes(Int32.Parse(timestamp.Groups[5].Value));
                AddSeconds(Int32.Parse(timestamp.Groups[6].Value));
                AddMilliseconds(Int32.Parse(timestamp.Groups[7].Value));
                utcOffset = Double.Parse(timestamp.Groups[8].Value, CultureInfo.InvariantCulture);
                return true;
            }
            else
            {
                return false;
            }
        }
        /// <summary>
        /// Returns a fully formatted Syslog timestamp, as string.
        /// </summary>
        /// <returns>Syslog timestamp, as string</returns>
        public string ToFormattedString()
        {
            string timezonePreSign = "+";
            if (utcOffset < 0)
            {
                timezonePreSign = "";
            }
            return string.Format("{0}-{1}-{2}T{3}:{4}:{5}.{6}Z{7}{8}", year, month, dayOfMonth, hours, minutes, seconds, miliseconds, timezonePreSign, utcOffset.ToString().Replace(',','.'));
        }

        public DateTime ToDateTime()
        {
            DateTimeKind dateTimeKind;
            if(utcOffset == 0)
            {
                dateTimeKind = DateTimeKind.Utc;
            }
            else
	        {
                dateTimeKind = DateTimeKind.Local;        
	        }
            return new DateTime(year, month, dayOfMonth, hours, minutes, seconds, miliseconds, dateTimeKind);
        }

        /// <summary>
        /// Overriden ToString() method - Displays the same as ToFormattedString().
        /// </summary>
        /// <returns></returns>
        public override string ToString()
        {
            return this.ToFormattedString();
        }
        /// <summary>
        /// Parses a <see cref="System.DateTime"/> type to a <see cref="SyslogTimestamp"/>. It is assumed that the
        /// DateTime type must be converted to UTC if the second argument is left out.
        /// </summary>
        /// <remarks>
        /// The FromDateTime method recognizes only the current daylight saving time adjustment rule for the local time zone. 
        /// As a result, it is guaranteed to accurately return the UTC offset of a local time only during the period in which the 
        /// latest adjustment rule is in effect. It may return inaccurate results if time is a historic date and time value 
        /// that was subject to a previous adjustment rule.
        /// </remarks>
        /// <param name="timestamp">The <see cref="System.DateTime"/> type which will be parsed</param>
        public void FromDateTime(DateTime timestamp)
        {
            TimeSpan utcOffset = TimeZone.CurrentTimeZone.GetUtcOffset(timestamp);
            this.utcOffset = utcOffset.Hours + (utcOffset.Minutes / 100); 

            AddMilliseconds(timestamp.Millisecond);
            AddSeconds(timestamp.Second);
            AddMinutes(timestamp.Minute);
            AddHours(timestamp.Hour);
            AddDays(timestamp.Day);
            AddMonths(timestamp.Month);
            AddYears(timestamp.Year);
        }

        /// <summary>
        /// Adds a <see cref="System.TimeSpan"/> to the timestamp
        /// </summary>
        /// <param name="timeSpan">The time span which is added to the Timestamp</param>
        public void Add(TimeSpan timeSpan)
        {
            AddMilliseconds(timeSpan.Milliseconds);
            AddSeconds(timeSpan.Seconds);
            AddMinutes(timeSpan.Minutes);
            AddHours(timeSpan.Hours);
            AddDays(timeSpan.Days);
        }
        /// <summary>
        /// Adds the passed millisecond value to the timestamp
        /// </summary>
        /// <param name="val">Added milliseconds</param>
        public void AddMilliseconds(int val)
        {
            if (val + miliseconds >= 1000)
            {
                AddSeconds( val / 1000);
                miliseconds = (val % 1000);
            }
            else
            {
                miliseconds += val;
            }
        }
        /// <summary>
        /// Adds the passed second value to the timestamp
        /// </summary>
        /// <param name="val">Added seconds</param>
        private void AddSeconds(int val)
        {
            if (seconds + val >= 60)
            {
                AddMinutes(val / 60);
                seconds = (val % 60);
            }
            else
            {
                seconds += val;
            }
        }
        /// <summary>
        /// Adds the passed minute value to the timestamp
        /// </summary>
        /// <param name="val">Added minutes</param>
        private void AddMinutes(int val)
        {
            if (minutes + val >= 60)
            {
                AddMinutes(val / 60);
                minutes = (val % 60);
            }
            else
            {
                minutes += val;
            }
        }
        /// <summary>
        /// Adds the passed hour value to the timestamp
        /// </summary>
        /// <param name="val">Added hours</param>
        private void AddHours(int val)
        {
            if (hours + val >= 24)
            {
                AddDays (val / 24);
                hours = (val % 24);
            }
            else
            {
                hours += val;
            }
        }
        /// <summary>
        /// Adds the passed days value to the timestamp
        /// </summary>
        /// <param name="val">Added days</param>
        private void AddDays(int val)
        {
            short dayCount = GetDayMaxDaysOfMonth(month, year);
            if (dayOfMonth + val > dayCount)
            {
                AddMonths(val / dayCount);
                dayOfMonth = (val % dayCount);
            }
            else
            {
                dayOfMonth += val;
            }
        }
        /// <summary>
        /// Adds the passed month value to the timestamp
        /// </summary>
        /// <param name="val">Added months</param>
        private void AddMonths(int val)
        {
            if (month + val > 12)
            {
                AddYears(val / 12);
                month = (val % 12);
            }
            else
            {
                month += val;
            }
        }
        /// <summary>
        /// Adds the passed value to the year part of the time stamp
        /// </summary>
        /// <param name="val">Years to be added</param>
        private void AddYears(int val)
        {
            year += val;
        }

        /// <summary>
        /// Returns true if the the parameter matches this instance.
        /// </summary>
        /// <remarks>
        /// See <see cref="DoMatch"/>
        /// </remarks>
        /// <param name="other">The parameter to compare</param>
        /// <returns>true|false</returns>
        public override bool Equals(object o)
        {
            if (o is SyslogTimestamp)
            {
                return DoMatch((SyslogTimestamp)o, this);
            }
            else
            {
                return false;
            }
        }
        /// <summary>
        /// Returns true if a & b match, else false.
        /// </summary>
        /// <remarks>
        /// Match criteria:
        /// (a.year == b.Year)
        /// && (a.month == b.Month)
        /// && (a.dayOfMonth == b.DayOfMonth)
        /// && (a.hours == b.Hours)
        /// && (a.minutes == b.Minutes)
        /// && (a.seconds == b.Seconds)
        /// && (a.miliseconds == b.Miliseconds)
        /// && (a.utcOffset == b.UtcOffset);
        /// </remarks>
        public static bool DoMatch(SyslogTimestamp a, SyslogTimestamp b)
        {
            bool doMatch = (a.year == b.Year)
                && (a.month == b.Month)
                && (a.dayOfMonth == b.DayOfMonth)
                && (a.hours == b.Hours)
                && (a.minutes == b.Minutes)
                && (a.seconds == b.Seconds)
                && (a.miliseconds == b.Miliseconds)
                && (a.utcOffset == b.UtcOffset);

            return doMatch;
        }
        /// <summary>
        /// The overloaded == operator
        /// </summary>
        /// <remarks>
        /// see http://msdn.microsoft.com/en-us/library/ms173147(v=vs.80).aspx
        /// </remarks>
        public static bool operator ==(SyslogTimestamp a, SyslogTimestamp b)
        {
            // If both are null, or both are same instance, return true.
            if (System.Object.ReferenceEquals(a, b))
            {
                return true;
            }

            // If one is null, but not both, return false.
            if (((object)a == null) || ((object)b == null))
            {
                return false;
            }

            return DoMatch(a, b);
        }
        /// <summary>
        /// The overloaded != operator.
        /// </summary>
        /// <remarks>
        /// see http://msdn.microsoft.com/en-us/library/ms173147(v=vs.80).aspx
        /// </remarks>
        public static bool operator !=(SyslogTimestamp a, SyslogTimestamp b)
        {
            return !(a == b);
        }
        /// <summary>
        /// The smaller than Operator
        /// compares every date|time related field with
        /// the other and returns true if the left hand side of
        /// the assignement is smaller than the right hand side
        /// </summary>
        /// <param name="a"></param>
        /// <param name="b"></param>
        /// <returns></returns>
        public static bool operator <(SyslogTimestamp a, SyslogTimestamp b)
        {
            if (a.Year < b.Year) { return true; }
            if (a.Year > b.Year) { return false; }

            if (a.Month < b.Month) { return true; }
            if (a.Month > b.Month) { return false; }

            if (a.DayOfMonth < b.DayOfMonth) { return true; }
            if (a.DayOfMonth > b.DayOfMonth) { return false; }

            if ((a.Hours + a.UtcOffset) < (b.Hours + b.UtcOffset)) { return true; }
            if ((a.Hours + a.UtcOffset) > (b.Hours + b.UtcOffset)) { return false; }

            if (a.Minutes < b.Minutes) { return true; }
            if (a.Minutes > b.Minutes) { return false; }

            if (a.Seconds < b.Seconds) { return true; }
            if (a.Seconds > b.Seconds) { return false; }

            if (a.Miliseconds < b.Miliseconds) { return true; }
            if (a.Miliseconds > b.Miliseconds) { return false; }

            return false;
        }
        /// <summary>
        /// The greater than Operator
        /// compares every date|time related field with
        /// the other and returns true if the left hand side of
        /// the assignement is greater than the right hand side
        /// </summary>
        /// <param name="a"></param>
        /// <param name="b"></param>
        /// <returns></returns>
        public static bool operator >(SyslogTimestamp a, SyslogTimestamp b)
        {
            if (a.Year > b.Year) { return true; }
            if (a.Year < b.Year) { return false; }

            if (a.Month > b.Month) { return true; }
            if (a.Month < b.Month) { return false; }

            if (a.DayOfMonth > b.DayOfMonth) { return true; }
            if (a.DayOfMonth < b.DayOfMonth) { return false; }

            if ((a.Hours + a.UtcOffset) > (b.Hours + b.UtcOffset)) { return true; }
            if ((a.Hours + a.UtcOffset) < (b.Hours + b.UtcOffset)) { return false; }

            if (a.Minutes > b.Minutes) { return true; }
            if (a.Minutes < b.Minutes) { return false; }

            if (a.Seconds > b.Seconds) { return true; }
            if (a.Seconds < b.Seconds) { return false; }

            if (a.Miliseconds > b.Miliseconds) { return true; }
            if (a.Miliseconds < b.Miliseconds) { return false; }

            return false;
        }
        /// <summary>
        /// greater or equal Operator
        /// </summary>
        /// <param name="a"></param>
        /// <param name="b"></param>
        /// <returns>(a > b) || DoMatch(a, b)</returns>
        public static bool operator >=(SyslogTimestamp a, SyslogTimestamp b) 
        {
            return (a > b) || DoMatch(a, b);
        }
        /// <summary>
        /// smaller or equal Operator
        /// </summary>
        /// <param name="a"></param>
        /// <param name="b"></param>
        /// <returns><code>(a { b) || DoMatch(a, b)</code></returns>
        public static bool operator <=(SyslogTimestamp a, SyslogTimestamp b)
        {
            return (a < b) || DoMatch(a, b);
        }

        /// <summary>
        /// Returns the Hash code of the object
        /// </summary>
        /// <returns>Hash code</returns>
        public override int GetHashCode()
        {
            return base.GetHashCode();
        }
    }
}


Which is checked by the following Unit Tests:

C#
using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Springlog.Com.Messaging;

namespace Springlog.Com.Messaging.UnitTests
{
    [TestClass]
    public class SyslogTimestampUnitTest
    {
        /// <summary>
        /// This test case shall ensure that the compareing operators on the 
        /// SyslogTimestamp type are working correctly.
        /// </summary>
        [TestMethod]
        public void SyslogTimestampComparisonIntegrity()
        {
            SyslogTimestamp timestamp1 = new SyslogTimestamp();
            SyslogTimestamp timestamp2 = new SyslogTimestamp();
            SyslogTimestamp timestamp3 = new SyslogTimestamp();
            SyslogTimestamp timestamp4 = new SyslogTimestamp();

            timestamp1.FromDateTime(DateTime.Now);
            timestamp2.FromDateTime(DateTime.Now.AddDays(-1));
            timestamp3 = timestamp1;
            timestamp4.FromDateTime(DateTime.Now.AddMinutes(2));

            Assert.AreEqual(true, (timestamp1 > timestamp2));
            Assert.AreEqual(true, (timestamp4 > timestamp1));
            Assert.AreEqual(false, (timestamp1 < timestamp2));
            Assert.AreEqual(true, (timestamp1 >= timestamp2));
            Assert.AreEqual(false, (timestamp1 <= timestamp2));
            Assert.AreEqual(true, (timestamp1 == timestamp3));
            Assert.AreEqual(false, (timestamp1 != timestamp3));
            Assert.AreEqual(false, (timestamp1 == timestamp4));
            Assert.AreEqual(false, (timestamp1 == timestamp2));
        }

        /// <summary>
        /// This test case shall ensure that no errors are happening when 
        /// converting a string to a timestamp, and vice versa.
        /// </summary>
        [TestMethod]
        public void SyslogTimestampStringConversionIntegrity()
        {
            DateTime now = DateTime.Now;
            SyslogTimestamp timestamp = new SyslogTimestamp();
            SyslogTimestamp timestamp2 = new SyslogTimestamp();

            timestamp.FromDateTime(now);

            timestamp.UtcOffset = 1;
            Assert.AreEqual(true, timestamp2.FromString(timestamp.ToFormattedString()));
            Assert.AreEqual(true, (timestamp2 == timestamp));

            timestamp.UtcOffset = 1.5;
            Assert.AreEqual(true, timestamp2.FromString(timestamp.ToFormattedString()));
            Assert.AreEqual(true, (timestamp2 == timestamp));
        }
        /// <summary>
        /// This test case shall ensure that no errors are happening when 
        /// converting a DateTime type to a timestamp, and vice versa.
        /// </summary>
        [TestMethod]
        public void SyslogTimestampDateTimeConversionIntegrity()
        {
            DateTime now = DateTime.Now;
            SyslogTimestamp timestamp = new SyslogTimestamp();

            timestamp.FromDateTime(now);
            DateTime timestampDateTime = timestamp.ToDateTime();

            Assert.AreEqual(now.Year, timestampDateTime.Year);
            Assert.AreEqual(now.Month, timestampDateTime.Month);
            Assert.AreEqual(now.Day, timestampDateTime.Day);
            Assert.AreEqual(now.Hour, timestampDateTime.Hour);
            Assert.AreEqual(now.Minute, timestampDateTime.Minute);
            Assert.AreEqual(now.Second, timestampDateTime.Second);
            Assert.AreEqual(now.Millisecond, timestampDateTime.Millisecond);
        }
    }
}

Clean-up crew needed, grammar spill... - Nagy Vilmos

GeneralRe: Regular Expression - Achievement unlocked Pin
BillWoodruff5-Feb-14 21:20
professionalBillWoodruff5-Feb-14 21:20 
GeneralRe: Regular Expression - Achievement unlocked Pin
Marco Bertschi5-Feb-14 21:24
protectorMarco Bertschi5-Feb-14 21:24 
GeneralRe: Regular Expression - Achievement unlocked Pin
Steve Wellens5-Feb-14 17:51
Steve Wellens5-Feb-14 17:51 
GeneralRe: Regular Expression - Achievement unlocked Pin
Septimus Hedgehog5-Feb-14 21:29
Septimus Hedgehog5-Feb-14 21:29 
GeneralRe: Regular Expression - Achievement unlocked Pin
Rage5-Feb-14 22:12
professionalRage5-Feb-14 22:12 
GeneralRe: Regular Expression - Achievement unlocked Pin
Fabio Franco5-Feb-14 23:02
professionalFabio Franco5-Feb-14 23:02 
GeneralRe: Regular Expression - Achievement unlocked Pin
Thornik6-Feb-14 0:24
Thornik6-Feb-14 0:24 
GeneralRe: Regular Expression - Achievement unlocked Pin
svella6-Feb-14 3:17
svella6-Feb-14 3:17 
GeneralRe: Regular Expression - Achievement unlocked Pin
Marco Bertschi6-Feb-14 3:29
protectorMarco Bertschi6-Feb-14 3:29 
GeneralRe: Regular Expression - Achievement unlocked Pin
TheFigmo6-Feb-14 4:34
TheFigmo6-Feb-14 4:34 
GeneralRe: Regular Expression - Achievement unlocked Pin
Marco Bertschi6-Feb-14 4:37
protectorMarco Bertschi6-Feb-14 4:37 
GeneralRe: Regular Expression - Achievement unlocked Pin
syspau6-Feb-14 7:52
syspau6-Feb-14 7:52 
GeneralRe: Regular Expression - Achievement unlocked Pin
Ralph Little6-Feb-14 7:56
Ralph Little6-Feb-14 7:56 
GeneralRe: Regular Expression - Achievement unlocked Pin
dpminusa6-Feb-14 22:37
dpminusa6-Feb-14 22:37 
GeneralVisual Studio with MSDN Premium Pin
Joel Palmer5-Feb-14 7:41
Joel Palmer5-Feb-14 7:41 
GeneralRe: Visual Studio with MSDN Premium Pin
S Houghtelin5-Feb-14 7:50
professionalS Houghtelin5-Feb-14 7:50 
GeneralRe: Visual Studio with MSDN Premium Pin
Marco Bertschi5-Feb-14 7:51
protectorMarco Bertschi5-Feb-14 7:51 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.