Analizar datetime en varios formatos

He creado un punto final de API. La persona que llama puede llamar a la API con el método que pasa los parámetros relevantes. En los parámetros hay un parámetro que es de formato.POSTdatetime

El problema es que al llamar a esta API la persona que llama puede pasar en 3 formatos diferentes:datetime

  1. long int – por ejemplo, 1374755180
  2. Formato de EE.UU. – por ejemplo, «7/25/2013 6:37:31 PM» (como string)
  3. Formato de marca de tiempo- por ejemplo, «2013-07-25 14:26:00» (como string)

Tengo que analizar el valor y convertirlo a un o en formato de marca de tiempo.datetimeDateTimestring

He intentado usar , , y pero ninguno de ellos está funcionando con certeza para mí.DateTime.TryParse()DateTime.Parse()Convert.ToDateTime()Convert.ToDouble()

La salida requerida tiene que estar en formato.en-GB

Editar:

Había pensado en tener un bloque para usar con 3 veces con una para decir que la cuerda no se podía analizar. ¿Es esta la mejor solución? ¿O hay soluciones mejores que esta?if-else if-elseTryParseelse

¡Por favor, ayuda!

Respuestas:7 Respuestas 7
Tiempo:hace 9 años, 2 meses
Última modificación:hace 1 año, 9 meses

Solución

Debe considerar la posibilidad de requerir una zona horaria. 1 no lo necesita, pero #2 y #3 sí.

public DateTime ParseRequestDate()
{
    // https://stackoverflow.com/questions/2883576/how-do-you-convert-epoch-time-in-c

    CultureInfo enUS = new CultureInfo("en-US");

    var dt = "1374755180";
    //var dt = "7/25/2013 6:37:31 PM";
    //var dt = "2013-07-25 14:26:00";

    DateTime dateValue;
    long dtLong;

    // Scenario #1
    if (long.TryParse(dt, out dtLong))
        return dtLong.FromUnixTime();

    // Scenario #2
    if (DateTime.TryParseExact(dt, "MM/dd/yyyy hh:mm:ss tt", enUS, DateTimeStyles.None, out dateValue))
        return dateValue;

    // Scenario #3
    if (DateTime.TryParseExact(dt, "yyyy-MM-dd hh:mm:ss", enUS, DateTimeStyles.None, out dateValue))
        return dateValue;

    throw new SomeException("Don't know how to parse...");
}

EDITAR Como señala Matt Johnson, DateTime.TryParseExact acepta una matriz de cadenas de formato. 2 y 3 podrían condensarse.

public DateTime ParseRequestDate()
{
    // https://stackoverflow.com/questions/2883576/how-do-you-convert-epoch-time-in-c

    CultureInfo enUS = new CultureInfo("en-US");

    var dt = "1374755180";
    //var dt = "7/25/2013 6:37:31 PM";
    //var dt = "2013-07-25 14:26:00";

    DateTime dateValue;
    long dtLong;

    // Scenario #1
    if (long.TryParse(dt, out dtLong))
        return dtLong.FromUnixTime();

    // Scenario #2 & #3
    var formatStrings = new string[] { "MM/dd/yyyy hh:mm:ss tt", "yyyy-MM-dd hh:mm:ss" };
    if (DateTime.TryParseExact(dt, formatStrings, enUS, DateTimeStyles.None, out dateValue))
        return dateValue;

    throw new SomeException("Don't know how to parse...");
}

La conversión de época la tomé prestada de otra pregunta. (Un método de extensión)

public static class MyExtensions
{
    public static DateTime FromUnixTime(this long unixTime)
    {
        var epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
        return epoch.AddSeconds(unixTime);
    }
}

Otras respuestas

Una forma de lidiar con este problema sería configurar un método de fábrica que «entienda» diferentes formatos y los analice en consecuencia.

Puede crear una cadena de –s para lidiar con este problema, pero también puede hacer una implementación «impulsada por tablas»: lo que necesita es una matriz de delegados que tomen una cadena y le digan dos cosas:ifthenelse

  • Si este delegado puede analizar o no la cadena entrante, y
  • En caso afirmativo, ¿cuál es el resultado de ese análisis, expresado como DateTime

Here is a sample implementation:

private static readonly DateParsers = new Func<string,Tuple<DateTime,bool>>[] {
    (s) => {
        long res;
        if (long.TryParse(s, out res)) {
            // The format was correct - make a DateTime,
            // and return true to indicate a successful parse
            return Tuple.Create(new DateTime(res), true);
        } else {
            // It does not matter what you put in the Item1
            // when Item2 of the tuple is set to false
            return Tuple.Create(DateTime.MinValue, false);
        }
    }
    ...
    // Add similar delegates for other formats here
};

Now your factory method could be implemented as follows:

private static bool TryParseMultiformat(string s, out DateTime res) {
    // Check all parsers in turn, looking for one returning success
    foreach (var p in DateParsers) {
        var tmp = p(s);
        if (tmp.Item2) {
            res = tmp.Item1;
            return true;
        }
    }
    res = DateTime.MinValue;
    return false;
}

Deja un comentario