任何 Smalltalk 方言中的时间格式 (HH:MM:SS)

Time formatting (HH:MM:SS) in any Smalltalk dialect

我有三个整数值,比方说

h := 3.
m := 19.
s := 8.

我想生成字符串 '03:19:08'。我知道如何将数字转换为字符串,甚至在必要时用零填充它。因此,作为第一步,我写了这个绝对可怕的代码:

h < 10 ifTrue: [hs := '0', (h asString)] ifFalse: [hs := h asString].
m < 10 ifTrue: [ms := '0', (m asString)] ifFalse: [ms := m asString].
s < 10 ifTrue: [ss := '0', (s asString)] ifFalse: [ss := s asString].
Transcript show: hs, ':', ms, ':', ss.
Transcript nl.

现在显然我需要清理它,所以我想知道这里最惯用的 Smalltalk 方法是什么。会不会像(显然不是合法的 Smalltalk):

aCollectionWithHMS each [c | padWithZero] join ':'

我发现了一个关于使用带有 separatedBy 参数的打印方法的流的讨论,但是难道没有更简单的方法来处理字符串吗?

或者也许有更优雅的方法来填充三个组件然后我可以 return hs, ':', ms, ':', ss ?

或者,是否有所有 Smalltalks 通用的 POSIX 时间格式(或类似的东西)接口?我知道 GNU Smalltalk 可以 link 到 C,但是对于这个简单的问题恕我直言,这太过分了。

编辑

我靠近了一点:

z := {h . m . s} collect: [:c | c < 10 ifTrue: ['0', c asString] ifFalse: [c asString]].
(Transcript show: ((z at: 1), ':',  (z at: 2), ':', (z at: 3))) nl.

但是集合元素的直接访问让我很难过。我找到了 page documenting the joining method asStringWith 但该方法不受支持,它似乎在 GNU Smalltalk 中。

这是在 Pharo 中执行此操作的一种方法:

String streamContents: [:stream |
  {h.m.s}
    do: [:token | token printOn: stream base: 10 nDigits: 2]
    separatedBy: [stream nextPut: $:]]

解释:

  1. streamContents: 消息用正式块参数 stream 表示的 WriteStream 的内容进行应答。

  2. do:separatedBy: 消息枚举了令牌 hms 为每个令牌评估 do: 块,并且在连续的标记之间插入第二个块的评估。

  3. printOn:base:nDigits: 消息转储到 stream 基础 10 表示 token 填充到 2 数字。

如果您使用的方言没有 printOn:base:nDigits: 方法(或其任何适当的变体),您可以执行以下操作:

String streamContents: [:stream |
  {h.m.s}
    do: [:token |
      token < 10 ifTrue: [stream nextPut: [=11=]].
      stream nextPutAll: token asString]
    separatedBy: [stream nextPut: $:]]

最后,如果你认为你会经常使用它,我建议将消息​​ hhmmss 添加到 Time(实例端),如上所示用 self hours 实现的h,等等。然后就是发送

的问题
(Time hour: h minute: m second: s) hhmmss

假设您拥有这三个量而不是 Time 对象,这将是不寻常的。否则,你只需要像

这样的东西
aTime hhmmss

附录

这是适用于任何方言的另一种方法:

{h.m.s}
  inject: ''
  into: [:r :t | | pad colon |
    pad := t < 10 ifTrue: ['0'] ifFalse: [''].
    colon := r isEmpty ifTrue: [''] ifFalse: [':'].
    r , colon, pad, t asString]

inject:into: 方法从 inject: 参数(在本例中为空 String)构建其结果,并不断用值替换正式块参数 r上一次迭代的。第二个正式参数 t 替换为每次迭代的相应元素。


附录 2

time := '00:00:00' copy.
{h asString. m asString. s asString} withIndexDo: [:t :i |
  time at: i - 1 * 3 + 2 put: t last.
  t size = 2 ifTrue: [time at: i - 1 * 3 + 1 put: t first]].
^time

copy 是确保文字未被修改所必需的。