24hr至12hr时间转换,将字符插入字符串 [英] 24hr to 12hr time convert, insert character to string

查看:136
本文介绍了24hr至12hr时间转换,将字符插入字符串的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是我的问题的第二个问题,此处

This is sort of a secondary question to my question here but it was suggested split the questions up for a better response.

我有如下几行数据,分别传递给函数。

I have individual lines of data like the following that a passed to the function separately.

Mon-Wed 930-1700 Thu 900-1700 Fri 930-1700  
Mon-Wed 930-1700 Thu 900-1700 Fri 930-1700 Sat 900-1200, Home Lending Sat 900-1600  
Mon-Thu 900-1600, Fri 900-1700  

,并需要将其读取,例如:

And need it to read as follows for example:

Mon-Wed 9:30am-5:00pm;Thu 9:00am-5:00pm;Fri 9:30am-5:00pm;Sat 9:00am-12:00pm, Home Lending Sat 9:00am-4:00pm

我需要将时间转换为12小时,这相对容易,例如

I need to convert the time to 12hour time instead which is relatively easy with something like

if (time > 1200) {  
    time = time - 1200
    //add the pm and the colon :
} else {
   //add the am and the colon :
}

我的问题是,我该怎么做:

-首先要查找数字。

-将它们拉出并转换为int以执行计算(使用我认为intValue。)

-进行计算并将其插入到字符串的相同位置,包括上午/下午和冒号。

My question is, how do I:
- first seek to find the numbers.
- pull them out and convert to int to perform calculations (using intValue I think).
- do calculation and insert them back into the same position of the string including the am/pm and the colon.

我一直在使用RegexKitLite的regex,但是我如何记住将其重新插入字符串的方式,以及如何从中删除已有的内容呢?要替换的字符串吗?例如1700。我假设使用MutableStrings,但需要一些帮助。

I have been giving it a go with regex from RegexKitLite but how do I remember where to insert it back into the string and also how do I remove what is already there from the string to replace it? eg the 1700. I assume using MutableStrings but need a bit of help.

这是我一直在努力的一些代码,但不介意是否有更简单的解决方案

Here is some code I have been working on but wouldn't mind if there was an easier solution that meant chucking this away...

NSString *regexString = @"(\\s|-?)(\\d{3,4})(;?|\\s?|-?)";

NSRange matchedRange = NSMakeRange(NSNotFound,NSNotFound);

//loop while we haven't fixed all times in the string
while (!matchedRange.length == 0) {

    matchedRange = [openingHoursString rangeOfRegex:regexString capture: 2];

    if (!matchedRange.length == 0) {

        NSString *digits = [openingHoursStrinig substringWithRange: matchedRange];
        NSLog(@"digits string: %@", digits);

        //do calculations and add colon to digits string and reinsert to openingHoursString
    }
}


推荐答案

一种方法是通过RegexKitLites块支持:

One way to do it is via RegexKitLites Blocks support:

NSString *string = @"Mon-Wed 930-1700 Thu 900-1700 Fri 930-1700\nMon-Wed 930-1700 Thu 900-1700 Fri 930-1700 Sat 900-1200, Home Lending Sat 900-1600\nMon-Thu 900-1600, Fri 900-1700";

NSString *replaced = [string stringByReplacingOccurrencesOfRegex:@"(?<=[[:Pattern_Syntax:][:White_Space:]]|\\A)(\\d{1,2})(\\d{2,2})(?=[[:Pattern_Syntax:][:White_Space:]]|\\z)" usingBlock:^NSString *(NSInteger captureCount, NSString * const capturedStrings[captureCount], const NSRange capturedRanges[captureCount], volatile BOOL * const stop) {
  NSInteger hour = [capturedStrings[1] integerValue];
  NSString *amOrPMString = @"am";
  if(hour >= 12) { amOrPMString = @"pm"; if(hour > 12) { hour -= 12; } }

  return([NSString stringWithFormat:@"%d:%@%@", hour, capturedStrings[2], amOrPMString]);
}];

NSLog(@"Replaced:\n%@", replaced);

运行时,打印出以下内容:

When run, prints out the following:

2010-07-10 17:42:10.650 RegexKitLite[26086:a0f] Replaced:
Mon-Wed 9:30am-5:00pm Thu 9:00am-5:00pm Fri 9:30am-5:00pm
Mon-Wed 9:30am-5:00pm Thu 9:00am-5:00pm Fri 9:30am-5:00pm Sat 9:00am-12:00pm, Home Lending Sat 9:00am-4:00pm
Mon-Thu 9:00am-4:00pm, Fri 9:00am-5:00pm

编辑2010/07/11 -根据OP的请求添加信息。

EDIT 2010/07/11 - Add info per OP's request.

正则表达式的解释示例中使用的代码如下(细分为四个最逻辑的块)

An explanation of the regex used in the example is as follows (broken down in to its four most logical chunks)

1: (?<=[[:Pattern_Syntax:][:White_Space:]]|\A)
2: (\d{1,2})
3: (\d{2,2})
4: (?=[[:Pattern_Syntax:][:White_Space:]]|\z)



第1部分



序列(?< = ...)的意思是向后看断言,或者在散文中,它大致翻译成如果...的下一部分正则表达式(在这种情况下为#2),则紧靠#2之前的文本必须与这些括号括起来的正则表达式进行匹配。​​

Part 1

The sequence (?<= ... ) means "A look-behind assertion", or in prose, it roughly translates in to something along the lines of "If the next part of the regex (in this case, #2), then the text just before #2 must be matched by the regex enclosed by these parenthesis".

由这些括号包围的正则表达式括号在这种情况下是 [[:Pattern_Syntax:] [:White_Space:]] | \A 。这个正则表达式在粗略的散文中说匹配具有Pattern_Syntax或White_Space或 \A 的Unicode属性的字符集中的任何字符,这意味着在输入的开头匹配。与$ A中的^不同,在输入中换行后将不匹配。 Pattern_Syntax White_Space 的字符是诸如''(一个空格),'\t'(标签),换行符等。 Pattern_Syntax 是类似'-',',','%'等的字符。

The regex "enclosed by these parenthesis" in this case is [[:Pattern_Syntax:][:White_Space:]]|\A. This regex says in rough prose 'Match any character that is in the set of characters that have the Unicode property of Pattern_Syntax or White_Space, or \A, which means Match at the beginning of the input. Differs from ^ in that \A will not match after a new-line within the input.. The characters that are Pattern_Syntax or White_Space are characters such as ' ' (a space), '\t' (a tab), new-lines, etc etc. Pattern_Syntax are characters like '-', ',', '%', etc.

这些部分相当明显。 \d 匹配一个数字字符,例如'0'..'9',而 {x,y} 的意思是匹配至少 x 次,但不超过 y 次。

These parts are fairly obvious. The \d matches a "digit" character, like '0'..'9', and the {x,y} means "Match at least x, but not more than y times".

第4部分与第1部分基本相同,不同之处在于,它使用了以下形式的预见断言 (?= ,从第1部分中的解释来看,含义应该很明显。另一个区别是使用 \z ,表示如果当前位置在输入结尾处则匹配。。

Part 4 is essentially identical to part one, except it uses a "look-ahead assertion" in the form of (?=, and the meaning should hopefully be obvious from the context of the explanation in part 1. Another difference is the use of \z, which means "Match if the current position is at the end of input.".

为什么 \A \z 是否需要?如果时间是字符串中的第一件事,或者时间是 [] 要匹配的字符集不包括或者如果要匹配的文本的开头或末尾不包含任何字符。例如,OP的示例字符串以 ...,星期五900-1700 。如果没有 | \z ,则正则表达式将与最后一个不匹配 1700

Why are \A and \z needed? In case the time is the very first thing in the string, or the very last thing in the string since the [] set of characters to match does not include "or no character if at either the start or end of the text to match". For example, the OP's example strings ends with ..., Fri 900-1700. Without the |\z, the regex would not match that last 1700.

为什么需要第1部分和第4部分?它们可能不是,取决于要匹配的文本字符串的确切格式。由于我对输入字符串的格式说的不多,因此我尝试使它相当健壮并且可以承受各种合理的输入。肯定有多种方法可以做到这一点。

Why are parts 1 and parts 4 needed? They may not be, depending on the exact format of the text string to be matched. Since I can't say much about the format of the input string, I tried to make it "fairly robust" and tolerant of a wide range of reasonable input. There's definitely more than one way to do this.

^ {} 每次匹配正则表达式时都会调用该块。有关匹配内容的详细信息作为参数传递给块。然后,Block返回一个新字符串,该字符串用于替换正则表达式匹配的所有文本。重复此过程,直到字符串中不再有正则表达式匹配为止。

The ^{} Block is called each time the regular expression is matched. Details about what was matched are passed as arguments to the Blocks. The Block then returns a new string that is used as to replace all of the text that was matched by the regex. This process is repeated until there is no more matches of the regex in the string.

为清楚起见,原始字符串仅匹配一次。例如,给定的正则表达式实质上匹配任何形式为 NNN或 NNNN的数字。对于每个匹配项,都会调用Block,然后在最后一个匹配项之后的下一个字符处搜索原始字符串中的下一个匹配项。它不会以任何方式返回或重新开始。

For clarity, the original string is only "matched once". For example, the regex given essentially matches any "number" in the form of "NNN" or "NNNN". For each match, the Block is called, and then the search for the next match in the original string picks up at the very next character after the last match. It does not "go back" or "start over" in any way.

原始字符串不会以任何方式进行修改。而是构造了一个全新的字符串。它由匹配之间的文本和块返回的替换字符串一点一点地建立起来。完成所有替换后,将返回此字符串。

The original string is not modified in any way. Instead, an entirely new string is constructed. It is built up bit by bit from the "text in between matches" and the replacement strings returned by the Block. When all the replacements are finished, this is the string that is returned.

编辑2010/07/12 -为每个OP添加一些其他信息(附加)请求。

EDIT 2010/07/12 - Add some additional information per OP's (additional) request.

Q 如果我对输入格式的一致性(例如Day-DaySpaceTime或DaySpaceTime)更有信心,可以只是有一些这样的正则表达式? (\s |-?)(\d {1,2})(\d {2,2})(;? | \s?|-?)。

Q If I was more confident on the input format being consistent (such as Day-DaySpaceTime OR DaySpaceTime) could I just have some regex something like this? (\s|-?)(\d{1,2})(\d{2,2})(;?|\s?|-?).

A 如果您对输入格式更有信心,则可以更改正则表达式。例如,如果您绝对肯定输入将始终为 nNNN-nNNN 的形式(小写的 n 表示可选数字,例如 900-1730 1100-1915 )对于时间,代码可以更改为以下内容:

A If you were more confident on the input format, the regex could definitely be changed. For example, if you were "absolutely positive" that the input was always going to be in the form of nNNN-nNNN (where the lower case n represents "an optional digit", as in 900-1730 vs 1100-1915) for "times", the code could be changed to something like:

NSString *string = @"Mon-Wed 930-1700 Thu 900-1700 Fri 930-1700\nMon-Wed 930-1700 Thu 900-1700 Fri 930-1700 Sat 900-1200, Home Lending Sat 900-1600\nMon-Thu 900-1600, Fri 900-1700";

NSString *replaced = [string stringByReplacingOccurrencesOfRegex:@"\\b(\\d{1,2})(\\d{2,2})\\-(\\d{1,2})(\\d{2,2})\\b" usingBlock:^NSString *(NSInteger captureCount, NSString * const capturedStrings[captureCount], const NSRange capturedRanges[captureCount], volatile BOOL * const stop) {
  NSInteger firstHour = [capturedStrings[1] integerValue], secondHour = [capturedStrings[3] integerValue];
  NSString *firstAMorPMString = @"am", *secondAMorPMString = @"am";

  if(firstHour >= 12) { firstAMorPMString = @"pm"; if(firstHour > 12) { firstHour -= 12; } }
  if(secondHour >= 12) { secondAMorPMString = @"pm"; if(secondHour > 12) { secondHour -= 12; } }
  if(firstHour == 0) { firstHour = 12; }
  if(secondHour == 0) { secondHour = 12; }

  return([NSString stringWithFormat:@"%d:%@%@-%d:%@%@", firstHour, capturedStrings[2], firstAMorPMString, secondHour, capturedStrings[4], secondAMorPMString]);
}];

NSLog(@"Replaced:\n%@", replaced);

此示例将两个时间作为单个块进行处理。正则表达式开头和结尾的 \b 表示如果当前位置是单词边界则匹配。这样可以防止它匹配 abc123-456def 之类的内容。在原始示例中,它是更复杂的 [[:Pattern_Syntax:] [:White_Space:]] 的一种简单形式,但不一定表示完全相同

This example processes both "times" as a single chunk. The \b present at the beginning and end of the regex means Match if the current position is a word boundary. This prevents it from matching something like abc123-456def. It is a simpler form of the more complicated [[:Pattern_Syntax:][:White_Space:]] stuff in the original example, but it doesn't necessarily mean exactly the same thing (though it is fairly close "for most purposes).

将两次匹配为一个块的另一个好处是,它减少了可能的错误匹配数量如果只匹配一次,就可能发生这种情况。例如,第一个示例会将 Home econ 101的注释变成 Home econ 1:01 am,这可能不是您想要的。:)

Another advantage to matching both times as a single chunk is it reduces the number of potential "false matches" that can happen if just matching for one time. For example, the first example would turn a "comment" of "Home econ 101" in to "Home econ 1:01am", which is probably not what you want. :)

我还修改了示例,使 24小时军用时间为 000表示 12:00 am,因此它假定解析的时间值始终在24小时军用时间格式。

I also modified the example so that a "military 24 hour time" of "000" means "12:00am", so it makes an assumption that the time values parsed are always in 24 hour military time format.

Q 这也是RegexKitLite语法部分的(?< = ...)外观还是标准正则表达式?

Q Also is the (?<= ... ) look behind syntax part of RegexKitLite or is that standard regex?

A 是ICU库接受的正则表达式语法的一部分(RegexKi是tLite用于执行实际的正则表达式匹配)。尽管(?< = ...)(?= ... )被大多数正则表达式引擎接受。

A It is part of the regex syntax accepted by the ICU library (which is what RegexKitLite uses to perform the actual regular expression matching). There is no "standard regular expression syntax" per-se, though both (?<=...) and (?=...) are accepted by "most" regular expression engines.

Q 抱歉,在您的正则表达式中,您有四组()的意思是否意味着存在一个captureStrings [0],capturedStrings [1],capturedStrings [2],capturedStrings [3]?

Q Sorry, In your regex you had four sets of () does that mean that there is a capturedStrings[0],capturedStrings[1],capturedStrings[2],capturedStrings[3]?

A (?< = ...)(?= ...)模式是什么被称为零宽度断言。它们实际上并不对正则表达式捕获的文本有帮助,但是必须匹配给定的文本才能使整个正则表达式匹配。上一句话中的捕获和匹配之间的区别在于,捕获消耗了输入的匹配部分,而匹配则没有。这样,您就可以创建正则表达式,例如(\d +)(?=,),这意味着匹配并'捕获'一个或多个数字,必须在其后跟一个',',但不捕获结尾的逗号。先行查找和后向查找绝对是正则表达式的高级,非新颖特征,很难在此类简短文章中充分解释。

A The (?<=...) and (?=...) patterns are what are known as "zero width assertions". They do not actually contribute to the text that is "captured" by the regular expression, but must match the given text in order for the overall regular expression to "match". The distinction between the words "captured" and "match" in the previous sentence is that "captured" consumes the part of the input matched, whereas "matched" does not. This allows you to create regular expressions like (\d+)(?=,), which means "Match and 'capture' one or more numbers which must be followed by a ',', but do not capture the trailing comma". Look-ahead and look-behind are definitely advanced, non-novice features of regular expressions which are difficult to explain fully in a short post like this.

特别要注意的是,但是,(?< = ...)(?= ...)都不算捕获,与(\d {1,2})(\d {2,2})不同。即使总共有四个括号组,原始示例中的完整正则表达式也只包含两个捕获。

Of particular note, however, is that neither (?<=...) or (?=...) count as "captures", unlike (\d{1,2})(\d{2,2}). The full regular expression from the original example contains only two captures even though there are a total of four parenthesis groups.

这篇关于24hr至12hr时间转换,将字符插入字符串的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆