Converting PayPal Dates to .Net DateTime using Regex
Jan
6
Written by:
Wednesday, January 06, 2010 6:27 PM
I recently had a problem writing a PayPal Instant Payment Notification (IPN) listener. The problem was that the PayPal Sandbox environment (now puzzlingly called x.com) would process my IPN requests OK, but any ‘live’ request that came through my site ended in error.
Now the PayPal support people assured me that this wasn’t possible, but after dumping most of the actual code out of my module, and replacing it with highly-sensitive ‘gotcha’ error capturing code, I worked out the problem was due to a slight difference in the date formats between the Sandbox and Live environments.
The Sandbox date looked like this:
22:40:29 Dec. 16, 2009 PST
The live date looked like this:
13:02:26 Dec 21, 2009 PST
Eagle eyed readers will detect the difference straight away. It was a bit more difficult for me, as I was looking through raw logs and all I could see was 22%3A40%3A29+Dec.+16%2C+2009+PST as the values are encoded. It was a surprise for me, but I guess I should have been more prepared for wide and varied date formats – they’re always the problem child of data handling and validation. At least they have a text month to differentiate from dd/mm and mm/dd formats – they’re always fun.
Converting a PayPal Date to a .NET DateTime value
The format of the PayPal date isn’t one of the ones that you can easily just convert to a .NET DateTime type by doing a DateTime.TryParse call. I looked into writing a customised date parser to supply with the DateTime.Parse routine, but it all just looked too hard for something that was (supposed) to be coming in with a standard format.
What I originally wrote (and which caused all the problems between Sandbox and Live environments) was a date parsing routine that worked out which bit of the date was which, all done by splitting up the string into substrings – one for the time, date and timezone. This worked on the sandbox because it didn’t have the ‘.’ at the end of the month. But move it into the live environment, and it didn’t work at all, because it was out by one character. The resulting error wasn’t handled well (my fault) and so the whole thing mysteriously failed.
A better .NET / PayPal Date Parsing routine
Instead of fiddling around with brittle substring functions, I decided to turn to my old friend Regex, which thrives on this sort of fixed-format string parsing. I quickly wrote this regex expression, which worked almost straight away. The routine splits out the time, date and timezone, and within those individual groups, split out the hours, minutes, days, months and years. Turns out I didn’t need the individual pieces, but by then the expression was written anyway.
Here’s the expression:
(?<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})
A routine to convert a PayPal date to a .NET DateTime value using Regex
Here’s the full routine in C# to convert a PayPal date into a .NET DateTime value
/// <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;
}
You can use this routine quite simply by extracting a field which contains a PayPal date, and transforming it into a .NET DateTime value, like this:
//Get the payment date of the request. Note 0 hours to return UTC time of payment
DateTime paymentDate = ConvertFromPayPalDate(Request.Form["payment_date"], 0);
Feel free to use the code as-is, if you find any problems let me know via the comments.
5 comment(s) so far...
Re: Converting PayPal Dates to .Net DateTime using Regex
I have been having troubles converting Paypal dates to a readable format to display on the user's screen, and stumbled upon this bit of code. This is definitely something that I feel I can use; however, When I implement it, I keep getting the date translated to "1/1/0001 12:00:00 AM." Is this because the system cannot actually make the conversion? Any help/suggestions are appreciated.
a.bean
By Andrew Bean on
Sunday, January 31, 2010 8:07 AM
|
Re: Converting PayPal Dates to .Net DateTime using Regex
@andrew : that's the empty value for a .NET datetime variable. I would guess that the problem is that your DateTime.TryParse() call is failing, because the extracted date is not in the correct format. Check the values of the rawDate, rawTime and see what they are resulting in.
By Bruce Chapman on
Sunday, January 31, 2010 9:25 AM
|
Re: Converting PayPal Dates to .Net DateTime using Regex
Good to know Bruce. Your code got me thinking that there's got to be an easier way to pull that data with some standard .NET class. After a bit of research I found out how: use DateTime.TryParseExact(). I've included an example at www.codeillustrator.com/2010/03/converting-paypal-paymentdate-to-net.html. Hope that helps! Thanks again for the tip on the period difference between sandbox and live, and let me know if you have any more thoughts!
By Nathan Markey on
Thursday, March 18, 2010 9:20 PM
|
Re: Converting PayPal Dates to .Net DateTime using Regex
excellent job !! thanks
By Raymundo Limon on
Friday, April 08, 2011 8:39 AM
|
Re: Converting PayPal Dates to .Net DateTime using Regex
Good post.....Saved me the time of doing it myself.
Thanks,
-zd
By zach davis on
Wednesday, January 25, 2012 1:32 AM
|