Results for: "partition"

Returns a 3-element array of substrings of self.

Matches a pattern against self, scanning from the beginning. The pattern is:

If the pattern is matched, returns pre-match, first-match, post-match:

'hello'.partition('l')      # => ["he", "l", "lo"]
'hello'.partition('ll')     # => ["he", "ll", "o"]
'hello'.partition('h')      # => ["", "h", "ello"]
'hello'.partition('o')      # => ["hell", "o", ""]
'hello'.partition(/l+/)     #=> ["he", "ll", "o"]
'hello'.partition('')       # => ["", "", "hello"]
'тест'.partition('т')       # => ["", "т", "ест"]
'こんにちは'.partition('に')  # => ["こん", "に", "ちは"]

If the pattern is not matched, returns a copy of self and two empty strings:

'hello'.partition('x') # => ["hello", "", ""]

Related: String#rpartition, String#split.

With a block given, returns an array of two arrays:

Examples:

p = (1..4).partition {|i| i.even? }
p # => [[2, 4], [1, 3]]
p = ('a'..'d').partition {|c| c < 'c' }
p # => [["a", "b"], ["c", "d"]]
h = {foo: 0, bar: 1, baz: 2, bat: 3}
p = h.partition {|key, value| key.start_with?('b') }
p # => [[[:bar, 1], [:baz, 2], [:bat, 3]], [[:foo, 0]]]
p = h.partition {|key, value| value < 2 }
p # => [[[:foo, 0], [:bar, 1]], [[:baz, 2], [:bat, 3]]]

With no block given, returns an Enumerator.

Related: Enumerable#group_by.

No documentation available

Continuation objects are generated by Kernel#callcc, after having +require+d continuation. They hold a return address and execution context, allowing a nonlocal return to the end of the callcc block from anywhere within a program. Continuations are somewhat analogous to a structured version of C’s setjmp/longjmp (although they contain more state, so you might consider them closer to threads).

For instance:

require "continuation"
arr = [ "Freddie", "Herbie", "Ron", "Max", "Ringo" ]
callcc{|cc| $cc = cc}
puts(message = arr.shift)
$cc.call unless message =~ /Max/

produces:

Freddie
Herbie
Ron
Max

Also you can call callcc in other methods:

require "continuation"

def g
  arr = [ "Freddie", "Herbie", "Ron", "Max", "Ringo" ]
  cc = callcc { |cc| cc }
  puts arr.shift
  return cc, arr.size
end

def f
  c, size = g
  c.call(c) if size > 1
end

f

This (somewhat contrived) example allows the inner loop to abandon processing early:

require "continuation"
callcc {|cont|
  for i in 0..4
    print "#{i}: "
    for j in i*5...(i+1)*5
      cont.call() if j == 17
      printf "%3d", j
    end
  end
}
puts

produces:

0:   0  1  2  3  4
1:   5  6  7  8  9
2:  10 11 12 13 14
3:  15 16

OptionParser

New to OptionParser?

See the Tutorial.

Introduction

OptionParser is a class for command-line option analysis. It is much more advanced, yet also easier to use, than GetoptLong, and is a more Ruby-oriented solution.

Features

  1. The argument specification and the code to handle it are written in the same place.

  2. It can output an option summary; you don’t need to maintain this string separately.

  3. Optional and mandatory arguments are specified very gracefully.

  4. Arguments can be automatically converted to a specified class.

  5. Arguments can be restricted to a certain set.

All of these features are demonstrated in the examples below. See make_switch for full documentation.

Minimal example

require 'optparse'

options = {}
OptionParser.new do |parser|
  parser.banner = "Usage: example.rb [options]"

  parser.on("-v", "--[no-]verbose", "Run verbosely") do |v|
    options[:verbose] = v
  end
end.parse!

p options
p ARGV

Generating Help

OptionParser can be used to automatically generate help for the commands you write:

require 'optparse'

Options = Struct.new(:name)

class Parser
  def self.parse(options)
    args = Options.new("world")

    opt_parser = OptionParser.new do |parser|
      parser.banner = "Usage: example.rb [options]"

      parser.on("-nNAME", "--name=NAME", "Name to say hello to") do |n|
        args.name = n
      end

      parser.on("-h", "--help", "Prints this help") do
        puts parser
        exit
      end
    end

    opt_parser.parse!(options)
    return args
  end
end
options = Parser.parse %w[--help]

#=>
   # Usage: example.rb [options]
   #     -n, --name=NAME                  Name to say hello to
   #     -h, --help                       Prints this help

Required Arguments

For options that require an argument, option specification strings may include an option name in all caps. If an option is used without the required argument, an exception will be raised.

require 'optparse'

options = {}
OptionParser.new do |parser|
  parser.on("-r", "--require LIBRARY",
            "Require the LIBRARY before executing your script") do |lib|
    puts "You required #{lib}!"
  end
end.parse!

Used:

$ ruby optparse-test.rb -r
optparse-test.rb:9:in `<main>': missing argument: -r (OptionParser::MissingArgument)
$ ruby optparse-test.rb -r my-library
You required my-library!

Type Coercion

OptionParser supports the ability to coerce command line arguments into objects for us.

OptionParser comes with a few ready-to-use kinds of type coercion. They are:

We can also add our own coercions, which we will cover below.

Using Built-in Conversions

As an example, the built-in Time conversion is used. The other built-in conversions behave in the same way. OptionParser will attempt to parse the argument as a Time. If it succeeds, that time will be passed to the handler block. Otherwise, an exception will be raised.

require 'optparse'
require 'optparse/time'
OptionParser.new do |parser|
  parser.on("-t", "--time [TIME]", Time, "Begin execution at given time") do |time|
    p time
  end
end.parse!

Used:

$ ruby optparse-test.rb  -t nonsense
... invalid argument: -t nonsense (OptionParser::InvalidArgument)
$ ruby optparse-test.rb  -t 10-11-12
2010-11-12 00:00:00 -0500
$ ruby optparse-test.rb  -t 9:30
2014-08-13 09:30:00 -0400

Creating Custom Conversions

The accept method on OptionParser may be used to create converters. It specifies which conversion block to call whenever a class is specified. The example below uses it to fetch a User object before the on handler receives it.

require 'optparse'

User = Struct.new(:id, :name)

def find_user id
  not_found = ->{ raise "No User Found for id #{id}" }
  [ User.new(1, "Sam"),
    User.new(2, "Gandalf") ].find(not_found) do |u|
    u.id == id
  end
end

op = OptionParser.new
op.accept(User) do |user_id|
  find_user user_id.to_i
end

op.on("--user ID", User) do |user|
  puts user
end

op.parse!

Used:

$ ruby optparse-test.rb --user 1
#<struct User id=1, name="Sam">
$ ruby optparse-test.rb --user 2
#<struct User id=2, name="Gandalf">
$ ruby optparse-test.rb --user 3
optparse-test.rb:15:in `block in find_user': No User Found for id 3 (RuntimeError)

Store options to a Hash

The into option of order, parse and so on methods stores command line options into a Hash.

require 'optparse'

options = {}
OptionParser.new do |parser|
  parser.on('-a')
  parser.on('-b NUM', Integer)
  parser.on('-v', '--verbose')
end.parse!(into: options)

p options

Used:

$ ruby optparse-test.rb -a
{:a=>true}
$ ruby optparse-test.rb -a -v
{:a=>true, :verbose=>true}
$ ruby optparse-test.rb -a -b 100
{:a=>true, :b=>100}

Complete example

The following example is a complete Ruby program. You can run it and see the effect of specifying various options. This is probably the best way to learn the features of optparse.

require 'optparse'
require 'optparse/time'
require 'ostruct'
require 'pp'

class OptparseExample
  Version = '1.0.0'

  CODES = %w[iso-2022-jp shift_jis euc-jp utf8 binary]
  CODE_ALIASES = { "jis" => "iso-2022-jp", "sjis" => "shift_jis" }

  class ScriptOptions
    attr_accessor :library, :inplace, :encoding, :transfer_type,
                  :verbose, :extension, :delay, :time, :record_separator,
                  :list

    def initialize
      self.library = []
      self.inplace = false
      self.encoding = "utf8"
      self.transfer_type = :auto
      self.verbose = false
    end

    def define_options(parser)
      parser.banner = "Usage: example.rb [options]"
      parser.separator ""
      parser.separator "Specific options:"

      # add additional options
      perform_inplace_option(parser)
      delay_execution_option(parser)
      execute_at_time_option(parser)
      specify_record_separator_option(parser)
      list_example_option(parser)
      specify_encoding_option(parser)
      optional_option_argument_with_keyword_completion_option(parser)
      boolean_verbose_option(parser)

      parser.separator ""
      parser.separator "Common options:"
      # No argument, shows at tail.  This will print an options summary.
      # Try it and see!
      parser.on_tail("-h", "--help", "Show this message") do
        puts parser
        exit
      end
      # Another typical switch to print the version.
      parser.on_tail("--version", "Show version") do
        puts Version
        exit
      end
    end

    def perform_inplace_option(parser)
      # Specifies an optional option argument
      parser.on("-i", "--inplace [EXTENSION]",
                "Edit ARGV files in place",
                "(make backup if EXTENSION supplied)") do |ext|
        self.inplace = true
        self.extension = ext || ''
        self.extension.sub!(/\A\.?(?=.)/, ".")  # Ensure extension begins with dot.
      end
    end

    def delay_execution_option(parser)
      # Cast 'delay' argument to a Float.
      parser.on("--delay N", Float, "Delay N seconds before executing") do |n|
        self.delay = n
      end
    end

    def execute_at_time_option(parser)
      # Cast 'time' argument to a Time object.
      parser.on("-t", "--time [TIME]", Time, "Begin execution at given time") do |time|
        self.time = time
      end
    end

    def specify_record_separator_option(parser)
      # Cast to octal integer.
      parser.on("-F", "--irs [OCTAL]", OptionParser::OctalInteger,
                "Specify record separator (default \\0)") do |rs|
        self.record_separator = rs
      end
    end

    def list_example_option(parser)
      # List of arguments.
      parser.on("--list x,y,z", Array, "Example 'list' of arguments") do |list|
        self.list = list
      end
    end

    def specify_encoding_option(parser)
      # Keyword completion.  We are specifying a specific set of arguments (CODES
      # and CODE_ALIASES - notice the latter is a Hash), and the user may provide
      # the shortest unambiguous text.
      code_list = (CODE_ALIASES.keys + CODES).join(', ')
      parser.on("--code CODE", CODES, CODE_ALIASES, "Select encoding",
                "(#{code_list})") do |encoding|
        self.encoding = encoding
      end
    end

    def optional_option_argument_with_keyword_completion_option(parser)
      # Optional '--type' option argument with keyword completion.
      parser.on("--type [TYPE]", [:text, :binary, :auto],
                "Select transfer type (text, binary, auto)") do |t|
        self.transfer_type = t
      end
    end

    def boolean_verbose_option(parser)
      # Boolean switch.
      parser.on("-v", "--[no-]verbose", "Run verbosely") do |v|
        self.verbose = v
      end
    end
  end

  #
  # Return a structure describing the options.
  #
  def parse(args)
    # The options specified on the command line will be collected in
    # *options*.

    @options = ScriptOptions.new
    @args = OptionParser.new do |parser|
      @options.define_options(parser)
      parser.parse!(args)
    end
    @options
  end

  attr_reader :parser, :options
end  # class OptparseExample

example = OptparseExample.new
options = example.parse(ARGV)
pp options # example.options
pp ARGV

Shell Completion

For modern shells (e.g. bash, zsh, etc.), you can use shell completion for command line options.

Further documentation

The above examples, along with the accompanying Tutorial, should be enough to learn how to use this class. If you have any questions, file a ticket at bugs.ruby-lang.org.

Raised to stop the iteration, in particular by Enumerator#next. It is rescued by Kernel#loop.

loop do
  puts "Hello"
  raise StopIteration
  puts "World"
end
puts "Done!"

produces:

Hello
Done!

Class Exception and its subclasses are used to indicate that an error or other problem has occurred, and may need to be handled. See Exceptions.

An Exception object carries certain information:

Built-In Exception Class Hierarchy

The hierarchy of built-in subclasses of class Exception:

Raised when a signal is received.

begin
  Process.kill('HUP',Process.pid)
  sleep # wait for receiver to handle signal sent by Process.kill
rescue SignalException => e
  puts "received Exception #{e}"
end

produces:

received Exception SIGHUP

A rational number can be represented as a pair of integer numbers: a/b (b>0), where a is the numerator and b is the denominator. Integer a equals rational a/1 mathematically.

You can create a Rational object explicitly with:

You can convert certain objects to Rationals with:

Examples

Rational(1)      #=> (1/1)
Rational(2, 3)   #=> (2/3)
Rational(4, -6)  #=> (-2/3) # Reduced.
3.to_r           #=> (3/1)
2/3r             #=> (2/3)

You can also create rational objects from floating-point numbers or strings.

Rational(0.3)    #=> (5404319552844595/18014398509481984)
Rational('0.3')  #=> (3/10)
Rational('2/3')  #=> (2/3)

0.3.to_r         #=> (5404319552844595/18014398509481984)
'0.3'.to_r       #=> (3/10)
'2/3'.to_r       #=> (2/3)
0.3.rationalize  #=> (3/10)

A rational object is an exact number, which helps you to write programs without any rounding errors.

10.times.inject(0) {|t| t + 0.1 }              #=> 0.9999999999999999
10.times.inject(0) {|t| t + Rational('0.1') }  #=> (1/1)

However, when an expression includes an inexact component (numerical value or operation), it will produce an inexact result.

Rational(10) / 3   #=> (10/3)
Rational(10) / 3.0 #=> 3.3333333333333335

Rational(-8) ** Rational(1, 3)
                   #=> (1.0000000000000002+1.7320508075688772i)

Raised when a feature is not implemented on the current platform. For example, methods depending on the fsync or fork system calls may raise this exception if the underlying operating system or Ruby runtime does not support them.

Note that if fork raises a NotImplementedError, then respond_to?(:fork) returns false.

A generic error class raised when an invalid operation is attempted. Kernel#raise will raise a RuntimeError if no Exception class is specified.

raise "ouch"

raises the exception:

RuntimeError: ouch

DateTime

A subclass of Date that easily handles date, hour, minute, second, and offset.

DateTime class is considered deprecated. Use Time class.

DateTime does not consider any leap seconds, does not track any summer time rules.

A DateTime object is created with DateTime::new, DateTime::jd, DateTime::ordinal, DateTime::commercial, DateTime::parse, DateTime::strptime, DateTime::now, Time#to_datetime, etc.

require 'date'

DateTime.new(2001,2,3,4,5,6)
                    #=> #<DateTime: 2001-02-03T04:05:06+00:00 ...>

The last element of day, hour, minute, or second can be a fractional number. The fractional number’s precision is assumed at most nanosecond.

DateTime.new(2001,2,3.5)
                    #=> #<DateTime: 2001-02-03T12:00:00+00:00 ...>

An optional argument, the offset, indicates the difference between the local time and UTC. For example, Rational(3,24) represents ahead of 3 hours of UTC, Rational(-5,24) represents behind of 5 hours of UTC. The offset should be -1 to +1, and its precision is assumed at most second. The default value is zero (equals to UTC).

DateTime.new(2001,2,3,4,5,6,Rational(3,24))
                    #=> #<DateTime: 2001-02-03T04:05:06+03:00 ...>

The offset also accepts string form:

DateTime.new(2001,2,3,4,5,6,'+03:00')
                    #=> #<DateTime: 2001-02-03T04:05:06+03:00 ...>

An optional argument, the day of calendar reform (start), denotes a Julian day number, which should be 2298874 to 2426355 or negative/positive infinity. The default value is Date::ITALY (2299161=1582-10-15).

A DateTime object has various methods. See each reference.

d = DateTime.parse('3rd Feb 2001 04:05:06+03:30')
                    #=> #<DateTime: 2001-02-03T04:05:06+03:30 ...>
d.hour              #=> 4
d.min               #=> 5
d.sec               #=> 6
d.offset            #=> (7/48)
d.zone              #=> "+03:30"
d += Rational('1.5')
                    #=> #<DateTime: 2001-02-04%16:05:06+03:30 ...>
d = d.new_offset('+09:00')
                    #=> #<DateTime: 2001-02-04%21:35:06+09:00 ...>
d.strftime('%I:%M:%S %p')
                    #=> "09:35:06 PM"
d > DateTime.new(1999)
                    #=> true

When should you use DateTime and when should you use Time?

It’s a common misconception that William Shakespeare and Miguel de Cervantes died on the same day in history - so much so that UNESCO named April 23 as World Book Day because of this fact. However, because England hadn’t yet adopted the Gregorian Calendar Reform (and wouldn’t until 1752) their deaths are actually 10 days apart. Since Ruby’s Time class implements a proleptic Gregorian calendar and has no concept of calendar reform there’s no way to express this with Time objects. This is where DateTime steps in:

shakespeare = DateTime.iso8601('1616-04-23', Date::ENGLAND)
 #=> Tue, 23 Apr 1616 00:00:00 +0000
cervantes = DateTime.iso8601('1616-04-23', Date::ITALY)
 #=> Sat, 23 Apr 1616 00:00:00 +0000

Already you can see something is weird - the days of the week are different. Taking this further:

cervantes == shakespeare
 #=> false
(shakespeare - cervantes).to_i
 #=> 10

This shows that in fact they died 10 days apart (in reality 11 days since Cervantes died a day earlier but was buried on the 23rd). We can see the actual date of Shakespeare’s death by using the gregorian method to convert it:

shakespeare.gregorian
 #=> Tue, 03 May 1616 00:00:00 +0000

So there’s an argument that all the celebrations that take place on the 23rd April in Stratford-upon-Avon are actually the wrong date since England is now using the Gregorian calendar. You can see why when we transition across the reform date boundary:

# start off with the anniversary of Shakespeare's birth in 1751
shakespeare = DateTime.iso8601('1751-04-23', Date::ENGLAND)
 #=> Tue, 23 Apr 1751 00:00:00 +0000

# add 366 days since 1752 is a leap year and April 23 is after February 29
shakespeare + 366
 #=> Thu, 23 Apr 1752 00:00:00 +0000

# add another 365 days to take us to the anniversary in 1753
shakespeare + 366 + 365
 #=> Fri, 04 May 1753 00:00:00 +0000

As you can see, if we’re accurately tracking the number of solar years since Shakespeare’s birthday then the correct anniversary date would be the 4th May and not the 23rd April.

So when should you use DateTime in Ruby and when should you use Time? Almost certainly you’ll want to use Time since your app is probably dealing with current dates and times. However, if you need to deal with dates and times in a historical context you’ll want to use DateTime to avoid making the same mistakes as UNESCO. If you also have to deal with timezones then best of luck - just bear in mind that you’ll probably be dealing with local solar times, since it wasn’t until the 19th century that the introduction of the railways necessitated the need for Standard Time and eventually timezones.

A Time object represents a date and time:

Time.new(2000, 1, 1, 0, 0, 0) # => 2000-01-01 00:00:00 -0600

Although its value can be expressed as a single numeric (see Epoch Seconds below), it can be convenient to deal with the value by parts:

t = Time.new(-2000, 1, 1, 0, 0, 0.0)
# => -2000-01-01 00:00:00 -0600
t.year # => -2000
t.month # => 1
t.mday # => 1
t.hour # => 0
t.min # => 0
t.sec # => 0
t.subsec # => 0

t = Time.new(2000, 12, 31, 23, 59, 59.5)
# => 2000-12-31 23:59:59.5 -0600
t.year # => 2000
t.month # => 12
t.mday # => 31
t.hour # => 23
t.min # => 59
t.sec # => 59
t.subsec # => (1/2)

Epoch Seconds

Epoch seconds is the exact number of seconds (including fractional subseconds) since the Unix Epoch, January 1, 1970.

You can retrieve that value exactly using method Time.to_r:

Time.at(0).to_r        # => (0/1)
Time.at(0.999999).to_r # => (9007190247541737/9007199254740992)

Other retrieval methods such as Time#to_i and Time#to_f may return a value that rounds or truncates subseconds.

Time Resolution

A Time object derived from the system clock (for example, by method Time.now) has the resolution supported by the system.

Time Internal Representation

Time implementation uses a signed 63 bit integer, Integer(T_BIGNUM), or Rational. It is a number of nanoseconds since the Epoch. The signed 63 bit integer can represent 1823-11-12 to 2116-02-20. When Integer or Rational is used (before 1823, after 2116, under nanosecond), Time works slower than when the signed 63 bit integer is used.

Ruby uses the C function “localtime” and “gmtime” to map between the number and 6-tuple (year,month,day,hour,minute,second). “localtime” is used for local time and “gmtime” is used for UTC.

Integer(T_BIGNUM) and Rational has no range limit, but the localtime and gmtime has range limits due to the C types “time_t” and “struct tm”. If that limit is exceeded, Ruby extrapolates the localtime function.

The Time class always uses the Gregorian calendar. I.e. the proleptic Gregorian calendar is used. Other calendars, such as Julian calendar, are not supported.

“time_t” can represent 1901-12-14 to 2038-01-19 if it is 32 bit signed integer, -292277022657-01-27 to 292277026596-12-05 if it is 64 bit signed integer. However “localtime” on some platforms doesn’t supports negative time_t (before 1970).

“struct tm” has tm_year member to represent years. (tm_year = 0 means the year 1900.) It is defined as int in the C standard. tm_year can represent between -2147481748 to 2147485547 if int is 32 bit.

Ruby supports leap seconds as far as if the C function “localtime” and “gmtime” supports it. They use the tz database in most Unix systems. The tz database has timezones which supports leap seconds. For example, “Asia/Tokyo” doesn’t support leap seconds but “right/Asia/Tokyo” supports leap seconds. So, Ruby supports leap seconds if the TZ environment variable is set to “right/Asia/Tokyo” in most Unix systems.

Examples

All of these examples were done using the EST timezone which is GMT-5.

Creating a New Time Instance

You can create a new instance of Time with Time.new. This will use the current system time. Time.now is an alias for this. You can also pass parts of the time to Time.new such as year, month, minute, etc. When you want to construct a time this way you must pass at least a year. If you pass the year with nothing else time will default to January 1 of that year at 00:00:00 with the current system timezone. Here are some examples:

Time.new(2002)         #=> 2002-01-01 00:00:00 -0500
Time.new(2002, 10)     #=> 2002-10-01 00:00:00 -0500
Time.new(2002, 10, 31) #=> 2002-10-31 00:00:00 -0500

You can pass a UTC offset:

Time.new(2002, 10, 31, 2, 2, 2, "+02:00") #=> 2002-10-31 02:02:02 +0200

Or a timezone object:

zone = timezone("Europe/Athens")      # Eastern European Time, UTC+2
Time.new(2002, 10, 31, 2, 2, 2, zone) #=> 2002-10-31 02:02:02 +0200

You can also use Time.local and Time.utc to infer local and UTC timezones instead of using the current system setting.

You can also create a new time using Time.at which takes the number of seconds (with subsecond) since the Unix Epoch.

Time.at(628232400) #=> 1989-11-28 00:00:00 -0500

Working with an Instance of Time

Once you have an instance of Time there is a multitude of things you can do with it. Below are some examples. For all of the following examples, we will work on the assumption that you have done the following:

t = Time.new(1993, 02, 24, 12, 0, 0, "+09:00")

Was that a monday?

t.monday? #=> false

What year was that again?

t.year #=> 1993

Was it daylight savings at the time?

t.dst? #=> false

What’s the day a year later?

t + (60*60*24*365) #=> 1994-02-24 12:00:00 +0900

How many seconds was that since the Unix Epoch?

t.to_i #=> 730522800

You can also do standard functions like compare two times.

t1 = Time.new(2010)
t2 = Time.new(2011)

t1 == t2 #=> false
t1 == t1 #=> true
t1 <  t2 #=> true
t1 >  t2 #=> false

Time.new(2010,10,31).between?(t1, t2) #=> true

What’s Here

First, what’s elsewhere. Class Time:

Here, class Time provides methods that are useful for:

Methods for Creating

Methods for Fetching

Methods for Querying

Methods for Comparing

Methods for Converting

Methods for Rounding

For the forms of argument zone, see Timezone Specifiers.

Timezone Specifiers

Certain Time methods accept arguments that specify timezones:

The value given with any of these must be one of the following (each detailed below):

Hours/Minutes Offsets

The zone value may be a string offset from UTC in the form '+HH:MM' or '-HH:MM', where:

Examples:

t = Time.utc(2000, 1, 1, 20, 15, 1) # => 2000-01-01 20:15:01 UTC
Time.at(t, in: '-23:59')            # => 1999-12-31 20:16:01 -2359
Time.at(t, in: '+23:59')            # => 2000-01-02 20:14:01 +2359

Single-Letter Offsets

The zone value may be a letter in the range 'A'..'I' or 'K'..'Z'; see List of military time zones:

t = Time.utc(2000, 1, 1, 20, 15, 1) # => 2000-01-01 20:15:01 UTC
Time.at(t, in: 'A')                 # => 2000-01-01 21:15:01 +0100
Time.at(t, in: 'I')                 # => 2000-01-02 05:15:01 +0900
Time.at(t, in: 'K')                 # => 2000-01-02 06:15:01 +1000
Time.at(t, in: 'Y')                 # => 2000-01-01 08:15:01 -1200
Time.at(t, in: 'Z')                 # => 2000-01-01 20:15:01 UTC

Integer Offsets

The zone value may be an integer number of seconds in the range -86399..86399:

t = Time.utc(2000, 1, 1, 20, 15, 1) # => 2000-01-01 20:15:01 UTC
Time.at(t, in: -86399)              # => 1999-12-31 20:15:02 -235959
Time.at(t, in: 86399)               # => 2000-01-02 20:15:00 +235959

Timezone Objects

The zone value may be an object responding to certain timezone methods, an instance of Timezone and TZInfo for example.

The timezone methods are:

A custom timezone class may have these instance methods, which will be called if defined:

Time-Like Objects

A Time-like object is a container object capable of interfacing with timezone libraries for timezone conversion.

The argument to the timezone conversion methods above will have attributes similar to Time, except that timezone related attributes are meaningless.

The objects returned by local_to_utc and utc_to_local methods of the timezone object may be of the same class as their arguments, of arbitrary object classes, or of class Integer.

For a returned class other than Integer, the class must have the following methods:

For a returned Integer, its components, decomposed in UTC, are interpreted as times in the specified timezone.

Timezone Names

If the class (the receiver of class methods, or the class of the receiver of instance methods) has find_timezone singleton method, this method is called to achieve the corresponding timezone object from a timezone name.

For example, using Timezone:

class TimeWithTimezone < Time
  require 'timezone'
  def self.find_timezone(z) = Timezone[z]
end

TimeWithTimezone.now(in: "America/New_York")        #=> 2023-12-25 00:00:00 -0500
TimeWithTimezone.new("2023-12-25 America/New_York") #=> 2023-12-25 00:00:00 -0500

Or, using TZInfo:

class TimeWithTZInfo < Time
  require 'tzinfo'
  def self.find_timezone(z) = TZInfo::Timezone.get(z)
end

TimeWithTZInfo.now(in: "America/New_York")          #=> 2023-12-25 00:00:00 -0500
TimeWithTZInfo.new("2023-12-25 America/New_York")   #=> 2023-12-25 00:00:00 -0500

You can define this method per subclasses, or on the toplevel Time class.

Use the Monitor class when you want to have a lock object for blocks with mutual exclusion.

require 'monitor'

lock = Monitor.new
lock.synchronize do
  # exclusive access
end

Raised when attempting to divide an integer by 0.

42 / 0   #=> ZeroDivisionError: divided by 0

Note that only division by an exact 0 will raise the exception:

42 /  0.0   #=> Float::INFINITY
42 / -0.0   #=> -Float::INFINITY
0  /  0.0   #=> NaN

The Comparable mixin is used by classes whose objects may be ordered. The class must define the <=> operator, which compares the receiver against another object, returning a value less than 0, returning 0, or returning a value greater than 0, depending on whether the receiver is less than, equal to, or greater than the other object. If the other object is not comparable then the <=> operator should return nil. Comparable uses <=> to implement the conventional comparison operators (<, <=, ==, >=, and >) and the method between?.

class StringSorter
  include Comparable

  attr :str
  def <=>(other)
    str.size <=> other.str.size
  end

  def initialize(str)
    @str = str
  end

  def inspect
    @str
  end
end

s1 = StringSorter.new("Z")
s2 = StringSorter.new("YY")
s3 = StringSorter.new("XXX")
s4 = StringSorter.new("WWWW")
s5 = StringSorter.new("VVVVV")

s1 < s2                       #=> true
s4.between?(s1, s3)           #=> false
s4.between?(s3, s5)           #=> true
[ s3, s2, s5, s4, s1 ].sort   #=> [Z, YY, XXX, WWWW, VVVVV]

What’s Here

Module Comparable provides these methods, all of which use method <=>:

In concurrent programming, a monitor is an object or module intended to be used safely by more than one thread. The defining characteristic of a monitor is that its methods are executed with mutual exclusion. That is, at each point in time, at most one thread may be executing any of its methods. This mutual exclusion greatly simplifies reasoning about the implementation of monitors compared to reasoning about parallel code that updates a data structure.

You can read more about the general principles on the Wikipedia page for Monitors.

Examples

Simple object.extend

require 'monitor.rb'

buf = []
buf.extend(MonitorMixin)
empty_cond = buf.new_cond

# consumer
Thread.start do
  loop do
    buf.synchronize do
      empty_cond.wait_while { buf.empty? }
      print buf.shift
    end
  end
end

# producer
while line = ARGF.gets
  buf.synchronize do
    buf.push(line)
    empty_cond.signal
  end
end

The consumer thread waits for the producer thread to push a line to buf while buf.empty?. The producer thread (main thread) reads a line from ARGF and pushes it into buf then calls empty_cond.signal to notify the consumer thread of new data.

Simple Class include

require 'monitor'

class SynchronizedArray < Array

  include MonitorMixin

  def initialize(*args)
    super(*args)
  end

  alias :old_shift :shift
  alias :old_unshift :unshift

  def shift(n=1)
    self.synchronize do
      self.old_shift(n)
    end
  end

  def unshift(item)
    self.synchronize do
      self.old_unshift(item)
    end
  end

  # other methods ...
end

SynchronizedArray implements an Array with synchronized access to items. This Class is implemented as subclass of Array which includes the MonitorMixin module.

Namespace for file utility methods for copying, moving, removing, etc.

What’s Here

First, what’s elsewhere. Module FileUtils:

Here, module FileUtils provides methods that are useful for:

Creating

Deleting

Querying

Setting

Comparing

Copying

Moving

Options

Path Arguments

Some methods in FileUtils accept path arguments, which are interpreted as paths to filesystem entries:

About the Examples

Some examples here involve trees of file entries. For these, we sometimes display trees using the tree command-line utility, which is a recursive directory-listing utility that produces a depth-indented listing of files and directories.

We use a helper method to launch the command and control the format:

def tree(dirpath = '.')
  command = "tree --noreport --charset=ascii #{dirpath}"
  system(command)
end

To illustrate:

tree('src0')
# => src0
#    |-- sub0
#    |   |-- src0.txt
#    |   `-- src1.txt
#    `-- sub1
#        |-- src2.txt
#        `-- src3.txt

Avoiding the TOCTTOU Vulnerability

For certain methods that recursively remove entries, there is a potential vulnerability called the Time-of-check to time-of-use, or TOCTTOU, vulnerability that can exist when:

To avoid that vulnerability, you can use this method to remove entries:

Also available are these methods, each of which calls FileUtils.remove_entry_secure:

Finally, this method for moving entries calls FileUtils.remove_entry_secure if the source and destination are on different file systems (which means that the “move” is really a copy and remove):

Method FileUtils.remove_entry_secure removes securely by applying a special pre-process:

WARNING: You must ensure that ALL parent directories cannot be moved by other untrusted users. For example, parent directories should not be owned by untrusted users, and should not be world writable except when the sticky bit is set.

For details of this security vulnerability, see Perl cases:

No documentation available

Timeout long-running blocks

Synopsis

require 'timeout'
status = Timeout::timeout(5) {
  # Something that should be interrupted if it takes more than 5 seconds...
}

Description

Timeout provides a way to auto-terminate a potentially long-running operation if it hasn’t finished in a fixed amount of time.

Previous versions didn’t use a module for namespacing, however timeout is provided for backwards compatibility. You should prefer Timeout.timeout instead.

Copyright

© 2000 Network Applied Communication Laboratory, Inc.

Copyright

© 2000 Information-technology Promotion Agency, Japan

Response class for Non-Authoritative Information responses (status code 203).

The Non-Authoritative Information response indicates that the server is a transforming proxy (such as a Web accelerator) that received a 200 OK response from its origin, and is returning a modified version of the origin’s response.

References:

Potentially raised when a specification is validated.

FIXME: This isn’t documented in Nutshell.

Since MonitorMixin.new_cond returns a ConditionVariable, and the example above calls while_wait and signal, this class should be documented.

ConditionVariable objects augment class Mutex. Using condition variables, it is possible to suspend while in the middle of a critical section until a resource becomes available.

Example:

mutex = Thread::Mutex.new
resource = Thread::ConditionVariable.new

a = Thread.new {
   mutex.synchronize {
     # Thread 'a' now needs the resource
     resource.wait(mutex)
     # 'a' can now have the resource
   }
}

b = Thread.new {
   mutex.synchronize {
     # Thread 'b' has finished using the resource
     resource.signal
   }
}

Response class for Partial Content responses (status code 206).

The Partial Content response indicates that the server is delivering only part of the resource (byte serving) due to a Range header in the request.

References:

Search took: 20ms  ·  Total Results: 3065