webmcp

diff libraries/atom/atom.lua @ 106:bbfbbddf13ad

Support for intervals
author jbe
date Sun Nov 04 04:55:22 2012 +0100 (2012-11-04)
parents bdebade717d3
children 6b435d3c0b14
line diff
     1.1 --- a/libraries/atom/atom.lua	Sun Nov 04 04:54:54 2012 +0100
     1.2 +++ b/libraries/atom/atom.lua	Sun Nov 04 04:55:22 2012 +0100
     1.3 @@ -1015,7 +1015,7 @@
     1.4      error("Left operand of '-' operator has wrong type.")
     1.5    end
     1.6    if getmetatable(value2) == date then
     1.7 -    return value1.jd - value2.jd  -- TODO: transform to interval
     1.8 +    return value1.jd - value2.jd
     1.9    elseif type(value2) == "number" then
    1.10      return date(value1.jd - value2)
    1.11    else
    1.12 @@ -1299,7 +1299,7 @@
    1.13      error("Left operand of '-' operator has wrong type.")
    1.14    end
    1.15    if getmetatable(value2) == timestamp then
    1.16 -    return value1.tsec - value2.tsec  -- TODO: transform to interval
    1.17 +    return value1.tsec - value2.tsec
    1.18    elseif type(value2) == "number" then
    1.19      return timestamp(value1.tsec - value2)
    1.20    else
    1.21 @@ -1508,7 +1508,7 @@
    1.22      error("Left operand of '-' operator has wrong type.")
    1.23    end
    1.24    if getmetatable(value2) == time then
    1.25 -    return value1.dsec - value2.dsec  -- TODO: transform to interval
    1.26 +    return value1.dsec - value2.dsec
    1.27    elseif type(value2) == "number" then
    1.28      return time((value1.dsec - value2) % 86400)
    1.29    else
    1.30 @@ -1539,4 +1539,154 @@
    1.31  
    1.32  
    1.33  
    1.34 +--------------
    1.35 +-- interval --
    1.36 +--------------
    1.37 +
    1.38 +interval = create_new_type("interval")
    1.39 +
    1.40 +--[[--
    1.41 +atom.interval.invalid
    1.42 +
    1.43 +Value representing an invalid interval.
    1.44 +
    1.45 +--]]--
    1.46 +interval.invalid = interval:_create{
    1.47 +  years = not_a_number, months = not_a_number, days = not_a_number,
    1.48 +  hours = not_a_number, minutes = not_a_number, seconds = not_a_number,
    1.49 +  hms_seconds = not_a_number,
    1.50 +  invalid = true
    1.51 +}
    1.52 +--//--
    1.53 +
    1.54 +--[[--
    1.55 +t =                 -- time based on given data
    1.56 +atom.interval:new{
    1.57 +  years    = years,
    1.58 +  months   = months,
    1.59 +  days     = days,
    1.60 +  hours    = hours,
    1.61 +  minutes  = minutes,
    1.62 +  seconds  = seconds
    1.63 +}
    1.64 +
    1.65 +This method returns a new time value, based on given data.
    1.66 +
    1.67 +--]]--
    1.68 +function interval:new(args)
    1.69 +  local args = args
    1.70 +  if type(args) == "number" then args = { seconds = args } end
    1.71 +  if type(args) == "table" then
    1.72 +    if
    1.73 +      (type(args.years)   == "number" or not args.years  ) and
    1.74 +      (type(args.months)  == "number" or not args.months ) and
    1.75 +      (type(args.days)    == "number" or not args.days   ) and
    1.76 +      (type(args.hours)   == "number" or not args.hours  ) and
    1.77 +      (type(args.minutes) == "number" or not args.minutes) and
    1.78 +      (type(args.seconds) == "number" or not args.seconds)
    1.79 +    then
    1.80 +      local years   = args.years   and tonumber(args.years)   or 0
    1.81 +      local months  = args.months  and tonumber(args.months)  or 0
    1.82 +      local days    = args.days    and tonumber(args.days)    or 0
    1.83 +      local hours   = args.hours   and tonumber(args.hours)   or 0
    1.84 +      local minutes = args.minutes and tonumber(args.minutes) or 0
    1.85 +      local seconds = args.seconds and tonumber(args.seconds) or 0
    1.86 +      if not (
    1.87 +        is_integer(years) and is_integer(months) and is_integer(days) and
    1.88 +        is_integer(hours) and is_integer(minutes) and is_integer(seconds)
    1.89 +      ) then
    1.90 +        return interval.invalid
    1.91 +      end
    1.92 +      local hms_seconds = 3600 * hours + 60 * minutes + seconds
    1.93 +      if not is_integer(hms_seconds) then return interval.invalid end
    1.94 +      local hms_negative = false
    1.95 +      if hms_seconds < 0 then
    1.96 +        hms_negative = true
    1.97 +        hms_seconds = -hms_seconds
    1.98 +        if not is_integer(hms_seconds) then return interval.invalid end
    1.99 +      end
   1.100 +      hours = math.floor(hms_seconds / 3600)
   1.101 +      minutes = math.floor(hms_seconds / 60) % 60
   1.102 +      seconds = hms_seconds % 60
   1.103 +      if hms_negative then
   1.104 +        hours       = -hours
   1.105 +        minutes     = -minutes
   1.106 +        seconds     = -seconds
   1.107 +        hms_seconds = -hms_seconds
   1.108 +      end
   1.109 +      return interval:_create{
   1.110 +        years = years, months = months, days = days,
   1.111 +        hours = hours, minutes = minutes, seconds = seconds,
   1.112 +        hms_seconds = hms_seconds,
   1.113 +      }
   1.114 +    end
   1.115 +  end
   1.116 +  error("Invalid arguments passed to interval constructor.")
   1.117 +end
   1.118 +--//--
   1.119 +
   1.120 +--[[--
   1.121 +t =                  -- interval represented by the string
   1.122 +atom.interval:load(
   1.123 +  string             -- string representing an interval
   1.124 +)
   1.125 +
   1.126 +This method returns an interval represented by the given string.
   1.127 +
   1.128 +--]]--
   1.129 +function interval:load(str)
   1.130 +  if str == nil or str == "" then
   1.131 +    return nil
   1.132 +  elseif type(str) ~= "string" then
   1.133 +    error("String expected")
   1.134 +  else
   1.135 +    local years, months, days, hours, minutes, seconds = string.match(
   1.136 +      str,
   1.137 +      "^(%-?[0-9]+) years (%-?[0-9]+) months (%-?[0-9]+) days (%-?[0-9]+) hours (%-?[0-9]+) minutes (%-?[0-9]+) seconds$"
   1.138 +    )
   1.139 +    return interval:new{
   1.140 +      years   = tonumber(years),
   1.141 +      months  = tonumber(months),
   1.142 +      days    = tonumber(days),
   1.143 +      hours   = tonumber(hours),
   1.144 +      minutes = tonumber(minutes),
   1.145 +      seconds = tonumber(seconds)
   1.146 +    }
   1.147 +  end
   1.148 +end
   1.149 +--//--
   1.150 +
   1.151 +function interval:__tostring()
   1.152 +  if self.invalid then
   1.153 +    return "invalid_interval"
   1.154 +  else
   1.155 +    return string.format(
   1.156 +      "%i years %i months %i days %i hours %i minutes %i seconds",
   1.157 +      self.years, self.months, self.days, self.hours, self.minutes, self.seconds
   1.158 +    )
   1.159 +  end
   1.160 +end
   1.161 +
   1.162 +function interval.__eq(value1, value2)
   1.163 +  if value1.invalid or value2.invalid then
   1.164 +    return false
   1.165 +  else
   1.166 +    return (
   1.167 +      value1.years  == value2.years  and
   1.168 +      value1.months == value2.months and
   1.169 +      value1.days   == value2.days   and
   1.170 +      value1.hms_seconds == value2.hms_seconds
   1.171 +    )
   1.172 +  end
   1.173 +end
   1.174 +
   1.175 +function interval:__unm()
   1.176 +  return self.new{
   1.177 +    years = -self.years, months = -self.months, days = -self.days,
   1.178 +    hours = -self.hours, minutes = -self.minutes, seconds = -self.seconds
   1.179 +  }
   1.180 +end
   1.181 +
   1.182 +
   1.183 +
   1.184  return _M

Impressum / About Us