Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I convert Paypal's HH:MM:SS DD Mmm(.) YYYY PST/PDT to a C# UTC DateTime?

Tags:

date

c#

I would like to log a payment_date in this format in a SQL Server database.

Update. Instinct was right on this one. Found a solution here: http://www.codeillustrator.com/2010/03/converting-paypal-paymentdate-to-net.html, verifying... of course, if Paypal ever moves out of the West Coast, I'll be in trouble. Is there a better way to parse this? Maybe with TimeZone?

public static DateTime ConvertPayPalDateTime(string payPalDateTime)
{
    // accept a few different date formats because of PST/PDT timezone and slight month difference in sandbox vs. prod.
    string[] dateFormats = { "HH:mm:ss MMM dd, yyyy PST", "HH:mm:ss MMM. dd, yyyy PST", "HH:mm:ss MMM dd, yyyy PDT", "HH:mm:ss MMM. dd, yyyy PDT" };
    DateTime outputDateTime;

    DateTime.TryParseExact(payPalDateTime, dateFormats, new CultureInfo("en-US"), DateTimeStyles.None, out outputDateTime);

    // convert to local timezone
    outputDateTime = outputDateTime.AddHours(3);

    return outputDateTime;
}

Wait a sec, that code above is completely wrong for me. I'm on the West Coast! Ideally this should be updated to send the date to a proper UTC DateTime and handle any time zone. Also the code above doesn't handle PDT properly (if converted to UTC).

Update2. Apparently, at least in previous versions, the sandbox would return "Feb." while the live returns "Feb". Lol. Someone save me!

Update3. Link to Regex version http://www.ifinity.com.au/Blog/EntryId/77/Converting-PayPal-Dates-to-Net-DateTime-using-Regex, but debugging could be an issue. Regex does not seem like the right way to do this. There must be a better way.

/// <summary>
/// Converts a PayPal datestring into a valid .net datetime value
/// </summary>
/// <param name="dateValue">a string containing a PayPal date</param>
/// <param name="localUtcOffset">the number of hours from UTC/GMT the local 
/// time is (ie, the timezone where the computer is)</param>
/// <returns>Valid DateTime value if successful, DateTime.MinDate if not</returns>
private static DateTime ConvertFromPayPalDate(string rawPayPalDate, int localUtcOffset)
{
    /* regex pattern splits paypal date into
     * time : hh:mm:ss
     * date : Mmm dd yyyy
     * timezone : PST/PDT
     */
     const string payPalDateRegex = @"(?<time>\d{1,2}:\d{2}:\d{2})\s(?<date>(?<
Mmm>[A-Za-z\.]{3,5})\s(?<dd>\d{1,2}),?\s(?<yyyy>\d{4}))\s(?<tz>[A-Z]{0,3})";  
    //!important : above line broken over two lines for formatting - rejoin in code editor
    //example 05:49:56 Oct. 18, 2009 PDT
    //        20:48:22 Dec 25, 2009 PST
    Match dateMatch = Regex.Match(rawPayPalDate, payPalDateRegex, RegexOptions.IgnoreCase);
    DateTime time, date = DateTime.MinValue;
    //check to see if the regex pattern matched the supplied string
    if (dateMatch.Success)
    {
        //extract the relevant parts of the date from regex match groups
        string rawDate = dateMatch.Groups["date"].Value;
        string rawTime = dateMatch.Groups["time"].Value;
        string tz = dateMatch.Groups["tz"].Value;

        //create date and time values
        if (DateTime.TryParse(rawTime, out time) && DateTime.TryParse(rawDate, out date))
        {
            //add the time to the date value to get the datetime value
            date = date.Add(new TimeSpan(time.Hour, time.Minute, time.Second));
            //adjust for the pdt timezone.  Pass 0 to localUtcOffset to get UTC/GMT
            int offset = localUtcOffset + 7; //pdt = utc-7, pst = utc-8
            if (tz == "PDT")//pacific daylight time
                date = date.AddHours(offset);
            else  //pacific standard time
                date = date.AddHours(offset + 1);
        }
    }
    return date;
}
like image 447
tofutim Avatar asked Jun 27 '11 23:06

tofutim


1 Answers

I haven't done any C# since 2006, so this code probably doesn't compile. Test it before you fly!

public static DateTime ConvertPayPalDateTime(string payPalDateTime)
{
  // Get the offset.
  // If C# supports switching on strings, it's probably more sensible to do that.
  int offset;
  if (payPalDateTime.EndsWith(" PDT"))
  {
     offset = 7;
  }
  else if (payPalDateTime.EndsWith(" PST"))
  {
     offset = 8;
  }
  else
  {
    throw some exception;
  }

  // We've "parsed" the time zone, so remove it from the string.
  payPalDatetime = payPalDateTime.Substring(0,payPalDateTime.Length-4);

  // Same formats as above, but with PST/PDT removed.
  string[] dateFormats = { "HH:mm:ss MMM dd, yyyy", "HH:mm:ss MMM. dd, yyyy" };

  // Parse the date. Throw an exception if it fails.
  DateTime ret = DateTime.ParseExact(payPalDateTime, dateFormats, new CultureInfo("en-US"), DateTimeStyles.None, out outputDateTime);

  // Add the offset, and make it a universal time.
  return ret.AddHours(offset).SpecifyKind(DateTimeKind.Universal);
}
like image 70
tc. Avatar answered Sep 18 '22 09:09

tc.