Day Of Week And Days In Month Example

lua-users home
wiki

The following code provides date functions that include calculating the number of days in a given month and the day of week for a given calendar day.

-- returns the number of days in a given month and year
-- Compatible with Lua 5.0 and 5.1.
-- from sam_lie 
function get_days_in_month(month, year)
  local days_in_month = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }   
  local d = days_in_month[month]
   
  -- check for leap year
  if (month == 2) then
    if (math.mod(year,4) == 0) then
     if (math.mod(year,100) == 0)then                
      if (math.mod(year,400) == 0) then                    
          d = 29
      end
     else                
      d = 29
     end
    end
  end

  return d  
end

-- RiciLake comments:
-- It would be better to create the days_in_month table outside the
-- function, like this (using % so it only works in Lua 5.1)
do
  local days_in_month = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }

  local function is_leap_year(year)
    return year % 4 == 0 and (year % 100 ~= 0 or year % 400 == 0)
  end

  function get_days_in_month(month, year)
    if month == 2 and is_leap_year(year) then
      return 29
    else
      return days_in_month[month]
    end
  end
end

-- It's also possible to avoid the table altogether:
  function get_days_in_month(month, year)
    return month == 2 and is_leap_year(year) and 29
           or ("\31\28\31\30\31\30\31\31\30\31\30\31"):byte(month)
  end

Alternate version - by RichardWarburton - returns number of days in a given month and year by using built in Lua libs. [*1]

function get_days_in_month(mnth, yr)
  return os.date('*t',os.time{year=yr,month=mnth+1,day=0})['day']
end

-- returns the day of week integer and the name of the week
-- Compatible with Lua 5.0 and 5.1.
-- from sam_lie 
function get_day_of_week(dd, mm, yy) 
  local days = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" }

  local mmx = mm

  if (mm == 1) then  mmx = 13; yy = yy-1  end
  if (mm == 2) then  mmx = 14; yy = yy-1  end

  local val8 = dd + (mmx*2) +  math.floor(((mmx+1)*3)/5)   + yy + math.floor(yy/4)  - math.floor(yy/100)  + math.floor(yy/400) + 2
  local val9 = math.floor(val8/7)
  local dw = val8-(val9*7) 

  if (dw == 0) then
    dw = 7
  end

  return dw, days[dw]
end

-- alternate version - returns the day of week integer and the name of the week
-- Compatible with Lua 5.0 and 5.1.
-- from http://richard.warburton.it 
function get_day_of_week(dd, mm, yy)
  dw=os.date('*t',os.time{year=yy,month=mm,day=dd})['wday']
  return dw,({"Sun","Mon","Tue","Wed","Thu","Fri","Sat" })[dw]
end

-- given a string date of '2006-12-31' breaks it down to integer yy, mm and dd
-- Compatible with Lua 5.0 and 5.1.
-- from sam_lie 
function get_date_parts(date_str)
  local iyy, imm, idd 

  if (date_str) then
    x = string.gsub(date_str, "(%d+)-(%d+)-(%d+)", function (yy,mm,dd)    
        iyy = tonumber(yy)
        imm = tonumber(mm)
        idd = tonumber(dd)
      end)
  end

  return iyy, imm, idd
end

-- alternate version - given a string date of '2006-12-31' breaks it down to integer yy, mm and dd
-- Compatible with Lua 5.0 and 5.1.
-- from http://richard.warburton.it 
function get_date_parts(date_str)
  _,_,y,m,d=string.find(date_str, "(%d+)-(%d+)-(%d+)")
  return tonumber(y),tonumber(m),tonumber(d)
end

Here is a test suite.

assert(get_days_in_month(1,2007) == 31)
assert(get_days_in_month(2,2007) == 28)
assert(get_days_in_month(3,2007) == 31)
assert(get_days_in_month(4,2007) == 30)
assert(get_days_in_month(5,2007) == 31)
assert(get_days_in_month(6,2007) == 30)
assert(get_days_in_month(7,2007) == 31)
assert(get_days_in_month(8,2007) == 31)
assert(get_days_in_month(9,2007) == 30)
assert(get_days_in_month(10,2007) == 31)
assert(get_days_in_month(11,2007) == 30)
assert(get_days_in_month(12,2007) == 31)
-- See http://en.wikipedia.org/wiki/Leap_year
assert(get_days_in_month(2,2008) == 29) -- leap year
assert(get_days_in_month(2,2000) == 29) -- leap year

-- note: this can fail in Richard's implementation. [*1]
assert(get_days_in_month(2,1900) == 28) -- not leap year

local i, n = get_day_of_week(1,1,2007)
assert(i == 2 and n == 'Mon')
assert(get_day_of_week(1,1,2007) == 2)
assert(get_day_of_week(2,1,2007) == 3)
assert(get_day_of_week(3,1,2007) == 4)
assert(get_day_of_week(4,1,2007) == 5)
assert(get_day_of_week(5,1,2007) == 6)
assert(get_day_of_week(6,1,2007) == 7)
assert(get_day_of_week(7,1,2007) == 1)
assert(get_day_of_week(1,2,2007) == 5)

See also [Wikipedia: Calculating the day of the week]

[*1] LuaList:2007-01/msg00100.html

The following code returns a table containing {year=years, month=months, day=days, hour=hours, min=minutes, sec=seconds} representing the time between two dates created by os.time - by RichardWarburton.

local timeDiff = function(t2,t1)
	local d1,d2,carry,diff = os.date('*t',t1),os.date('*t',t2),false,{}
	local colMax = {60,60,24,os.date('*t',os.time{year=d1.year,month=d1.month+1,day=0}).day,12}
	d2.hour = d2.hour - (d2.isdst and 1 or 0) + (d1.isdst and 1 or 0) -- handle dst
	for i,v in ipairs({'sec','min','hour','day','month','year'}) do 
		diff[v] = d2[v] - d1[v] + (carry and -1 or 0)
		carry = diff[v] < 0
		if carry then diff[v] = diff[v] + colMax[i] end
	end
	return diff
end

local td=timeDiff(os.time{year=2007,month=10,day=5,hour=10,min=10,sec=5},os.time{year=2006,month=11,day=6,hour=10,min=10,sec=5})
for i,v in pairs(td) do print(i,v) end

min     0
day     29
month   10
sec     0
hour    1
year    0

RecentChanges · preferences
edit · history
Last edited April 24, 2007 1:44 pm GMT (diff)