Определите, является ли String действительной датой перед анализом

Используйте приведенный ниже метод для установки правильной ориентации в соответствии с ориентацией видеообъекта в AVMutableVideoComposition

-(AVMutableVideoComposition *) getVideoComposition:(AVAsset *)asset
{
  AVAssetTrack *videoTrack = [[asset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0];
  AVMutableComposition *composition = [AVMutableComposition composition];
  AVMutableVideoComposition *videoComposition = [AVMutableVideoComposition videoComposition];
  CGSize videoSize = videoTrack.naturalSize;
  BOOL isPortrait_ = [self isVideoPortrait:asset];
  if(isPortrait_) {
      NSLog(@"video is portrait ");
      videoSize = CGSizeMake(videoSize.height, videoSize.width);
  }
  composition.naturalSize     = videoSize;
  videoComposition.renderSize = videoSize;
  // videoComposition.renderSize = videoTrack.naturalSize; //
  videoComposition.frameDuration = CMTimeMakeWithSeconds( 1 / videoTrack.nominalFrameRate, 600);

  AVMutableCompositionTrack *compositionVideoTrack;
  compositionVideoTrack = [composition addMutableTrackWithMediaType:AVMediaTypeVideo preferredTrackID:kCMPersistentTrackID_Invalid];
  [compositionVideoTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, asset.duration) ofTrack:videoTrack atTime:kCMTimeZero error:nil];
  AVMutableVideoCompositionLayerInstruction *layerInst;
  layerInst = [AVMutableVideoCompositionLayerInstruction videoCompositionLayerInstructionWithAssetTrack:videoTrack];
  [layerInst setTransform:videoTrack.preferredTransform atTime:kCMTimeZero];
  AVMutableVideoCompositionInstruction *inst = [AVMutableVideoCompositionInstruction videoCompositionInstruction];
  inst.timeRange = CMTimeRangeMake(kCMTimeZero, asset.duration);
  inst.layerInstructions = [NSArray arrayWithObject:layerInst];
  videoComposition.instructions = [NSArray arrayWithObject:inst];
  return videoComposition;
}


-(BOOL) isVideoPortrait:(AVAsset *)asset
{
  BOOL isPortrait = FALSE;
  NSArray *tracks = [asset tracksWithMediaType:AVMediaTypeVideo];
  if([tracks    count] > 0) {
    AVAssetTrack *videoTrack = [tracks objectAtIndex:0];

    CGAffineTransform t = videoTrack.preferredTransform;
    // Portrait
    if(t.a == 0 && t.b == 1.0 && t.c == -1.0 && t.d == 0)
    {
        isPortrait = YES;
    }
    // PortraitUpsideDown
    if(t.a == 0 && t.b == -1.0 && t.c == 1.0 && t.d == 0)  {

        isPortrait = YES;
    }
    // LandscapeRight
    if(t.a == 1.0 && t.b == 0 && t.c == 0 && t.d == 1.0)
    {
        isPortrait = NO;
    }
    // LandscapeLeft
    if(t.a == -1.0 && t.b == 0 && t.c == 0 && t.d == -1.0)
    {
        isPortrait = NO;
    }
   }
  return isPortrait;
}
13
задан Morgul Master 7 June 2009 в 22:20
поделиться

10 ответов

См. Ленивая обработка ошибок в Java для обзора того, как исключить блоки try / catch с использованием типа Option .

Функциональная Java - ваш друг.

По сути, вы хотите заключить синтаксический анализ даты в функцию, которая ничего не генерирует, но указывает в своем возвращаемом типе, был ли синтаксический анализ успешным или нет. Например:

import fj.F; import fj.F2;
import fj.data.Option;
import java.text.SimpleDateFormat;
import java.text.ParseException;
import static fj.Function.curry;
import static fj.Option.some;
import static fj.Option.none;
...

F<String, F<String, Option<Date>>> parseDate =
  curry(new F2<String, String, Option<Date>>() {
    public Option<Date> f(String pattern, String s) {
      try {
        return some(new SimpleDateFormat(pattern).parse(s));
      }
      catch (ParseException e) {
        return none();
      }
    }
  });

Хорошо, теперь у вас есть многоразовый синтаксический анализатор даты, который ничего не выдает, но указывает на сбой, возвращая значение типа Option.None . Вот как вы его используете:

import fj.data.List;
import static fj.data.Stream.stream;
import static fj.data.Option.isSome_;
....
public Option<Date> parseWithPatterns(String s, Stream<String> patterns) { 
  return stream(s).apply(patterns.map(parseDate)).find(isSome_()); 
}

Это даст вам дату, проанализированную с первым совпадающим шаблоном, или значение типа Option.None, которое является типобезопасным, тогда как null - нет.

Если вы интересно, что такое Stream ... it ' в ленивом списке . Это гарантирует, что вы игнорируете шаблоны после первого успешного. Не нужно делать слишком много работы.

Назовите свою функцию так:

for (Date d: parseWithPatterns(someString, stream("dd/MM/yyyy", "dd-MM-yyyy")) {
  // Do something with the date here.
}

Или ...

Option<Date> d = parseWithPatterns(someString,
                                   stream("dd/MM/yyyy", "dd-MM-yyyy"));
if (d.isNone()) {
  // Handle the case where neither pattern matches.
} 
else {
  // Do something with d.some()
}
7
ответ дан 1 December 2019 в 19:08
поделиться

Не относитесь к себе слишком строго, используя try-catch в логике: это одна из тех ситуаций, когда Java вынуждает вас делать это, так что вы мало что можете с этим поделать.

Но в этом случае вы можете вместо этого использовать DateFormat.parse (String, ParsePosition) .

7
ответ дан 1 December 2019 в 19:08
поделиться

Вы можете воспользоваться регулярными выражениями, чтобы определить, в каком формате находится строка и соответствует ли она какому-либо допустимому формату. Примерно так (не проверено):

(К сожалению, я написал это на C #, прежде чем проверять, какой язык вы используете.)

Regex test = new Regex(@"^(?:(?<formatA>\d{2}-[a-zA-Z]{3}-\d{2})|(?<formatB>\d{2}/\d{2}/\d{3}))$", RegexOption.Compiled);
Match match = test.Match(yourString);
if (match.Success)
{
    if (!string.IsNullOrEmpty(match.Groups["formatA"]))
    {
        // Use format A.
    }
    else if (!string.IsNullOrEmpty(match.Groups["formatB"]))
    {
        // Use format B.
    }
    ...
}
6
ответ дан 1 December 2019 в 19:08
поделиться

Если форматы точны (7 июня 1999 г. будет либо 07 июня 1999 г., либо 06.07.1999: вы уверены, что у вас есть ведущие нули), тогда вы можете просто проверьте длину строки перед попыткой синтаксического анализа.

Будьте осторожны с коротким названием месяца в первой версии, потому что июнь может не быть июнем на другом языке.

Но если ваши данные приходят. из одной базы данных, тогда я бы просто преобразовал все даты в общий формат (он разовый, но затем вы управляете данными и их форматом).

3
ответ дан 1 December 2019 в 19:08
поделиться

В этой ограниченной ситуации лучший (и самый быстрый метод) - это определенно проанализировать день, а затем на основе следующего символа '/' или '-' попытаться проанализировать остальные . и если в какой-то момент появятся неожиданные данные, тогда верните NULL.

3
ответ дан 1 December 2019 в 19:08
поделиться

Похоже, три варианта, если у вас есть только два известных формата:

  • проверить наличие - или / сначала и начните с этого синтаксического анализа для этого формата.
  • проверьте длину, поскольку «dd-MMM-yy» и «dd / MM / yyyy» различны
  • , используйте предварительно скомпилированные регулярные выражения

] Последнее кажется ненужным.

3
ответ дан 1 December 2019 в 19:08
поделиться

Используйте регулярные выражения для анализа вашей строки. Убедитесь, что оба регулярных выражения предварительно скомпилированы (не создавайте новые при каждом вызове метода, а сохраняете их как константы), и сравните, действительно ли оно быстрее, чем используемый вами try-catch .

Мне все еще кажется странным, что ваш метод возвращает null , если обе версии терпят неудачу, а не генерирует исключение.

2
ответ дан 1 December 2019 в 19:08
поделиться

вы можете использовать разделение, чтобы определить, какой формат использовать

String[] parts = date.split("-");
df = (parts.length==3 ? format1 : format2);

Предполагается, что все они находятся в том или ином формате, вы можете улучшить проверку, если это необходимо

2
ответ дан 1 December 2019 в 19:08
поделиться

Предполагая, что предоставленные вами шаблоны являются единственно вероятным выбором, я бы посмотрел на переданную строку, чтобы увидеть, какой формат применить.

public Date parseDate(final String date) {
  if (date == null) {
    return null;
  }

  SimpleDateFormat format = (date.charAt(2) == '/') ? new SimpleDateFormat("dd/MMM/yyyy")
                                                   : new SimpleDateFormat("dd-MMM-yy");
  try {
    return format.parse(date);
  } catch (ParseException e) {
    // Log a complaint and include date in the complaint
  }
  return null;
}

Как уже упоминали другие, если вы можете гарантировать , что вы никогда никогда не получите доступ к DateFormat в многопоточном режиме, вы можете создавать экземпляры уровня класса или статические экземпляры.

2
ответ дан 1 December 2019 в 19:08
поделиться

Альтернативой созданию SimpleDateFormat (или двух) на итерацию было бы ленивое заполнение контейнера ThreadLocal для этих форматов. Это решит как проблемы безопасности потоков, так и проблемы, связанные с производительностью создания объектов.

2
ответ дан 1 December 2019 в 19:08
поделиться
Другие вопросы по тегам:

Похожие вопросы: