简体   繁体   中英

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

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;
}

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);
}

This should work

 public static DateTime ConvertPayPalDateTime(string payPalDateTime)
 { 
    CultureInfo enUS = new CultureInfo("en-US");
    // 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",
                             "HH:mm:ss dd MMM yyyy PST", "HH:mm:ss dd MMM. yyyy PST", "HH:mm:ss dd MMM yyyy PDT", "HH:mm:ss dd MMM. yyyy PDT"};
    DateTime outputDateTime;

    DateTime.TryParseExact(payPalDateTime, dateFormats, CultureInfo.InvariantCulture, DateTimeStyles.None, out outputDateTime);

    // convert to local timezone
    TimeZoneInfo hwZone = TimeZoneInfo.FindSystemTimeZoneById("Pacific Standard Time");

    outputDateTime = TimeZoneInfo.ConvertTime(outputDateTime, hwZone, TimeZoneInfo.Local);

    return outputDateTime;
}

The code in this post seems to work fine: http://www.codeillustrator.com/2010/03/converting-paypal-paymentdate-to-net.html

using System;
using System.Globalization;

public static class PayPalTransaction
{
    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;
    }
}

(answer cross-posted for this similar question: How to cast this date and save to database )

Assuming you have already parsed the date with DateTime.ParseExact() (or one of the other similar methods) you can call DateTime.ToUniversalTime()

EDIT: perhaps TimeZoneInfo.ConvertTimeToUtc is more appropriate: The ToUniversalTime method converts a DateTime value from local time to UTC. To convert the time in a non-local time zone to UTC, use the TimeZoneInfo.ConvertTimeToUtc(DateTime, TimeZoneInfo) method. To convert a time whose offset from UTC is known, use the ToUniversalTime method.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM